gitops_operator/telemetry/
telemetry.rs

1use opentelemetry::{global, trace::TracerProvider as _, KeyValue};
2use opentelemetry_sdk::{
3    metrics::{MeterProviderBuilder, PeriodicReader},
4    runtime,
5    trace::TracerProvider,
6    Resource,
7};
8use opentelemetry_semantic_conventions::{
9    attribute::{SERVICE_NAME, SERVICE_VERSION},
10    SCHEMA_URL,
11};
12use tracing::subscriber::set_global_default;
13use tracing::Subscriber;
14use tracing_bunyan_formatter::{BunyanFormattingLayer, JsonStorageLayer};
15use tracing_log::LogTracer;
16use tracing_subscriber::{layer::SubscriberExt, EnvFilter, Registry};
17
18pub fn resource() -> Resource {
19    Resource::from_schema_url(
20        [
21            KeyValue::new(SERVICE_NAME, env!("CARGO_PKG_NAME")),
22            KeyValue::new(SERVICE_VERSION, env!("CARGO_PKG_VERSION")),
23        ],
24        SCHEMA_URL,
25    )
26}
27
28// TODO: split this function and add more tests
29pub fn get_subscriber(name: String, env_filter: String) -> impl Subscriber + Send + Sync {
30    let env_filter =
31        EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new(env_filter));
32    let formatting_layer = BunyanFormattingLayer::new(name, std::io::stdout);
33
34    let exporter = opentelemetry_otlp::SpanExporter::builder()
35        .with_tonic()
36        .build()
37        .unwrap();
38
39    let provider = TracerProvider::builder()
40        .with_batch_exporter(exporter, runtime::Tokio)
41        .with_resource(Resource::new(vec![opentelemetry::KeyValue::new(
42            "service.name",
43            "gitops-operator",
44        )]))
45        .build();
46
47    let tracer = provider.tracer("gitops-operator");
48    let telemetry = tracing_opentelemetry::layer().with_tracer(tracer);
49
50    // Metrics
51    let metrics_exporter = opentelemetry_otlp::MetricExporter::builder()
52        .with_tonic()
53        .with_temporality(opentelemetry_sdk::metrics::Temporality::default())
54        .build()
55        .unwrap();
56
57    let reader = PeriodicReader::builder(metrics_exporter, runtime::Tokio)
58        .with_interval(std::time::Duration::from_secs(30))
59        .build();
60
61    let meter_provider = MeterProviderBuilder::default()
62        .with_resource(resource())
63        .with_reader(reader)
64        .build();
65
66    global::set_meter_provider(meter_provider.clone());
67
68    Registry::default()
69        .with(env_filter)
70        .with(JsonStorageLayer)
71        .with(formatting_layer)
72        .with(telemetry)
73}
74
75pub fn init_subscriber(subscriber: impl Subscriber + Send + Sync) {
76    match LogTracer::init() {
77        Ok(_) => (),
78        Err(e) => eprintln!("Failed to set logger: {}", e),
79    };
80    set_global_default(subscriber).expect("Failed to set subscriber");
81}