use anyhow::Result;
use greentic_config_types::{TelemetryConfig, TelemetryExporterKind};
pub use greentic_telemetry::with_task_local;
use greentic_telemetry::{
TelemetryConfig as ServiceTelemetryConfig, TelemetryCtx,
export::{ExportConfig, ExportMode, Sampling},
init_telemetry_auto, init_telemetry_from_config, set_current_telemetry_ctx,
};
use greentic_types::TenantCtx;
pub fn install(service_name: &str) -> Result<()> {
init_telemetry_auto(ServiceTelemetryConfig {
service_name: service_name.to_string(),
})
}
pub fn install_with_config(service_name: &str, cfg: &TelemetryConfig) -> Result<()> {
if !cfg.enabled || matches!(cfg.exporter, TelemetryExporterKind::None) {
return Ok(());
}
let export = match cfg.exporter {
TelemetryExporterKind::Otlp => export_config(ExportMode::OtlpGrpc, cfg),
TelemetryExporterKind::Stdout => export_config(ExportMode::JsonStdout, cfg),
TelemetryExporterKind::Gcp => export_config(ExportMode::GcpCloudTrace, cfg),
TelemetryExporterKind::Azure => export_config(ExportMode::AzureAppInsights, cfg),
TelemetryExporterKind::Aws => export_config(ExportMode::AwsXRay, cfg),
TelemetryExporterKind::None => unreachable!("handled above"),
};
init_telemetry_from_config(
ServiceTelemetryConfig {
service_name: service_name.to_string(),
},
export,
)
}
fn export_config(mode: ExportMode, cfg: &TelemetryConfig) -> ExportConfig {
let mut export = ExportConfig::default();
export.mode = mode;
export.endpoint = cfg.endpoint.clone();
export.sampling = Sampling::TraceIdRatio(cfg.sampling as f64);
export.compression = None;
export
}
pub fn set_current_tenant_ctx(ctx: &TenantCtx) {
let mut telemetry = TelemetryCtx::new(ctx.tenant_id.as_ref());
if let Some(session) = ctx.session_id() {
telemetry = telemetry.with_session(session);
}
if let Some(flow) = ctx.flow_id() {
telemetry = telemetry.with_flow(flow);
}
if let Some(node) = ctx.node_id() {
telemetry = telemetry.with_node(node);
}
if let Some(provider) = ctx.provider_id() {
telemetry = telemetry.with_provider(provider);
}
set_current_telemetry_ctx(telemetry);
}
#[cfg(test)]
mod tests {
use super::*;
use greentic_config_types::TelemetryConfig;
use greentic_types::{EnvId, TenantCtx, TenantId};
use std::str::FromStr;
#[test]
fn install_with_config_is_noop_when_disabled() {
let cfg = TelemetryConfig {
enabled: false,
exporter: TelemetryExporterKind::Otlp,
endpoint: Some("http://localhost:4317".to_string()),
sampling: 1.0,
};
install_with_config("packc-test", &cfg).expect("disabled config should be a no-op");
}
#[test]
fn install_with_config_is_noop_for_none_exporter() {
let cfg = TelemetryConfig {
enabled: true,
exporter: TelemetryExporterKind::None,
endpoint: None,
sampling: 0.25,
};
install_with_config("packc-test", &cfg).expect("none exporter should be a no-op");
}
#[test]
fn set_current_tenant_ctx_accepts_full_context() {
let tenant = TenantId::from_str("tenant-a").expect("tenant");
let env = EnvId::from_str("dev").expect("env");
let ctx = TenantCtx::new(env, tenant)
.with_session("sess-123")
.with_flow("flow.main")
.with_node("node-1")
.with_provider("provider-1");
set_current_tenant_ctx(&ctx);
}
}