Repository: denoland/deno
Pull request: fix(http): generate `OtelInfo` only when otel metrics are enabled


Changed files:
filename: cli/main.rs
patch: @@ -458,7 +458,10 @@ fn resolve_flags_and_init(
   };
 
   let otel_config = flags.otel_config();
-  deno_telemetry::init(deno_lib::version::otel_runtime_config(), &otel_config)?;
+  deno_telemetry::init(
+    deno_lib::version::otel_runtime_config(),
+    otel_config.clone(),
+  )?;
   init_logging(flags.log_level, Some(otel_config));
 
   // TODO(bartlomieju): remove in Deno v2.5 and hard error then.

filename: cli/rt/main.rs
patch: @@ -74,7 +74,7 @@ fn main() {
       Ok(Some(data)) => {
         deno_runtime::deno_telemetry::init(
           otel_runtime_config(),
-          &data.metadata.otel_config,
+          data.metadata.otel_config.clone(),
         )?;
         init_logging(
           data.metadata.log_level,

filename: ext/http/lib.rs
patch: @@ -382,11 +382,11 @@ impl OtelInfoAttributes {
 
 impl OtelInfo {
   fn new(
+    otel: &deno_telemetry::OtelGlobals,
     instant: std::time::Instant,
     request_size: u64,
     attributes: OtelInfoAttributes,
   ) -> Self {
-    let otel = OTEL_GLOBALS.get().unwrap();
     let collectors = OTEL_COLLECTORS.get_or_init(|| {
       let meter = otel
         .meter_provider
@@ -596,7 +596,10 @@ impl HttpConnResource {
       let (request_tx, request_rx) = oneshot::channel();
       let (response_tx, response_rx) = oneshot::channel();
 
-      let otel_instant = OTEL_GLOBALS.get().map(|_| std::time::Instant::now());
+      let otel_instant = OTEL_GLOBALS
+        .get()
+        .filter(|o| o.has_metrics())
+        .map(|_| std::time::Instant::now());
 
       let acceptor = HttpAcceptor::new(request_tx, response_rx);
       self.acceptors_tx.unbounded_send(acceptor).ok()?;
@@ -615,26 +618,28 @@ impl HttpConnResource {
           .unwrap_or(Encoding::Identity)
       };
 
-      let otel_info = OTEL_GLOBALS.get().map(|_| {
-        let size_hint = request.size_hint();
-        Rc::new(RefCell::new(Some(OtelInfo::new(
-          otel_instant.unwrap(),
-          size_hint.upper().unwrap_or(size_hint.lower()),
-          OtelInfoAttributes {
-            http_request_method: OtelInfoAttributes::method_v02(
-              request.method(),
-            ),
-            url_scheme: Cow::Borrowed(self.scheme),
-            network_protocol_version: OtelInfoAttributes::version_v02(
-              request.version(),
-            ),
-            server_address: request.uri().host().map(|host| host.to_string()),
-            server_port: request.uri().port_u16().map(|port| port as i64),
-            error_type: Default::default(),
-            http_response_status_code: Default::default(),
-          },
-        ))))
-      });
+      let otel_info =
+        OTEL_GLOBALS.get().filter(|o| o.has_metrics()).map(|otel| {
+          let size_hint = request.size_hint();
+          Rc::new(RefCell::new(Some(OtelInfo::new(
+            otel,
+            otel_instant.unwrap(),
+            size_hint.upper().unwrap_or(size_hint.lower()),
+            OtelInfoAttributes {
+              http_request_method: OtelInfoAttributes::method_v02(
+                request.method(),
+              ),
+              url_scheme: Cow::Borrowed(self.scheme),
+              network_protocol_version: OtelInfoAttributes::version_v02(
+                request.version(),
+              ),
+              server_address: request.uri().host().map(|host| host.to_string()),
+              server_port: request.uri().port_u16().map(|port| port as i64),
+              error_type: Default::default(),
+              http_response_status_code: Default::default(),
+            },
+          ))))
+        });
 
       let method = request.method().to_string();
       let url = req_url(&request, self.scheme, &self.addr);

filename: ext/http/service.rs
patch: @@ -188,10 +188,14 @@ pub(crate) async fn handle_request(
   server_state: SignallingRc<HttpServerState>, // Keep server alive for duration of this future.
   tx: tokio::sync::mpsc::Sender<Rc<HttpRecord>>,
 ) -> Result<Response, hyper_v014::Error> {
-  let otel_info = if deno_telemetry::OTEL_GLOBALS.get().is_some() {
+  let otel_info = if let Some(otel) = deno_telemetry::OTEL_GLOBALS
+    .get()
+    .filter(|o| o.has_metrics())
+  {
     let instant = std::time::Instant::now();
     let size_hint = request.size_hint();
     Some(OtelInfo::new(
+      otel,
       instant,
       size_hint.upper().unwrap_or(size_hint.lower()),
       OtelInfoAttributes {

filename: ext/telemetry/lib.rs
patch: @@ -595,13 +595,24 @@ pub struct OtelGlobals {
   pub id_generator: DenoIdGenerator,
   pub meter_provider: SdkMeterProvider,
   pub builtin_instrumentation_scope: InstrumentationScope,
+  pub config: OtelConfig,
+}
+
+impl OtelGlobals {
+  pub fn has_tracing(&self) -> bool {
+    self.config.tracing_enabled
+  }
+
+  pub fn has_metrics(&self) -> bool {
+    self.config.metrics_enabled
+  }
 }
 
 pub static OTEL_GLOBALS: OnceCell<OtelGlobals> = OnceCell::new();
 
 pub fn init(
   rt_config: OtelRuntimeConfig,
-  config: &OtelConfig,
+  config: OtelConfig,
 ) -> deno_core::anyhow::Result<()> {
   // Parse the `OTEL_EXPORTER_OTLP_PROTOCOL` variable. The opentelemetry_*
   // crates don't do this automatically.
@@ -726,6 +737,7 @@ pub fn init(
       id_generator,
       meter_provider,
       builtin_instrumentation_scope,
+      config,
     })
     .map_err(|_| deno_core::anyhow::anyhow!("failed to set otel globals"))?;