@@ -23,7 +23,7 @@ use opentelemetry::{
23
23
trace:: TracerProvider as _,
24
24
} ;
25
25
use opentelemetry_otlp:: { WithExportConfig , WithHttpConfig } ;
26
- use opentelemetry_prometheus :: PrometheusExporter ;
26
+ use opentelemetry_prometheus_text_exporter :: PrometheusExporter ;
27
27
use opentelemetry_sdk:: {
28
28
Resource ,
29
29
metrics:: { ManualReader , SdkMeterProvider , periodic_reader_with_async_runtime:: PeriodicReader } ,
@@ -33,7 +33,6 @@ use opentelemetry_sdk::{
33
33
} ,
34
34
} ;
35
35
use opentelemetry_semantic_conventions as semcov;
36
- use prometheus:: Registry ;
37
36
use url:: Url ;
38
37
39
38
static SCOPE : LazyLock < InstrumentationScope > = LazyLock :: new ( || {
@@ -49,7 +48,7 @@ pub static METER: LazyLock<Meter> =
49
48
pub static TRACER : OnceLock < Tracer > = OnceLock :: new ( ) ;
50
49
static METER_PROVIDER : OnceLock < SdkMeterProvider > = OnceLock :: new ( ) ;
51
50
static TRACER_PROVIDER : OnceLock < SdkTracerProvider > = OnceLock :: new ( ) ;
52
- static PROMETHEUS_REGISTRY : OnceLock < Registry > = OnceLock :: new ( ) ;
51
+ static PROMETHEUS_EXPORTER : OnceLock < PrometheusExporter > = OnceLock :: new ( ) ;
53
52
54
53
pub fn setup ( config : & TelemetryConfig ) -> anyhow:: Result < ( ) > {
55
54
let propagator = propagator ( & config. tracing . propagators ) ;
@@ -180,21 +179,30 @@ type PromServiceFuture =
180
179
181
180
#[ allow( clippy:: needless_pass_by_value) ]
182
181
fn 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
+ }
198
206
} else {
199
207
Response :: builder ( )
200
208
. status ( 500 )
@@ -209,7 +217,7 @@ fn prometheus_service_fn<T>(_req: T) -> PromServiceFuture {
209
217
}
210
218
211
219
pub fn prometheus_service < T > ( ) -> tower:: util:: ServiceFn < fn ( T ) -> PromServiceFuture > {
212
- if PROMETHEUS_REGISTRY . get ( ) . is_none ( ) {
220
+ if PROMETHEUS_EXPORTER . get ( ) . is_none ( ) {
213
221
tracing:: warn!(
214
222
"A Prometheus resource was mounted on a listener, but the Prometheus exporter was not setup in the config"
215
223
) ;
@@ -219,16 +227,11 @@ pub fn prometheus_service<T>() -> tower::util::ServiceFn<fn(T) -> PromServiceFut
219
227
}
220
228
221
229
fn 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 ( ) ;
227
231
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" ) ) ?;
232
235
233
236
Ok ( exporter)
234
237
}
0 commit comments