spin_telemetry/
env.rs

1use std::env::VarError;
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
15/// Returns a boolean indicating if the OTEL tracing layer should be enabled.
16///
17/// It is considered enabled if any of the following environment variables are set and not empty:
18/// - `OTEL_EXPORTER_OTLP_ENDPOINT`
19/// - `OTEL_EXPORTER_OTLP_TRACES_ENDPOINT`
20///
21/// Note that this is overridden if OTEL_SDK_DISABLED is set and not empty.
22pub(crate) 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
29/// Returns a boolean indicating if the OTEL metrics layer should be enabled.
30///
31/// It is considered enabled if any of the following environment variables are set and not empty:
32/// - `OTEL_EXPORTER_OTLP_ENDPOINT`
33/// - `OTEL_EXPORTER_OTLP_METRICS_ENDPOINT`
34///
35/// Note that this is overridden if OTEL_SDK_DISABLED is set and not empty.
36pub(crate) 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
43/// Returns a boolean indicating if the OTEL log layer should be enabled.
44///
45/// It is considered enabled if any of the following environment variables are set and not empty:
46/// - `OTEL_EXPORTER_OTLP_ENDPOINT`
47/// - `OTEL_EXPORTER_OTLP_LOGS_ENDPOINT`
48///
49/// Note that this is overridden if OTEL_SDK_DISABLED is set and not empty.
50pub(crate) fn otel_logs_enabled() -> bool {
51    any_vars_set(&[
52        OTEL_EXPORTER_OTLP_ENDPOINT,
53        OTEL_EXPORTER_OTLP_LOGS_ENDPOINT,
54    ]) && !otel_sdk_disabled()
55}
56
57/// Returns a boolean indicating if the compatibility layer that emits tracing events from
58/// applications logs should be disabled.
59///
60/// It is considered disabled if the environment variable `SPIN_DISABLED_LOG_TO_TRACING` is set and not
61/// empty. By default the features is enabled.
62pub(crate) fn spin_disable_log_to_tracing() -> bool {
63    any_vars_set(&[SPIN_DISABLE_LOG_TO_TRACING])
64}
65
66fn any_vars_set(enabling_vars: &[&str]) -> bool {
67    enabling_vars
68        .iter()
69        .any(|key| std::env::var_os(key).is_some_and(|val| !val.is_empty()))
70}
71
72/// Returns a boolean indicating if the OTEL SDK should be disabled for all signals.
73///
74/// It is considered disabled if the environment variable `OTEL_SDK_DISABLED` is set and not empty.
75pub(crate) fn otel_sdk_disabled() -> bool {
76    std::env::var_os(OTEL_SDK_DISABLED).is_some_and(|val| !val.is_empty())
77}
78
79/// The protocol to use for OTLP exporter.
80pub(crate) enum OtlpProtocol {
81    Grpc,
82    HttpProtobuf,
83    HttpJson,
84}
85
86impl OtlpProtocol {
87    /// Returns the protocol to be used for exporting traces as defined by the environment.
88    pub(crate) fn traces_protocol_from_env() -> Self {
89        Self::protocol_from_env(
90            std::env::var(OTEL_EXPORTER_OTLP_TRACES_PROTOCOL),
91            std::env::var(OTEL_EXPORTER_OTLP_PROTOCOL),
92        )
93    }
94
95    /// Returns the protocol to be used for exporting metrics as defined by the environment.
96    pub(crate) fn metrics_protocol_from_env() -> Self {
97        Self::protocol_from_env(
98            std::env::var(OTEL_EXPORTER_OTLP_METRICS_PROTOCOL),
99            std::env::var(OTEL_EXPORTER_OTLP_PROTOCOL),
100        )
101    }
102
103    /// Returns the protocol to be used for exporting logs as defined by the environment.
104    pub(crate) fn logs_protocol_from_env() -> Self {
105        Self::protocol_from_env(
106            std::env::var(OTEL_EXPORTER_OTLP_LOGS_PROTOCOL),
107            std::env::var(OTEL_EXPORTER_OTLP_PROTOCOL),
108        )
109    }
110
111    fn protocol_from_env(
112        specific_protocol: Result<String, VarError>,
113        general_protocol: Result<String, VarError>,
114    ) -> Self {
115        let protocol =
116            specific_protocol.unwrap_or(general_protocol.unwrap_or("http/protobuf".to_string()));
117
118        static WARN_ONCE: std::sync::Once = std::sync::Once::new();
119
120        match protocol.as_str() {
121            "grpc" => Self::Grpc,
122            "http/protobuf" => Self::HttpProtobuf,
123            "http/json" => Self::HttpJson,
124            s => {
125                WARN_ONCE.call_once(|| {
126                    terminal::warn!(
127                        "'{s}' is not a valid OTLP protocol, defaulting to http/protobuf"
128                    );
129                });
130                Self::HttpProtobuf
131            }
132        }
133    }
134}