opentelemetry_resource_detectors/
host.rsuse opentelemetry::KeyValue;
use opentelemetry_sdk::resource::ResourceDetector;
use opentelemetry_sdk::Resource;
use std::env::consts::ARCH;
#[cfg(target_os = "linux")]
use std::fs::read_to_string;
#[cfg(target_os = "linux")]
use std::path::Path;
#[cfg(target_os = "macos")]
use std::process::Command;
use std::time::Duration;
pub struct HostResourceDetector {
    host_id_detect: fn() -> Option<String>,
}
impl ResourceDetector for HostResourceDetector {
    fn detect(&self, _timeout: Duration) -> Resource {
        Resource::new(
            [
                (self.host_id_detect)().map(|host_id| {
                    KeyValue::new(
                        opentelemetry_semantic_conventions::attribute::HOST_ID,
                        host_id,
                    )
                }),
                Some(KeyValue::new(
                    opentelemetry_semantic_conventions::attribute::HOST_ARCH,
                    ARCH,
                )),
            ]
            .into_iter()
            .flatten(),
        )
    }
}
#[cfg(target_os = "linux")]
fn host_id_detect() -> Option<String> {
    let machine_id_path = Path::new("/etc/machine-id");
    let dbus_machine_id_path = Path::new("/var/lib/dbus/machine-id");
    read_to_string(machine_id_path)
        .or_else(|_| read_to_string(dbus_machine_id_path))
        .ok()
}
#[cfg(target_os = "macos")]
fn host_id_detect() -> Option<String> {
    let output = Command::new("ioreg")
        .arg("-rd1")
        .arg("-c")
        .arg("IOPlatformExpertDevice")
        .output()
        .ok()?
        .stdout;
    let output = String::from_utf8(output).ok()?;
    let line = output
        .lines()
        .find(|line| line.contains("IOPlatformUUID"))?;
    Some(line.split_once('=')?.1.trim().trim_matches('"').to_owned())
}
#[cfg(not(any(target_os = "linux", target_os = "macos")))]
fn host_id_detect() -> Option<String> {
    None
}
impl Default for HostResourceDetector {
    fn default() -> Self {
        Self { host_id_detect }
    }
}
#[cfg(test)]
mod tests {
    use super::HostResourceDetector;
    use opentelemetry::{Key, Value};
    use opentelemetry_sdk::resource::ResourceDetector;
    use std::time::Duration;
    #[cfg(target_os = "linux")]
    #[test]
    fn test_host_resource_detector_linux() {
        let resource = HostResourceDetector::default().detect(Duration::from_secs(0));
        assert_eq!(resource.len(), 2);
        assert!(resource
            .get(Key::from_static_str(
                opentelemetry_semantic_conventions::attribute::HOST_ID
            ))
            .is_some());
        assert!(resource
            .get(Key::from_static_str(
                opentelemetry_semantic_conventions::attribute::HOST_ARCH
            ))
            .is_some())
    }
    #[cfg(target_os = "macos")]
    #[test]
    fn test_host_resource_detector_macos() {
        let resource = HostResourceDetector::default().detect(Duration::from_secs(0));
        dbg!(&resource);
        assert_eq!(resource.len(), 2);
        assert!(resource
            .get(Key::from_static_str(
                opentelemetry_semantic_conventions::attribute::HOST_ID
            ))
            .is_some());
        assert!(resource
            .get(Key::from_static_str(
                opentelemetry_semantic_conventions::attribute::HOST_ARCH
            ))
            .is_some())
    }
    #[test]
    fn test_resource_host_arch_value() {
        let resource = HostResourceDetector::default().detect(Duration::from_secs(0));
        assert!(resource
            .get(Key::from_static_str(
                opentelemetry_semantic_conventions::attribute::HOST_ARCH
            ))
            .is_some());
        #[cfg(target_arch = "x86_64")]
        assert_eq!(
            resource.get(Key::from_static_str(
                opentelemetry_semantic_conventions::attribute::HOST_ARCH
            )),
            Some(Value::from("x86_64"))
        );
        #[cfg(target_arch = "aarch64")]
        assert_eq!(
            resource.get(Key::from_static_str(
                opentelemetry_semantic_conventions::attribute::HOST_ARCH
            )),
            Some(Value::from("aarch64"))
        )
    }
}