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.
80#[derive(Debug)]
81pub(crate) enum OtlpProtocol {
82    Grpc,
83    HttpProtobuf,
84    HttpJson,
85}
86
87impl OtlpProtocol {
88    /// Returns the protocol to be used for exporting traces as defined by the environment.
89    pub(crate) fn traces_protocol_from_env() -> Self {
90        Self::protocol_from_env(
91            std::env::var(OTEL_EXPORTER_OTLP_TRACES_PROTOCOL),
92            std::env::var(OTEL_EXPORTER_OTLP_PROTOCOL),
93        )
94    }
95
96    /// Returns the protocol to be used for exporting metrics as defined by the environment.
97    pub(crate) fn metrics_protocol_from_env() -> Self {
98        Self::protocol_from_env(
99            std::env::var(OTEL_EXPORTER_OTLP_METRICS_PROTOCOL),
100            std::env::var(OTEL_EXPORTER_OTLP_PROTOCOL),
101        )
102    }
103
104    /// Returns the protocol to be used for exporting logs as defined by the environment.
105    pub(crate) fn logs_protocol_from_env() -> Self {
106        Self::protocol_from_env(
107            std::env::var(OTEL_EXPORTER_OTLP_LOGS_PROTOCOL),
108            std::env::var(OTEL_EXPORTER_OTLP_PROTOCOL),
109        )
110    }
111
112    fn protocol_from_env(
113        specific_protocol: Result<String, VarError>,
114        general_protocol: Result<String, VarError>,
115    ) -> Self {
116        let protocol =
117            specific_protocol.unwrap_or(general_protocol.unwrap_or("http/protobuf".to_string()));
118
119        static WARN_ONCE: std::sync::Once = std::sync::Once::new();
120
121        match protocol.as_str() {
122            "grpc" => Self::Grpc,
123            "http/protobuf" => Self::HttpProtobuf,
124            "http/json" => Self::HttpJson,
125            s => {
126                WARN_ONCE.call_once(|| {
127                    terminal::warn!(
128                        "'{s}' is not a valid OTLP protocol, defaulting to http/protobuf"
129                    );
130                });
131                Self::HttpProtobuf
132            }
133        }
134    }
135}