@@ -23,7 +23,7 @@ use opentelemetry::{
2323 trace:: TracerProvider as _,
2424} ;
2525use opentelemetry_otlp:: { WithExportConfig , WithHttpConfig } ;
26- use opentelemetry_prometheus :: PrometheusExporter ;
26+ use opentelemetry_prometheus_text_exporter :: PrometheusExporter ;
2727use opentelemetry_sdk:: {
2828 Resource ,
2929 metrics:: { ManualReader , SdkMeterProvider , periodic_reader_with_async_runtime:: PeriodicReader } ,
@@ -33,7 +33,6 @@ use opentelemetry_sdk::{
3333 } ,
3434} ;
3535use opentelemetry_semantic_conventions as semcov;
36- use prometheus:: Registry ;
3736use url:: Url ;
3837
3938static SCOPE : LazyLock < InstrumentationScope > = LazyLock :: new ( || {
@@ -49,7 +48,7 @@ pub static METER: LazyLock<Meter> =
4948pub static TRACER : OnceLock < Tracer > = OnceLock :: new ( ) ;
5049static METER_PROVIDER : OnceLock < SdkMeterProvider > = OnceLock :: new ( ) ;
5150static TRACER_PROVIDER : OnceLock < SdkTracerProvider > = OnceLock :: new ( ) ;
52- static PROMETHEUS_REGISTRY : OnceLock < Registry > = OnceLock :: new ( ) ;
51+ static PROMETHEUS_EXPORTER : OnceLock < PrometheusExporter > = OnceLock :: new ( ) ;
5352
5453pub fn setup ( config : & TelemetryConfig ) -> anyhow:: Result < ( ) > {
5554 let propagator = propagator ( & config. tracing . propagators ) ;
@@ -180,21 +179,30 @@ type PromServiceFuture =
180179
181180#[ allow( clippy:: needless_pass_by_value) ]
182181fn prometheus_service_fn < T > ( _req : T ) -> PromServiceFuture {
183- use prometheus:: { Encoder , TextEncoder } ;
184-
185- let response = if let Some ( registry) = PROMETHEUS_REGISTRY . get ( ) {
186- let mut buffer = Vec :: new ( ) ;
187- let encoder = TextEncoder :: new ( ) ;
188- let metric_families = registry. gather ( ) ;
189-
190- // That shouldn't panic, unless we're constructing invalid labels
191- encoder. encode ( & metric_families, & mut buffer) . unwrap ( ) ;
192-
193- Response :: builder ( )
194- . status ( 200 )
195- . header ( CONTENT_TYPE , encoder. format_type ( ) )
196- . body ( Full :: new ( Bytes :: from ( buffer) ) )
197- . unwrap ( )
182+ let response = if let Some ( exporter) = PROMETHEUS_EXPORTER . get ( ) {
183+ // We'll need some space for this, so we preallocate a bit
184+ let mut buffer = Vec :: with_capacity ( 1024 ) ;
185+
186+ if let Err ( err) = exporter. export ( & mut buffer) {
187+ tracing:: error!(
188+ error = & err as & dyn std:: error:: Error ,
189+ "Failed to export Prometheus metrics"
190+ ) ;
191+
192+ Response :: builder ( )
193+ . status ( 500 )
194+ . header ( CONTENT_TYPE , "text/plain" )
195+ . body ( Full :: new ( Bytes :: from_static (
196+ b"Failed to export Prometheus metrics, see logs for details" ,
197+ ) ) )
198+ . unwrap ( )
199+ } else {
200+ Response :: builder ( )
201+ . status ( 200 )
202+ . header ( CONTENT_TYPE , "text/plain;version=1.0.0" )
203+ . body ( Full :: new ( Bytes :: from ( buffer) ) )
204+ . unwrap ( )
205+ }
198206 } else {
199207 Response :: builder ( )
200208 . status ( 500 )
@@ -209,7 +217,7 @@ fn prometheus_service_fn<T>(_req: T) -> PromServiceFuture {
209217}
210218
211219pub fn prometheus_service < T > ( ) -> tower:: util:: ServiceFn < fn ( T ) -> PromServiceFuture > {
212- if PROMETHEUS_REGISTRY . get ( ) . is_none ( ) {
220+ if PROMETHEUS_EXPORTER . get ( ) . is_none ( ) {
213221 tracing:: warn!(
214222 "A Prometheus resource was mounted on a listener, but the Prometheus exporter was not setup in the config"
215223 ) ;
@@ -219,16 +227,11 @@ pub fn prometheus_service<T>() -> tower::util::ServiceFn<fn(T) -> PromServiceFut
219227}
220228
221229fn prometheus_metric_reader ( ) -> anyhow:: Result < PrometheusExporter > {
222- let registry = Registry :: new ( ) ;
223-
224- PROMETHEUS_REGISTRY
225- . set ( registry. clone ( ) )
226- . map_err ( |_| anyhow:: anyhow!( "PROMETHEUS_REGISTRY was set twice" ) ) ?;
230+ let exporter = PrometheusExporter :: builder ( ) . without_scope_info ( ) . build ( ) ;
227231
228- let exporter = opentelemetry_prometheus:: exporter ( )
229- . with_registry ( registry)
230- . without_scope_info ( )
231- . build ( ) ?;
232+ PROMETHEUS_EXPORTER
233+ . set ( exporter. clone ( ) )
234+ . map_err ( |_| anyhow:: anyhow!( "PROMETHEUS_EXPORTER was set twice" ) ) ?;
232235
233236 Ok ( exporter)
234237}
0 commit comments