spin_telemetry/
detector.rs

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