1use anyhow::Result;
2use greentic_config_types::{TelemetryConfig, TelemetryExporterKind};
3pub use greentic_telemetry::with_task_local;
4use greentic_telemetry::{
5 TelemetryConfig as ServiceTelemetryConfig, TelemetryCtx,
6 export::{ExportConfig, ExportMode, Sampling},
7 init_telemetry_auto, init_telemetry_from_config, set_current_telemetry_ctx,
8};
9use greentic_types::TenantCtx;
10
11pub fn install(service_name: &str) -> Result<()> {
13 init_telemetry_auto(ServiceTelemetryConfig {
14 service_name: service_name.to_string(),
15 })
16}
17
18pub fn install_with_config(service_name: &str, cfg: &TelemetryConfig) -> Result<()> {
20 if !cfg.enabled || matches!(cfg.exporter, TelemetryExporterKind::None) {
21 return Ok(());
22 }
23
24 let export = match cfg.exporter {
25 TelemetryExporterKind::Otlp => export_config(ExportMode::OtlpGrpc, cfg),
26 TelemetryExporterKind::Stdout => export_config(ExportMode::JsonStdout, cfg),
27 TelemetryExporterKind::Gcp => export_config(ExportMode::GcpCloudTrace, cfg),
28 TelemetryExporterKind::Azure => export_config(ExportMode::AzureAppInsights, cfg),
29 TelemetryExporterKind::Aws => export_config(ExportMode::AwsXRay, cfg),
30 TelemetryExporterKind::None => unreachable!("handled above"),
31 };
32
33 init_telemetry_from_config(
34 ServiceTelemetryConfig {
35 service_name: service_name.to_string(),
36 },
37 export,
38 )
39}
40
41fn export_config(mode: ExportMode, cfg: &TelemetryConfig) -> ExportConfig {
42 let mut export = ExportConfig::default();
43 export.mode = mode;
44 export.endpoint = cfg.endpoint.clone();
45 export.sampling = Sampling::TraceIdRatio(cfg.sampling as f64);
46 export.compression = None;
47 export
48}
49
50pub fn set_current_tenant_ctx(ctx: &TenantCtx) {
52 use greentic_types::telemetry::attr_keys;
53
54 let mut telemetry = TelemetryCtx::new(ctx.tenant_id.as_ref()).with_env(ctx.env.as_str());
55
56 if let Some(session) = ctx.session_id() {
57 telemetry = telemetry.with_session(session);
58 }
59 if let Some(flow) = ctx.flow_id() {
60 telemetry = telemetry.with_flow(flow);
61 }
62 if let Some(node) = ctx.node_id() {
63 telemetry = telemetry.with_node(node);
64 }
65 if let Some(provider) = ctx.provider_id() {
66 telemetry = telemetry.with_provider(provider);
67 }
68 if let Some(v) = ctx.attributes.get(attr_keys::CUSTOMER_ID) {
72 telemetry = telemetry.with_customer_id(v);
73 }
74 if let Some(v) = ctx.attributes.get(attr_keys::DEPLOYMENT_ID) {
75 telemetry = telemetry.with_deployment_id(v);
76 }
77 if let Some(v) = ctx.attributes.get(attr_keys::BUNDLE_ID) {
78 telemetry = telemetry.with_bundle_id(v);
79 }
80 if let Some(v) = ctx.attributes.get(attr_keys::REVISION_ID) {
81 telemetry = telemetry.with_revision_id(v);
82 }
83
84 set_current_telemetry_ctx(telemetry);
85}
86
87#[cfg(test)]
88mod tests {
89 use super::*;
90 use greentic_config_types::TelemetryConfig;
91 use greentic_types::{EnvId, TenantCtx, TenantId};
92 use std::str::FromStr;
93
94 #[test]
95 fn install_with_config_is_noop_when_disabled() {
96 let cfg = TelemetryConfig {
97 enabled: false,
98 exporter: TelemetryExporterKind::Otlp,
99 endpoint: Some("http://localhost:4317".to_string()),
100 sampling: 1.0,
101 };
102
103 install_with_config("packc-test", &cfg).expect("disabled config should be a no-op");
104 }
105
106 #[test]
107 fn install_with_config_is_noop_for_none_exporter() {
108 let cfg = TelemetryConfig {
109 enabled: true,
110 exporter: TelemetryExporterKind::None,
111 endpoint: None,
112 sampling: 0.25,
113 };
114
115 install_with_config("packc-test", &cfg).expect("none exporter should be a no-op");
116 }
117
118 #[test]
119 fn set_current_tenant_ctx_accepts_full_context() {
120 let tenant = TenantId::from_str("tenant-a").expect("tenant");
121 let env = EnvId::from_str("dev").expect("env");
122 let mut ctx = TenantCtx::new(env, tenant)
123 .with_session("sess-123")
124 .with_flow("flow.main")
125 .with_node("node-1")
126 .with_provider("provider-1");
127 ctx.attributes.insert(
129 greentic_types::telemetry::attr_keys::BUNDLE_ID.to_string(),
130 "customer.support".to_string(),
131 );
132
133 set_current_tenant_ctx(&ctx);
134 }
135}