Skip to main content

o_sfu/config/
telemetry.rs

1use std::time::Duration;
2
3use anyhow::{Result, anyhow, ensure};
4use o_sfu_core::server::transport::MediaTransportConfig;
5pub use o_sfu_telemetry::{
6    DEFAULT_MEDIA_QUALITY_INTERVAL, DEFAULT_TELEMETRY_DEPLOYMENT_ENVIRONMENT,
7    DEFAULT_TELEMETRY_SERVICE_NAME, TelemetryConfig, TelemetryLogFormat, TelemetryResource,
8    TraceExportConfig,
9};
10
11use super::env::{Env, EnvParse, EnvValue, non_empty};
12
13const OTEL_TRACING_FEATURE_NAME: &str = "otel-tracing";
14const MEDIA_QUALITY_INTERVAL_ENV: &str = "TELEMETRY_MEDIA_QUALITY_INTERVAL_MS";
15
16impl EnvParse for TelemetryLogFormat {
17    fn parse(value: EnvValue) -> Result<Self> {
18        let key = value.key;
19        match value.raw.as_str() {
20            "compact" => Ok(Self::Compact),
21            "json" => Ok(Self::Json),
22            _ => Err(anyhow!("{key} must be either `compact` or `json`")),
23        }
24    }
25}
26
27pub(super) fn load_telemetry_config(env: &Env<'_>) -> Result<TelemetryConfig> {
28    let log_format = env
29        .var("TELEMETRY_LOG_FORMAT")
30        .default(TelemetryLogFormat::default())?;
31    let otlp_endpoint = env
32        .var("TELEMETRY_OTLP_ENDPOINT")
33        .check(non_empty)
34        .optional()?;
35    if !cfg!(feature = "otel-tracing") && otlp_endpoint.is_some() {
36        return Err(anyhow!(
37            "TELEMETRY_OTLP_ENDPOINT requires the `{OTEL_TRACING_FEATURE_NAME}` cargo feature"
38        ));
39    }
40    let media_quality_interval_ms = env
41        .var(MEDIA_QUALITY_INTERVAL_ENV)
42        .check(|key, value| {
43            ensure!(
44                Duration::from_millis(value) <= MediaTransportConfig::MAX_MEDIA_QUALITY_INTERVAL,
45                "{key} must not exceed 86400000 milliseconds"
46            );
47            Ok(value)
48        })
49        .default(u64::try_from(DEFAULT_MEDIA_QUALITY_INTERVAL.as_millis()).unwrap_or(5_000))?;
50    let service_name = env
51        .var("TELEMETRY_SERVICE_NAME")
52        .check(non_empty)
53        .optional()?;
54    let deployment_environment = env
55        .var("TELEMETRY_DEPLOYMENT_ENVIRONMENT")
56        .check(non_empty)
57        .optional()?;
58    let service_instance_id = env
59        .var("TELEMETRY_SERVICE_INSTANCE_ID")
60        .check(non_empty)
61        .optional()?;
62    Ok(TelemetryConfig {
63        log_format,
64        resource: TelemetryResource {
65            service_name: service_name.unwrap_or_else(|| DEFAULT_TELEMETRY_SERVICE_NAME.to_owned()),
66            deployment_environment: deployment_environment
67                .unwrap_or_else(|| DEFAULT_TELEMETRY_DEPLOYMENT_ENVIRONMENT.to_owned()),
68            service_instance_id,
69        },
70        trace_export: TraceExportConfig { otlp_endpoint },
71        media_quality_interval: (media_quality_interval_ms > 0)
72            .then(|| Duration::from_millis(media_quality_interval_ms)),
73    })
74}
75
76#[cfg(test)]
77#[path = "TESTS/telemetry.rs"]
78mod tests;