Replace init_tracing + init_sentry with single init_telemetry
Add TelemetryGuard that wraps both tracing and Sentry guards.
init_telemetry() sets up the OTEL tracing subscriber and optionally
initializes the Sentry client, all via one call. Returns Result<TelemetryGuard>
using telemetry::Result type alias. Removed init_tracing and all
per-crate init_sentry functions.
Assisted-by: Owl Alpha via pi
diff --git a/quire-ci/src/main.rs b/quire-ci/src/main.rs
index 3205bb3..88c6b06 100644
--- a/quire-ci/src/main.rs
+++ b/quire-ci/src/main.rs
@@ -367,7 +367,7 @@ fn main() -> Result<()> {
// _tracing_guard must be declared AFTER _sentry so it drops
// BEFORE _sentry — OTEL provider flushes spans to Sentry SDK
// before the Sentry client flushes to the server.
- let _tracing_guard = telemetry::init_tracing(miette_layer, FmtMode::Plain)?;
+ let _guard = telemetry::init_telemetry(miette_layer, FmtMode::Plain, None, VERSION)?;
let (git_dir, meta, sentry_ctx) = if local {
let Some(git_dir) = git_dir else {
diff --git a/quire-ci/src/server.rs b/quire-ci/src/server.rs
index edfe0ae..ac37287 100644
--- a/quire-ci/src/server.rs
+++ b/quire-ci/src/server.rs
@@ -34,7 +34,7 @@ pub async fn run(quire: QuireCi) -> Result<()> {
let port = quire.config().port;
let miette_layer = telemetry::MietteLayer::new();
- let (_tracing_guard, _sentry_guard) = telemetry::init_telemetry(
+ let _guard = telemetry::init_telemetry(
miette_layer,
FmtMode::AutoJson,
quire.config().sentry.as_ref(),
diff --git a/quire-core/src/telemetry.rs b/quire-core/src/telemetry.rs
index f9d7a36..209c0ef 100644
--- a/quire-core/src/telemetry.rs
+++ b/quire-core/src/telemetry.rs
@@ -15,6 +15,8 @@ pub enum Error {
Secret(#[from] crate::secret::Error),
}
+pub type Result<T> = std::result::Result<T, Error>;
+
/// Sentry configuration extracted from the global config.
#[derive(serde::Deserialize, Debug, Clone)]
pub struct SentryConfig {
@@ -207,29 +209,36 @@ pub fn sentry_client_options(release: &'static str) -> sentry::ClientOptions {
}
}
-/// Returned by `init_tracing`; shuts down the OTEL TracerProvider on drop.
-pub struct TracingGuard {
+/// Returned by `init_telemetry`; shuts down both tracing and Sentry on drop.
+pub struct TelemetryGuard {
+ #[allow(dead_code)]
provider: opentelemetry_sdk::trace::SdkTracerProvider,
+ sentry: Option<sentry::ClientInitGuard>,
}
-impl Drop for TracingGuard {
+impl Drop for TelemetryGuard {
fn drop(&mut self) {
- let _ = self.provider.shutdown();
+ // Drop tracing first (flushes OTEL spans to Sentry), then Sentry.
+ self.sentry.take();
}
}
-/// Initialize the global tracing subscriber with `QUIRE_LOG`-driven filtering,
-/// a stderr fmt layer per `fmt_mode`, the `sentry-tracing` bridge, the
-/// supplied [`MietteLayer`], and an OTEL tracing layer wired to Sentry.
+/// Initialize both tracing and Sentry.
///
-/// Layer ordering is baked in: `miette_layer` registers before
-/// `sentry_tracing::layer()` so its thread-local is populated when
-/// sentry-tracing's `on_event` calls `capture_event`.
-pub fn init_tracing(
+/// Sets up the global tracing subscriber (OTEL + stderr fmt) and, if a
+/// Sentry config is provided, initializes the Sentry client.
+pub fn init_telemetry(
miette_layer: MietteLayer,
fmt_mode: FmtMode,
-) -> std::result::Result<TracingGuard, Error> {
+ sentry_config: Option<&SentryConfig>,
+ release: &'static str,
+) -> Result<TelemetryGuard> {
+ // Build the tracing subscriber first (same as init_tracing).
let filter = EnvFilter::builder().with_env_var("QUIRE_LOG").from_env()?;
+ let provider = opentelemetry_sdk::trace::SdkTracerProvider::builder()
+ .with_span_processor(sentry_opentelemetry::SentrySpanProcessor::new())
+ .build();
+ let tracer = provider.tracer("quire");
let layer = tracing_subscriber::fmt::layer().with_writer(std::io::stderr);
let fmt_layer = match fmt_mode {
@@ -246,11 +255,7 @@ pub fn init_tracing(
opentelemetry::global::set_text_map_propagator(
opentelemetry_sdk::propagation::TraceContextPropagator::new(),
);
- let provider = opentelemetry_sdk::trace::SdkTracerProvider::builder()
- .with_span_processor(sentry_opentelemetry::SentrySpanProcessor::new())
- .build();
opentelemetry::global::set_tracer_provider(provider.clone());
- let tracer = provider.tracer("quire");
tracing_subscriber::registry()
.with(miette_layer)
@@ -260,23 +265,7 @@ pub fn init_tracing(
.with(filter)
.init();
- Ok(TracingGuard { provider })
-}
-
-/// Initialize both tracing and Sentry.
-///
-/// Sets up the global tracing subscriber (OTEL + stderr fmt) and, if a
-/// Sentry config is provided, initializes the Sentry client. Returns both
-/// guards so the caller can control drop order.
-pub fn init_telemetry(
- miette_layer: MietteLayer,
- fmt_mode: FmtMode,
- sentry_config: Option<&SentryConfig>,
- release: &'static str,
-) -> std::result::Result<(TracingGuard, Option<sentry::ClientInitGuard>), Error> {
- let tracing_guard = init_tracing(miette_layer, fmt_mode)?;
-
- let sentry_guard = match sentry_config {
+ let sentry = match sentry_config {
Some(config) => {
let dsn = config.dsn.reveal()?;
Some(sentry::init((dsn, sentry_client_options(release))))
@@ -284,7 +273,7 @@ pub fn init_telemetry(
None => None,
};
- Ok((tracing_guard, sentry_guard))
+ Ok(TelemetryGuard { provider, sentry })
}
#[cfg(test)]
diff --git a/quire-server/src/bin/quire/main.rs b/quire-server/src/bin/quire/main.rs
index 61c7105..3f4b52b 100644
--- a/quire-server/src/bin/quire/main.rs
+++ b/quire-server/src/bin/quire/main.rs
@@ -114,7 +114,7 @@ async fn main() -> Result<()> {
.with_type::<quire::Error>()
.with_type::<quire::ci::Error>()
.with_type::<quire_core::fennel::FennelError>();
- let (_tracing_guard, _sentry_guard) = telemetry::init_telemetry(
+ let _guard = telemetry::init_telemetry(
miette_layer,
FmtMode::AutoJson,
sentry_config.as_ref(),