View Source Sentry.LoggerHandler (Sentry v10.5.0)

:logger handler to report logged events to Sentry.

This module is similar to Sentry.LoggerBackend, but it implements a :logger handler rather than an Elixir's Logger backend. It provides additional functionality compared to the Logger backend, such as rate-limiting of reported messages, better fingerprinting, and better handling of crashes.

This module is available since v9.0.0 of this library.

When to Use the Handler vs the Backend?

There is no functional difference in behavior between Sentry.LoggerHandler and Sentry.LoggerBackend when it comes to reporting to Sentry. The main functional difference is that Sentry.LoggerBackend runs in its own process, while Sentry.LoggerHandler runs in the process that logs. The latter is generally preferable.

The reason both exist is that :logger handlers are a relatively-new feature in Erlang/OTP, and Sentry.LoggerBackend was created before :logger handlers were introduced.

In general, try to use Sentry.LoggerHandler if possible. In future Elixir releases, Logger backends may become deprecated and hence Sentry.LoggerBackend may be eventually removed.

crash-reports

Crash Reports

The reason you'll want to add this handler to your application is so that you can report crashes in your system to Sentry. Sometimes, you're able to catch exceptions and handle them (such as reporting them to Sentry), which is what you can do with Sentry.PlugCapture for example.

However, Erlang/OTP systems are made of processes running concurrently, and sometimes those processes crash and exit. If you're not explicitly catching exceptions in those processes to report them to Sentry, then you won't see those crash reports in Sentry. That's where this handler comes in. This handler hooks into :logger and reports nicely-formatted crash reports to Sentry.

usage

Usage

To add this handler to your system, see the documentation for handlers in Elixir.

You can configure this handler in the :logger key under your application's configuration, potentially alongside other :logger handlers:

config :my_app, :logger, [
  {:handler, :my_sentry_handler, Sentry.LoggerHandler, %{
    config: %{metadata: [:file, :line]}
  }}
]

If you do this, then you'll want to add this to your application's Application.start/2 callback, similarly to what you would do with Sentry.LoggerBackend and the call to Logger.add_backend/1:

def start(_type, _args) do
  Logger.add_handlers(:my_app)

  # ...
end

Alternatively, you can skip the :logger configuration and add the handler directly to your application's Application.start/2 callback:

def start(_type, _args) do
  :logger.add_handler(:my_sentry_handler, Sentry.LoggerHandler, %{
    config: %{metadata: [:file, :line]}
  })

  # ...
end

configuration

Configuration

This handler supports the following configuration options:

  • :level (Logger.level/0) - The minimum Logger level to send events for. The default value is :error.

  • :excluded_domains (list of atom/0) - Any messages with a domain in the configured list will not be sent. The default is so as to avoid double-reporting events from Sentry.PlugCapture. The default value is [:cowboy].

  • :metadata (list of atom/0, or :all) - Use this to include non-Sentry logger metadata in reports. If it's a list of keys, metadata in those keys will be added in the :extra context (see Sentry.Context.set_extra_context/1) under the :logger_metadata key. If set to :all, all metadata will be included. The default value is [].

  • :capture_log_messages (boolean/0) - When true, this module will report all logged messages to Sentry (provided they're not filtered by :excluded_domains and :level). The default of false means that the handler will only send crash reports, which are messages with metadata that has the shape of an exit reason and a stacktrace. The default value is false.

  • :rate_limiting (keyword/0 or nil) - since v10.4.0 - If present, enables rate limiting of reported messages. This can help avoid "spamming" Sentry with repeated log messages. To disable rate limiting, set this to nil or don't pass it altogether.

    • :max_events (non_neg_integer/0) - Required. The maximum number of events to send to Sentry in the :interval period.

    • :interval (non_neg_integer/0) - Required. The interval (in milliseconds) to send :max_events events.

    The default value is nil.

examples

Examples

To log all messages with level :error and above to Sentry, set :capture_log_messages to true:

config :my_app, :logger, [
  {:handler, :my_sentry_handler, Sentry.LoggerHandler, %{
    config: %{metadata: [:file, :line], capture_log_messages: true, level: :error}
  }}
]

Now, logs like this will be reported as messages to Sentry:

Logger.error("Something went wrong")

If you want to customize options for the reported message, use the :sentry metadata key in the Logger call. For example, to add a tag to the Sentry event:

Logger.error("Something went wrong", sentry: [tags: %{my_tag: "my_value"}])

Sentry context (in :sentry) is also read from the logger metadata, so you can configure it for a whole process (with Logger.metadata/1). Last but not least, context is also read from the ancestor chain of the process (:"$callers"), so if you set :sentry context in a process and then spawn something like a task or a GenServer from that process, the context will be included in the reported messages.