Skip to main content

microclaw_engine/internal/observability/
sdk.rs

1use opentelemetry::KeyValue;
2use opentelemetry_sdk::Resource;
3use serde_yaml::{Mapping, Value};
4
5#[derive(Clone)]
6pub struct OTelSdkContext {
7    pub resource: Resource,
8    pub service_name: String,
9}
10
11impl OTelSdkContext {
12    pub fn from_observability(map: &Mapping) -> Self {
13        let service_name = get_trimmed(map, "service_name")
14            .unwrap_or("microclaw")
15            .to_string();
16        let resource = Resource::builder_empty()
17            .with_attributes([KeyValue::new("service.name", service_name.clone())])
18            .build();
19        Self {
20            resource,
21            service_name,
22        }
23    }
24}
25
26pub fn get_trimmed<'a>(map: &'a Mapping, key: &str) -> Option<&'a str> {
27    map.get(Value::String(key.to_string()))
28        .and_then(Value::as_str)
29        .map(str::trim)
30        .filter(|s| !s.is_empty())
31}
32
33pub fn get_u64(map: &Mapping, key: &str) -> Option<u64> {
34    map.get(Value::String(key.to_string()))
35        .and_then(Value::as_u64)
36}
37
38pub fn get_bool(map: &Mapping, key: &str) -> Option<bool> {
39    map.get(Value::String(key.to_string()))
40        .and_then(Value::as_bool)
41}
42
43pub fn parse_headers(map: &Mapping) -> Vec<(String, String)> {
44    let mut headers = Vec::new();
45    if let Some(hmap) = map
46        .get(Value::String("otlp_headers".to_string()))
47        .and_then(Value::as_mapping)
48    {
49        for (k, v) in hmap {
50            let Some(key) = k.as_str() else {
51                continue;
52            };
53            let Some(val) = v.as_str() else {
54                continue;
55            };
56            headers.push((key.to_string(), val.to_string()));
57        }
58    }
59    headers
60}