spin_telemetry/
detector.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
use std::{env, time::Duration};

use opentelemetry::{Key, KeyValue, Value};
use opentelemetry_sdk::{
    resource::{EnvResourceDetector, ResourceDetector},
    Resource,
};

const OTEL_SERVICE_NAME: &str = "OTEL_SERVICE_NAME";

/// Custom resource detector for Spin relevant attributes service.name and service.version.
///
/// To set service.name this detector will first try `OTEL_SERVICE_NAME` env. If it's not available,
/// then it will check the `OTEL_RESOURCE_ATTRIBUTES` env and see if it contains `service.name`
/// resource. If it's also not available, it will use `spin`.
///
/// To set service.version, it will use the spin_version passed in new.
#[derive(Debug)]
pub struct SpinResourceDetector {
    spin_version: String,
}

impl SpinResourceDetector {
    /// Create a new instance of SpinResourceDetector.
    pub fn new(spin_version: String) -> Self {
        SpinResourceDetector { spin_version }
    }
}

impl ResourceDetector for SpinResourceDetector {
    fn detect(&self, _timeout: Duration) -> Resource {
        let service_name = env::var(OTEL_SERVICE_NAME)
            .ok()
            .filter(|s| !s.is_empty())
            .map(Value::from)
            .or_else(|| {
                EnvResourceDetector::new()
                    .detect(Duration::from_secs(0))
                    .get(Key::new("service.name"))
            })
            .unwrap_or_else(|| "spin".into());
        Resource::new(vec![
            KeyValue::new("service.name", service_name),
            KeyValue::new("service.version", self.spin_version.clone()),
        ])
    }
}