unc_o11y/
opentelemetry.rs1use crate::reload::TracingLayer;
2use opentelemetry::sdk::trace::{self, IdGenerator, Sampler};
3use opentelemetry::sdk::Resource;
4use opentelemetry::KeyValue;
5use opentelemetry_semantic_conventions::resource::SERVICE_NAME;
6use tracing::level_filters::LevelFilter;
7use tracing_subscriber::layer::SubscriberExt;
8use tracing_subscriber::registry::LookupSpan;
9use tracing_subscriber::{reload, Layer};
10use unc_crypto::PublicKey;
11use unc_primitives_core::types::AccountId;
12
13#[derive(Copy, Clone, Debug, Default, clap::ValueEnum, serde::Serialize, serde::Deserialize)]
15pub enum OpenTelemetryLevel {
16 #[default]
17 OFF,
18 INFO,
19 DEBUG,
20 TRACE,
21}
22
23pub(crate) async fn add_opentelemetry_layer<S>(
28 opentelemetry_level: OpenTelemetryLevel,
29 chain_id: String,
30 node_public_key: PublicKey,
31 account_id: Option<AccountId>,
32 subscriber: S,
33) -> (TracingLayer<S>, reload::Handle<LevelFilter, S>)
34where
35 S: tracing::Subscriber + for<'span> LookupSpan<'span> + Send + Sync,
36{
37 let filter = get_opentelemetry_filter(opentelemetry_level);
38 let (filter, handle) = reload::Layer::<LevelFilter, S>::new(filter);
39
40 let mut resource = vec![
41 KeyValue::new("chain_id", chain_id),
42 KeyValue::new("node_id", node_public_key.to_string()),
43 ];
44 let service_name = if let Some(account_id) = account_id {
47 resource.push(KeyValue::new("account_id", account_id.to_string()));
48 format!("unc-node:{}", account_id)
49 } else {
50 format!("unc-node:{}", node_public_key)
51 };
52 resource.push(KeyValue::new(SERVICE_NAME, service_name));
53
54 let tracer = opentelemetry_otlp::new_pipeline()
55 .tracing()
56 .with_exporter(opentelemetry_otlp::new_exporter().tonic())
57 .with_trace_config(
58 trace::config()
59 .with_sampler(Sampler::AlwaysOn)
60 .with_id_generator(IdGenerator::default())
61 .with_resource(Resource::new(resource)),
62 )
63 .install_batch(opentelemetry::runtime::Tokio)
64 .unwrap();
65 let layer = tracing_opentelemetry::layer().with_tracer(tracer).with_filter(filter);
66 (subscriber.with(layer), handle)
67}
68
69pub(crate) fn get_opentelemetry_filter(opentelemetry_level: OpenTelemetryLevel) -> LevelFilter {
70 match opentelemetry_level {
71 OpenTelemetryLevel::OFF => LevelFilter::OFF,
72 OpenTelemetryLevel::INFO => LevelFilter::INFO,
73 OpenTelemetryLevel::DEBUG => LevelFilter::DEBUG,
74 OpenTelemetryLevel::TRACE => LevelFilter::TRACE,
75 }
76}