Skip to main content

spin_telemetry/
detector.rs

1use std::env;
2
3use opentelemetry::{Key, KeyValue, Value};
4use opentelemetry_sdk::{
5    Resource,
6    resource::{EnvResourceDetector, ResourceDetector},
7};
8use opentelemetry_semantic_conventions::attribute as otel_attribute;
9
10const OTEL_SERVICE_NAME: &str = "OTEL_SERVICE_NAME";
11
12/// Custom resource detector for Spin relevant attributes service.name and service.version.
13///
14/// To set service.name this detector will first try `OTEL_SERVICE_NAME` env. If it's not available,
15/// then it will check the `OTEL_RESOURCE_ATTRIBUTES` env and see if it contains `service.name`
16/// resource. If it's also not available, it will use `spin`.
17///
18/// To set service.version, it will use the spin_version passed in new.
19#[derive(Debug)]
20pub struct SpinResourceDetector {
21    spin_version: String,
22}
23
24impl SpinResourceDetector {
25    /// Create a new instance of SpinResourceDetector.
26    pub fn new(spin_version: String) -> Self {
27        SpinResourceDetector { spin_version }
28    }
29}
30
31impl ResourceDetector for SpinResourceDetector {
32    fn detect(&self) -> Resource {
33        let service_name = env::var(OTEL_SERVICE_NAME)
34            .ok()
35            .filter(|s| !s.is_empty())
36            .map(Value::from)
37            .or_else(|| {
38                EnvResourceDetector::new()
39                    .detect()
40                    .get(&Key::new(otel_attribute::SERVICE_NAME))
41            })
42            .unwrap_or_else(|| "spin".into());
43        Resource::builder()
44            .with_attributes(vec![
45                KeyValue::new(otel_attribute::SERVICE_NAME, service_name),
46                KeyValue::new(otel_attribute::SERVICE_VERSION, self.spin_version.clone()),
47            ])
48            .build()
49    }
50}