From 1b36fbc598a5347b6083d1a6869cbc0da3f9ae75 Mon Sep 17 00:00:00 2001 From: Javier Segura Date: Mon, 27 Apr 2026 18:11:57 +0200 Subject: [PATCH] fix: Propagate muted flag to :error telemetry events MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `Repo.insert!(_, on_conflict: [set: [...]])` only round-trips the columns it sets, so the in-memory `Error` struct dispatched to subscribers of `[:error_tracker, :error, :new]` and `[:error_tracker, :error, :unresolved]` always carried the schema default (`muted: false`), regardless of the row's real state in the database. This made the dashboard mute action effectively a no-op for those two events. The DB row is already queried for `existing_status` and `muted` at the top of `upsert_error!/5`, so stamp the in-memory struct with that value before dispatching the telemetry events. Two-line change, no public API surface modified — subscribers that already read `metadata.error.muted` start working without any change on their side. --- lib/error_tracker.ex | 6 ++++++ test/error_tracker/telemetry_test.exs | 20 ++++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/lib/error_tracker.ex b/lib/error_tracker.ex index d88ced0..e8f017e 100644 --- a/lib/error_tracker.ex +++ b/lib/error_tracker.ex @@ -371,6 +371,12 @@ defmodule ErrorTracker do %Occurrence{} = occurrence occurrence = %{occurrence | error: error} + # `Repo.insert!(_, on_conflict: [set: [...]])` only round-trips the columns + # it sets, so the in-memory struct keeps `muted: false` (the schema default) + # even when the DB row is muted. Stamp it with the value we already fetched + # so subscribers of `[:error_tracker, :error, :*]` see the real flag. + error = %{error | muted: muted} + # If the error existed and was marked as resolved before this exception, # sent a Telemetry event # If it is a new error, sent a Telemetry event diff --git a/test/error_tracker/telemetry_test.exs b/test/error_tracker/telemetry_test.exs index 07c0405..d85f54e 100644 --- a/test/error_tracker/telemetry_test.exs +++ b/test/error_tracker/telemetry_test.exs @@ -51,4 +51,24 @@ defmodule ErrorTracker.TelemetryTest do assert_receive {:telemetry_event, [:error_tracker, :error, :unresolved], _, %{error: %Error{}}} end + + test "the :unresolved event carries the muted flag for muted errors" do + {exception, stacktrace} = + try do + raise "This is a test" + rescue + e -> {e, __STACKTRACE__} + end + + %Occurrence{error: error = %Error{}} = ErrorTracker.report(exception, stacktrace) + {:ok, error} = ErrorTracker.mute(error) + {:ok, _resolved} = ErrorTracker.resolve(error) + + # Trigger the same error again. It exists and is resolved, so the + # :unresolved telemetry event fires — and its `error` struct must + # reflect the muted flag stored in the DB. + ErrorTracker.report(exception, stacktrace) + + assert_receive {:telemetry_event, [:error_tracker, :error, :unresolved], _, %{error: %Error{muted: true}}} + end end