greentic_deployer/
telemetry.rs1use std::collections::HashMap;
2
3use greentic_config_types::{TelemetryConfig as ResolvedTelemetryConfig, TelemetryExporterKind};
4use greentic_telemetry::{
5 TelemetryConfig,
6 export::{ExportConfig, ExportMode, Sampling},
7 init_telemetry_from_config,
8};
9
10use crate::config::DeployerConfig;
11use crate::error::{DeployerError, Result};
12
13pub fn init(config: &DeployerConfig) -> Result<()> {
14 let telemetry_cfg = config.telemetry_config();
15 if !telemetry_cfg.enabled || matches!(telemetry_cfg.exporter, TelemetryExporterKind::None) {
16 return Ok(());
17 }
18
19 let export = export_from_config(telemetry_cfg);
20 let cfg = TelemetryConfig {
21 service_name: format!("greentic-deployer-{}", config.provider.as_str()),
22 };
23
24 init_telemetry_from_config(cfg, export).map_err(|err| DeployerError::Telemetry(err.to_string()))
25}
26
27fn export_from_config(cfg: &ResolvedTelemetryConfig) -> ExportConfig {
28 let sampling = Sampling::TraceIdRatio(cfg.sampling as f64);
29
30 let mut export = ExportConfig::json_default();
31 export.sampling = sampling;
32
33 match cfg.exporter {
34 TelemetryExporterKind::Stdout => export,
35 TelemetryExporterKind::Otlp => {
36 export.mode = ExportMode::OtlpGrpc;
37 export.endpoint = cfg
38 .endpoint
39 .clone()
40 .or_else(|| std::env::var("OTEL_EXPORTER_OTLP_ENDPOINT").ok())
41 .or_else(|| Some("https://otel.greentic.ai".to_string()));
42 export.headers = HashMap::new();
43 export.compression = None;
44 export
45 }
46 TelemetryExporterKind::Gcp => {
47 export.mode = ExportMode::GcpCloudTrace;
48 export.endpoint = cfg.endpoint.clone();
49 export
50 }
51 TelemetryExporterKind::Azure => {
52 export.mode = ExportMode::AzureAppInsights;
53 export.endpoint = cfg.endpoint.clone();
54 export
55 }
56 TelemetryExporterKind::Aws => {
57 export.mode = ExportMode::AwsXRay;
58 export.endpoint = cfg.endpoint.clone();
59 export
60 }
61 TelemetryExporterKind::None => ExportConfig::json_default(),
62 }
63}
64
65#[cfg(test)]
66mod tests {
67 use super::*;
68
69 fn base_config(exporter: TelemetryExporterKind) -> ResolvedTelemetryConfig {
70 ResolvedTelemetryConfig {
71 enabled: true,
72 exporter,
73 endpoint: Some("https://otel.test".to_string()),
74 sampling: 0.5,
75 }
76 }
77
78 #[test]
79 fn stdout_uses_json_export() {
80 let export = export_from_config(&base_config(TelemetryExporterKind::Stdout));
81 assert!(matches!(export.mode, ExportMode::JsonStdout));
82 assert!(
83 matches!(export.sampling, Sampling::TraceIdRatio(v) if (v - 0.5).abs() < f64::EPSILON)
84 );
85 }
86
87 #[test]
88 fn otlp_prefers_config_endpoint() {
89 let export = export_from_config(&base_config(TelemetryExporterKind::Otlp));
90 assert!(matches!(export.mode, ExportMode::OtlpGrpc));
91 assert_eq!(export.endpoint.as_deref(), Some("https://otel.test"));
92 }
93
94 #[test]
95 fn cloud_exporters_use_cloud_modes() {
96 let gcp = export_from_config(&base_config(TelemetryExporterKind::Gcp));
97 assert!(matches!(gcp.mode, ExportMode::GcpCloudTrace));
98 assert_eq!(gcp.endpoint.as_deref(), Some("https://otel.test"));
99
100 let azure = export_from_config(&base_config(TelemetryExporterKind::Azure));
101 assert!(matches!(azure.mode, ExportMode::AzureAppInsights));
102 assert_eq!(azure.endpoint.as_deref(), Some("https://otel.test"));
103
104 let aws = export_from_config(&base_config(TelemetryExporterKind::Aws));
105 assert!(matches!(aws.mode, ExportMode::AwsXRay));
106 assert_eq!(aws.endpoint.as_deref(), Some("https://otel.test"));
107 }
108}