commonware_runtime/tokio/
telemetry.rs1use super::{
4 tracing::{export, Config},
5 Context,
6};
7use crate::{Metrics, Spawner};
8use axum::{
9 body::Body,
10 http::{header, Response, StatusCode},
11 routing::get,
12 serve, Extension, Router,
13};
14use std::net::SocketAddr;
15use tokio::net::TcpListener;
16use tracing::Level;
17use tracing_subscriber::{layer::SubscriberExt, Registry};
18
19pub fn init(context: Context, level: Level, metrics: Option<SocketAddr>, traces: Option<Config>) {
21 let fmt_layer = tracing_subscriber::fmt::layer()
23 .json()
24 .with_line_number(true)
25 .with_thread_ids(true)
26 .with_file(true)
27 .with_span_events(tracing_subscriber::fmt::format::FmtSpan::CLOSE);
28
29 let filter = tracing_subscriber::EnvFilter::new(level.to_string());
31
32 if let Some(cfg) = metrics {
34 context
35 .with_label("metrics")
36 .spawn(move |context| async move {
37 let listener = TcpListener::bind(cfg)
43 .await
44 .expect("Failed to bind metrics server");
45
46 let app = Router::new()
48 .route(
49 "/metrics",
50 get(|Extension(ctx): Extension<Context>| async move {
51 Response::builder()
52 .status(StatusCode::OK)
53 .header(header::CONTENT_TYPE, "text/plain; version=0.0.4")
54 .body(Body::from(ctx.encode()))
55 .expect("Failed to create response")
56 }),
57 )
58 .layer(Extension(context));
59
60 serve(listener, app.into_make_service())
65 .await
66 .expect("Could not serve metrics");
67 });
68 }
69
70 if let Some(cfg) = traces {
72 let tracer = export(cfg).expect("Failed to initialize tracer");
74
75 let telemetry_layer = tracing_opentelemetry::layer().with_tracer(tracer);
77
78 let subscriber = Registry::default()
80 .with(filter)
81 .with(fmt_layer)
82 .with(telemetry_layer);
83 tracing::subscriber::set_global_default(subscriber).expect("Failed to set subscriber");
84 } else {
85 let subscriber = Registry::default().with(filter).with(fmt_layer);
87 tracing::subscriber::set_global_default(subscriber).expect("Failed to set subscriber");
88 };
89}