From a0ee61992cb0b2ec70795bdafe9498fec32452f5 Mon Sep 17 00:00:00 2001 From: Ruben Fiszel Date: Mon, 24 Aug 2026 18:19:10 +0000 Subject: [PATCH] fix: filter sqlx notices on the otel bridge too Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01Qzqmh52NU8fB9RBQNNkJGt --- backend/windmill-common/src/db.rs | 4 ++-- backend/windmill-common/src/tracing_init.rs | 23 +++++++++++++++++---- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/backend/windmill-common/src/db.rs b/backend/windmill-common/src/db.rs index ea3f352525..822eb5e7f8 100644 --- a/backend/windmill-common/src/db.rs +++ b/backend/windmill-common/src/db.rs @@ -317,7 +317,7 @@ impl<'b> DbExecutor<'b> for &'b mut PgConnection { /// it, the only way to know is to issue a `ROLLBACK`, and doing that on every checkout costs /// a round trip per query — about a third of the throughput on small ones. So it is armed /// only once Postgres has reported a state that proves a connection is carrying leftover -/// transaction state, and disarms itself after [`RESET_WINDOW`]. +/// transaction state, and disarms itself after `RESET_WINDOW`. /// /// # Why on acquire rather than release /// @@ -329,7 +329,7 @@ impl<'b> DbExecutor<'b> for &'b mut PgConnection { /// /// Arming is process-wide, not per-query: the flag covers a pool shared by everything in the /// process, so it does not matter *which* caller notices a poisoned connection, only that -/// one does. [`note_sqlx_error`] is reached from the two conversions a `sqlx::Error` usually +/// one does. `note_sqlx_error` is reached from the two conversions a `sqlx::Error` usually /// passes through, which is most queries; a caller that instead formats the error into a /// message never converts it and reports nothing. That only delays arming until the next /// converting query touches the same pool — on a worker the job poller alone does so every diff --git a/backend/windmill-common/src/tracing_init.rs b/backend/windmill-common/src/tracing_init.rs index b0823f3205..7fc7d52ab8 100644 --- a/backend/windmill-common/src/tracing_init.rs +++ b/backend/windmill-common/src/tracing_init.rs @@ -48,13 +48,24 @@ pub const VERBOSE_TARGET: &str = "windmill_verbose"; /// when `OTEL_JOB_LOGS=true`. Stripped before forwarding to the tracing layer. pub const OTEL_PREFIX: &str = "OTEL: "; +/// sqlx only ever talks to Windmill's own database, so a Postgres NOTICE/WARNING on this +/// target is never something an operator acts on. `db::connection_reset` in particular +/// provokes one per checkout while it is armed. Applied to every sink separately — the OTEL +/// logs bridge does not share the sinks' `Targets` filter, and an unfiltered bridge would +/// ship the burst off-box. +fn sqlx_notice_filter() -> Targets { + Targets::new() + .with_target( + "sqlx::postgres::notice", + tracing::level_filters::LevelFilter::ERROR, + ) + .with_default(tracing::level_filters::LevelFilter::TRACE) +} + /// Creates a Targets filter that optionally filters out verbose logs when quiet mode is enabled. fn create_targets_filter(default_env_filter: LevelFilter) -> Targets { let targets = Targets::new() .with_target("windmill:job_log", tracing::level_filters::LevelFilter::OFF) - // sqlx only ever talks to Windmill's own database, so a Postgres NOTICE/WARNING on - // this target is never something an operator acts on. `connection_reset` in - // particular provokes one per checkout while it is armed. .with_target( "sqlx::postgres::notice", tracing::level_filters::LevelFilter::ERROR, @@ -182,7 +193,11 @@ pub fn initialize_tracing( let opentelemetry_filtered = opentelemetry; let base_layer = tracing_subscriber::registry() - .with(logs_bridge.with_filter(otel_logs_filter)) + .with( + logs_bridge + .with_filter(otel_logs_filter) + .with_filter(sqlx_notice_filter()), + ) .with(opentelemetry_filtered); match *JSON_FMT {