diff --git a/lib/sentry.ex b/lib/sentry.ex index fc9899a4..5ac12804 100644 --- a/lib/sentry.ex +++ b/lib/sentry.ex @@ -155,6 +155,8 @@ defmodule Sentry do ## Crashing Callbacks + *Available since 14.0.0.* + When a callback you configure raises, throws, or exits, Sentry catches the failure and logs it at the `:error` level instead of letting it reach the code that was reporting the event or serving the request. The log carries the `:sentry` logger domain, so the SDK never @@ -212,7 +214,8 @@ defmodule Sentry do > > Apart from `Sentry.LiveViewHook`, which redacts the data outright, falling back to the > SDK's default scrubber means that data only your custom scrubber was dropping is sent to - > Sentry for as long as that scrubber keeps failing. The error-level log is the only signal. + > Sentry for as long as that scrubber keeps failing. The error-level log is the only signal, + > so alert on it rather than treating a custom scrubber as a guarantee. ### Oban Callbacks diff --git a/lib/sentry/config.ex b/lib/sentry/config.ex index 4f8fb677..a88f4eb7 100644 --- a/lib/sentry/config.ex +++ b/lib/sentry/config.ex @@ -714,11 +714,8 @@ defmodule Sentry.Config do `Sentry.LiveViewHook` breadcrumb data, Oban job args, and maps captured into stacktrace frame variables. - These *extend* the SDK default (see `Sentry.Scrubber.default_param_keys/0`), - which is the denylist required by the - [Sentry Data Collection spec](https://develop.sentry.dev/sdk/foundations/client/data-collection/). - The spec defines custom deny-mode terms as additive, so there is no way - to shrink the default list — that is deliberate. + These terms extend `Sentry.Scrubber.default_param_keys/0`; the default + list cannot be shortened. Terms are matched as case-insensitive substrings of the key name, so `"ref"` redacts `"internal_ref"` and `"REF_ID"` alike. diff --git a/lib/sentry/live_view_hook.ex b/lib/sentry/live_view_hook.ex index 6d875524..fb9b814a 100644 --- a/lib/sentry/live_view_hook.ex +++ b/lib/sentry/live_view_hook.ex @@ -75,12 +75,13 @@ if Code.ensure_loaded?(Phoenix.LiveView) do ## Crashing Callbacks - The `:scrubber` runs in the LiveView process, where a failure of its own - would crash the LiveView. It cannot: if it raises, throws, exits, or returns - anything other than a map, Sentry catches the failure and logs it at the - `:error` level with the `:sentry` logger domain, so the SDK never reports its - own callback failure as an event. The breadcrumb is then recorded with - redacted data - an empty map - rather than with data that was never scrubbed. + *Available since 14.0.0.* + + If the `:scrubber` raises, throws, exits, or returns anything other than a + map, the LiveView keeps running and the breadcrumb is recorded with redacted + data - an empty map - rather than with data that was never scrubbed. See the + [*Crashing Callbacks*](`m:Sentry#module-crashing-callbacks`) section of the + `Sentry` documentation for how the failure is logged. """ diff --git a/lib/sentry/metrics.ex b/lib/sentry/metrics.ex index 24f84814..ad6c44d1 100644 --- a/lib/sentry/metrics.ex +++ b/lib/sentry/metrics.ex @@ -27,6 +27,8 @@ defmodule Sentry.Metrics do ## Automatically Collected Metrics + *Available since 14.0.0.* + The SDK can also report BEAM runtime health on its own, without any calls to the functions above. This is opt-in: @@ -43,8 +45,8 @@ defmodule Sentry.Metrics do waiting to run * `elixir.runtime.process.*`, `elixir.runtime.atom.*` and `elixir.runtime.port.*` — a `count`, the hard VM `limit`, and the `utilization` ratio between them. The - `limit` and `utilization` gauges need telemetry_poller 1.3.0 or later, which is - when it started measuring the limits; on older versions only `count` is reported. + `limit` and `utilization` gauges require telemetry_poller 1.3.0 or later; older + versions report only `count`. * `elixir.runtime.scheduler.utilization` — the busy fraction of scheduler time, as a ratio between `0.0` and `1.0`. Unlike the others this is a delta between two samples, so the first collection only takes a baseline and the first value arrives @@ -54,7 +56,7 @@ defmodule Sentry.Metrics do ### Collection Frequency The SDK does not collect these itself. It listens to the events that - [telemetry_poller](https://hexdocs.pm/telemetry_poller) already emits, so how often + `telemetry_poller` already emits, so how often they are reported is how often that library polls. Its default poller runs every 5 seconds, which is more often than most applications need for runtime health and costs metric volume, so consider slowing it down: diff --git a/lib/sentry/plug_capture.ex b/lib/sentry/plug_capture.ex index ad6a2a33..589afa85 100644 --- a/lib/sentry/plug_capture.ex +++ b/lib/sentry/plug_capture.ex @@ -99,30 +99,22 @@ defmodule Sentry.PlugCapture do ## Crashing Callbacks - This module captures the application's exception from inside `c:Plug.call/2`, - where a failure of its own would replace the error the application raised. It - cannot: if anything in the capture path raises, throws, or exits - the - `:scrubber` callback, the scrubbing of the exception, or the reporting - itself - Sentry catches the failure and re-raises **the application's - original exception, unchanged**. The failure is logged at the `:error` level - with the `:sentry` logger domain, so the SDK never reports its own failure as - an event. + *Available since 14.0.0.* + If anything in the capture path raises, throws, or exits - the `:scrubber` + callback, the scrubbing of the exception, or the reporting itself - this + module still re-raises **the application's original exception, unchanged**. Only the reporting degrades, and only as far as the failure forces: | Failure | What Sentry still reports | | --- | --- | | The `:scrubber` crashes, or returns something other than a `Plug.Conn` | The event, with the conn scrubbed by the built-in scrubber, `Sentry.Scrubber.scrub/1` | | Scrubbing a `Phoenix.ActionClauseError` fails for any other reason | The event, with each of the exception's arguments scrubbed on its own, without mirroring the conn's scrubbed params onto the action's params argument | - | Capturing the event itself fails | Nothing - the log is the only record of the error | - - > #### A crashed scrubber reports more, not less {: .warning} - > - > The fallback redacts the keys listed in `Sentry.Scrubber.default_param_keys/0` - > and `Sentry.Scrubber.default_header_keys/0`, and nothing more. Data that only - > a custom `:scrubber` was dropping is sent to Sentry for as long as that - > scrubber keeps failing, and the error-level log is the only signal. + | Capturing the event itself fails | Nothing - the error-level log is the only record of the error | + See the [*Crashing Callbacks*](`m:Sentry#module-crashing-callbacks`) section of + the `Sentry` documentation for how the failure is logged and why a crashed + scrubber sends data that only it was dropping. """ defmacro __using__(opts) do quote do diff --git a/lib/sentry/plug_context.ex b/lib/sentry/plug_context.ex index 98f09ea9..54350ac3 100644 --- a/lib/sentry/plug_context.ex +++ b/lib/sentry/plug_context.ex @@ -167,15 +167,11 @@ defmodule Sentry.PlugContext do ## Crashing Callbacks - Every callback this plug accepts runs in the request process. If one raises, - throws, or exits, Sentry catches the failure rather than letting it reach the - rest of your pipeline, so **the request itself is unaffected** and is served - exactly as it would have been. The failure is logged at the `:error` level with - the `:sentry` logger domain, so the SDK never reports its own callback failure - as an event. + *Available since 14.0.0.* - Only the field that callback was responsible for degrades, and it degrades to - the SDK's own default for that field: + If a callback this plug accepts raises, throws, or exits, the request is still + served and the event is still sent. Only the field that callback was + responsible for falls back to the SDK's own default for that field: | Option | Value reported after a crash | | --- | --- | @@ -185,18 +181,10 @@ defmodule Sentry.PlugContext do | `:url_scrubber` | `default_url_scrubber/1` | | `:remote_address_reader` | the `x-forwarded-for` header, falling back to `conn.remote_ip` | - The other fields are still produced by their own callbacks, and the event is - still sent. - - > #### A crashed scrubber reports more, not less {: .warning} - > - > The fallback is the SDK default, which redacts the keys listed in - > `Sentry.Scrubber.default_param_keys/0` and `Sentry.Scrubber.default_header_keys/0` - > and nothing more. A custom scrubber that dropped a field the default keeps - - > an internal identifier, a request body the default has no rule for - stops - > dropping it for as long as it keeps failing, and that data is sent to Sentry. - > The error-level log is the only signal, so alert on it rather than treating a - > custom scrubber as a guarantee. + The other fields are still produced by their own callbacks. See the + [*Crashing Callbacks*](`m:Sentry#module-crashing-callbacks`) section of the + `Sentry` documentation for how the failure is logged and why a crashed + scrubber sends data that only it was dropping. """ if Code.ensure_loaded?(Plug) do diff --git a/lib/sentry/scrubber.ex b/lib/sentry/scrubber.ex index 502c0007..754da70a 100644 --- a/lib/sentry/scrubber.ex +++ b/lib/sentry/scrubber.ex @@ -43,8 +43,7 @@ defmodule Sentry.Scrubber do ## Defaults The default sensitive *parameter* keys (used for body params, query strings, - and arbitrary maps) are the denylist required by the - [Sentry Data Collection spec](https://develop.sentry.dev/sdk/foundations/client/data-collection/): + and arbitrary maps) are: #{Enum.map_join(@default_scrubbed_param_keys, "\n", &" * `\"#{&1}\"`")} @@ -246,8 +245,6 @@ defmodule Sentry.Scrubber do @doc """ Returns the placeholder that replaces redacted values: `"[Filtered]"`. - - *Changed in 14.0.0:* returns `"[Filtered]"` instead of `"*********"`. """ @doc since: "13.1.0" @spec scrubbed_value() :: String.t() @@ -256,10 +253,9 @@ defmodule Sentry.Scrubber do @doc """ Returns the SDK default list of sensitive parameter keys. - This is the denylist required by the - [Sentry Data Collection spec](https://develop.sentry.dev/sdk/foundations/client/data-collection/), - matched as a case-insensitive substring of the key name. The - `scrubber: [param_keys: ...]` configuration option extends it. + A key is sensitive when any of these terms appears anywhere in its name, + compared case-insensitively. The `scrubber: [param_keys: ...]` configuration + option extends this list; it cannot shorten it. """ @doc since: "13.1.0" @spec default_param_keys() :: [String.t()] diff --git a/lib/sentry/telemetry/buffer.ex b/lib/sentry/telemetry/buffer.ex index cb94f394..1552fb3e 100644 --- a/lib/sentry/telemetry/buffer.ex +++ b/lib/sentry/telemetry/buffer.ex @@ -124,6 +124,7 @@ defmodule Sentry.Telemetry.Buffer do Returns milliseconds until a pending batch is ready, or `:infinity` when the buffer is empty or a partial batch has no timeout. """ + @doc since: "14.0.0" @spec next_timeout(GenServer.server()) :: timeout() def next_timeout(server) do GenServer.call(server, :next_timeout) diff --git a/pages/upgrade-14.x.md b/pages/upgrade-14.x.md index a532cb6d..8a12eb8b 100644 --- a/pages/upgrade-14.x.md +++ b/pages/upgrade-14.x.md @@ -64,3 +64,13 @@ config :sentry, ``` The transaction is dropped only once the response status is known, so the trace has already been propagated as sampled. Services called while handling the request still report their spans, which appear in Sentry without their root transaction. + +## Check How You Handle `Sentry.capture_check_in/1` Results + +Check-ins are now handled by the Telemetry Processor by default, and as a result, `Sentry.capture_check_in/1` returns `{:ok, check_in_id}` right away instead of waiting for the HTTP request, and a failure to send the check-in is no longer returned as `{:error, reason}`. Call `Sentry.flush/1` if you need to wait until buffered check-ins are sent. + +## Review the Default Scrubbed Parameter Keys + +`Sentry.Scrubber.default_param_keys/0` now returns a longer denylist instead of `["password", "passwd", "secret"]`, and its terms match as case-insensitive substrings of the key name instead of exact key names. For example, `"auth"` now scrubs both `"Authorization"` and `"X-Auth-Token"`. + +Parameters that used to reach Sentry may now be scrubbed. See `Sentry.Scrubber` for the full list. Terms you add with `scrubber: [param_keys: ...]` extend this list; it can't be shortened.