kmp_observability/
metrics.rs1use opentelemetry::metrics::{Counter, Histogram, Meter};
2use opentelemetry_otlp::WithExportConfig;
3use opentelemetry_otlp::WithTonicConfig;
4use opentelemetry_sdk::metrics::SdkMeterProvider;
5
6pub struct KernelMetrics {
11 pub rpc_duration: Histogram<f64>,
12 pub bundle_nodes: Histogram<u64>,
13 pub bundle_relationships: Histogram<u64>,
14 pub bundle_details: Histogram<u64>,
15 pub rendered_tokens: Histogram<u64>,
16 pub truncation_total: Counter<u64>,
17 pub projection_lag: Histogram<f64>,
18}
19
20impl KernelMetrics {
21 pub fn new(meter: &Meter) -> Self {
22 Self {
23 rpc_duration: meter
24 .f64_histogram("rehydration.rpc.duration")
25 .with_description("RPC latency in seconds")
26 .with_unit("s")
27 .build(),
28 bundle_nodes: meter
29 .u64_histogram("rehydration.bundle.nodes")
30 .with_description("Number of nodes in rehydrated bundle")
31 .build(),
32 bundle_relationships: meter
33 .u64_histogram("rehydration.bundle.relationships")
34 .with_description("Number of relationships in rehydrated bundle")
35 .build(),
36 bundle_details: meter
37 .u64_histogram("rehydration.bundle.details")
38 .with_description("Number of node details in rehydrated bundle")
39 .build(),
40 rendered_tokens: meter
41 .u64_histogram("rehydration.rendered.tokens")
42 .with_description("Rendered token count after budget enforcement")
43 .build(),
44 truncation_total: meter
45 .u64_counter("rehydration.truncation.total")
46 .with_description("Number of renders that required truncation")
47 .build(),
48 projection_lag: meter
49 .f64_histogram("rehydration.projection.lag")
50 .with_description("Projection processing lag in seconds")
51 .with_unit("s")
52 .build(),
53 }
54 }
55}
56
57pub(crate) fn init_otel_metrics(service_name: &str) -> Option<SdkMeterProvider> {
58 let endpoint = std::env::var("OTEL_EXPORTER_OTLP_ENDPOINT").ok()?;
59 if endpoint.trim().is_empty() {
60 return None;
61 }
62
63 let mut builder = opentelemetry_otlp::MetricExporter::builder()
64 .with_tonic()
65 .with_endpoint(endpoint);
66 if let Some(tls_config) = super::build_otlp_tls_config() {
67 builder = builder.with_tls_config(tls_config);
68 }
69 let exporter = builder.build().ok()?;
70
71 let reader = opentelemetry_sdk::metrics::PeriodicReader::builder(exporter).build();
72
73 let provider = SdkMeterProvider::builder()
74 .with_resource(
75 opentelemetry_sdk::Resource::builder()
76 .with_service_name(service_name.to_string())
77 .build(),
78 )
79 .with_reader(reader)
80 .build();
81
82 Some(provider)
83}