diff --git a/ext/telemetry/lib.rs b/ext/telemetry/lib.rs index 1c0f57e292..ca705526fe 100644 --- a/ext/telemetry/lib.rs +++ b/ext/telemetry/lib.rs @@ -770,9 +770,87 @@ pub fn init( }) .map_err(|_| deno_core::anyhow::anyhow!("failed to set otel globals"))?; + setup_signal_handlers(); Ok(()) } +#[cfg(unix)] +fn setup_signal_handlers() { + use tokio::signal::unix::SignalKind; + + let signals_to_handle = [ + SignalKind::hangup(), + SignalKind::interrupt(), + SignalKind::terminate(), + ]; + + for signal_kind in signals_to_handle { + tokio::spawn(async move { + let Ok(mut signal_fut) = tokio::signal::unix::signal(signal_kind) else { + return; + }; + + loop { + signal_fut.recv().await; + flush(); + } + }); + } +} + +#[cfg(windows)] +fn setup_signal_handlers() { + tokio::spawn(async { + let Ok(mut signal_fut) = tokio::signal::windows::ctrl_break() else { + return; + }; + loop { + signal_fut.recv().await; + flush(); + } + }); + + tokio::spawn(async { + let Ok(mut signal_fut) = tokio::signal::windows::ctrl_c() else { + return; + }; + loop { + signal_fut.recv().await; + flush(); + } + }); + + tokio::spawn(async { + let Ok(mut signal_fut) = tokio::signal::windows::ctrl_close() else { + return; + }; + loop { + signal_fut.recv().await; + flush(); + } + }); + + tokio::spawn(async { + let Ok(mut signal_fut) = tokio::signal::windows::ctrl_logoff() else { + return; + }; + loop { + signal_fut.recv().await; + flush(); + } + }); + + tokio::spawn(async { + let Ok(mut signal_fut) = tokio::signal::windows::ctrl_shutdown() else { + return; + }; + loop { + signal_fut.recv().await; + flush(); + } + }); +} + /// This function is called by the runtime whenever it is about to call /// `process::exit()`, to ensure that all OpenTelemetry logs are properly /// flushed before the process terminates.