1use std::{env::VarError, sync::OnceLock};
2
3use opentelemetry_otlp::{
4 OTEL_EXPORTER_OTLP_ENDPOINT, OTEL_EXPORTER_OTLP_LOGS_ENDPOINT,
5 OTEL_EXPORTER_OTLP_METRICS_ENDPOINT, OTEL_EXPORTER_OTLP_PROTOCOL,
6 OTEL_EXPORTER_OTLP_TRACES_ENDPOINT,
7};
8
9const OTEL_SDK_DISABLED: &str = "OTEL_SDK_DISABLED";
10const OTEL_EXPORTER_OTLP_TRACES_PROTOCOL: &str = "OTEL_EXPORTER_OTLP_TRACES_PROTOCOL";
11const OTEL_EXPORTER_OTLP_METRICS_PROTOCOL: &str = "OTEL_EXPORTER_OTLP_METRICS_PROTOCOL";
12const OTEL_EXPORTER_OTLP_LOGS_PROTOCOL: &str = "OTEL_EXPORTER_OTLP_LOGS_PROTOCOL";
13const SPIN_DISABLE_LOG_TO_TRACING: &str = "SPIN_DISABLE_LOG_TO_TRACING";
14
15pub fn otel_tracing_enabled() -> bool {
23 any_vars_set(&[
24 OTEL_EXPORTER_OTLP_ENDPOINT,
25 OTEL_EXPORTER_OTLP_TRACES_ENDPOINT,
26 ]) && !otel_sdk_disabled()
27}
28
29pub fn otel_metrics_enabled() -> bool {
37 any_vars_set(&[
38 OTEL_EXPORTER_OTLP_ENDPOINT,
39 OTEL_EXPORTER_OTLP_METRICS_ENDPOINT,
40 ]) && !otel_sdk_disabled()
41}
42
43pub fn otel_logs_enabled() -> bool {
53 static ENABLED: OnceLock<bool> = OnceLock::new();
54 *ENABLED.get_or_init(|| {
55 any_vars_set(&[
56 OTEL_EXPORTER_OTLP_ENDPOINT,
57 OTEL_EXPORTER_OTLP_LOGS_ENDPOINT,
58 ]) && !otel_sdk_disabled()
59 })
60}
61
62pub fn spin_disable_log_to_tracing() -> bool {
68 any_vars_set(&[SPIN_DISABLE_LOG_TO_TRACING])
69}
70
71fn any_vars_set(enabling_vars: &[&str]) -> bool {
72 enabling_vars
73 .iter()
74 .any(|key| std::env::var_os(key).is_some_and(|val| !val.is_empty()))
75}
76
77pub fn otel_sdk_disabled() -> bool {
81 std::env::var_os(OTEL_SDK_DISABLED).is_some_and(|val| !val.is_empty())
82}
83
84#[derive(Debug)]
86pub enum OtlpProtocol {
87 Grpc,
88 HttpProtobuf,
89 HttpJson,
90}
91
92impl OtlpProtocol {
93 pub fn traces_protocol_from_env() -> Self {
95 Self::protocol_from_env(
96 std::env::var(OTEL_EXPORTER_OTLP_TRACES_PROTOCOL),
97 std::env::var(OTEL_EXPORTER_OTLP_PROTOCOL),
98 )
99 }
100
101 pub fn metrics_protocol_from_env() -> Self {
103 Self::protocol_from_env(
104 std::env::var(OTEL_EXPORTER_OTLP_METRICS_PROTOCOL),
105 std::env::var(OTEL_EXPORTER_OTLP_PROTOCOL),
106 )
107 }
108
109 pub fn logs_protocol_from_env() -> Self {
111 Self::protocol_from_env(
112 std::env::var(OTEL_EXPORTER_OTLP_LOGS_PROTOCOL),
113 std::env::var(OTEL_EXPORTER_OTLP_PROTOCOL),
114 )
115 }
116
117 fn protocol_from_env(
118 specific_protocol: Result<String, VarError>,
119 general_protocol: Result<String, VarError>,
120 ) -> Self {
121 let protocol =
122 specific_protocol.unwrap_or(general_protocol.unwrap_or("http/protobuf".to_string()));
123
124 static WARN_ONCE: std::sync::Once = std::sync::Once::new();
125
126 match protocol.as_str() {
127 "grpc" => Self::Grpc,
128 "http/protobuf" => Self::HttpProtobuf,
129 "http/json" => Self::HttpJson,
130 s => {
131 WARN_ONCE.call_once(|| {
132 terminal::warn!(
133 "'{s}' is not a valid OTLP protocol, defaulting to http/protobuf"
134 );
135 });
136 Self::HttpProtobuf
137 }
138 }
139 }
140}