View Source Sentry.LoggerHandler (Sentry v10.8.0)
A highly-configurable :logger
handler
that reports logged messages and crashes to Sentry.
This module is available since v9.0.0 of this library.
When to Use the Handler vs the Backend?
Sentry's Elixir SDK also ships with
Sentry.LoggerBackend
, an ElixirLogger
backend. The backend has similar functionality to this handler. The main functional difference is thatSentry.LoggerBackend
runs in its own process, whileSentry.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, andSentry.LoggerBackend
was created before:logger
handlers were introduced.In general, use
Sentry.LoggerHandler
whenever possible. In future Elixir releases,Logger
backends may become deprecated and henceSentry.LoggerBackend
may be eventually removed.
Features
This logger handler provides the features listed here.
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.
Overload Protection
This handler has built-in overload protection via the :sync_threshold
configuration option. Under normal circumstances, this handler sends events to
Sentry asynchronously, without blocking the logging process. However, if the
number of queued up events exceeds the :sync_threshold
, then this handler
starts blocking the logging process until the event is sent.
Overload protection is available since v10.6.0.
Rate Limiting
You can configure this handler to rate-limit the number of messages it sends to
Sentry. This can help avoid "spamming" Sentry. See the :rate_limiting
configuration
option.
Rate limiting is available since v10.5.0.
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
This handler supports the following configuration options:
:level
(Logger.level/0
) - The minimumLogger
level to send events for. The default value is:error
.:excluded_domains
(list ofatom/0
) - Any messages with a domain in the configured list will not be sent. The default is so as to avoid double-reporting events fromSentry.PlugCapture
. The default value is[:cowboy, :bandit]
.:metadata
(list ofatom/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 (seeSentry.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
) - Whentrue
, this module will report all logged messages to Sentry (provided they're not filtered by:excluded_domains
and:level
). The default offalse
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 isfalse
.:rate_limiting
(keyword/0
ornil
) - 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 tonil
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
.:sync_threshold
(non_neg_integer/0
) - since v10.6.0 - The number of queued events after which this handler switches to sync mode. Generally, this handler sends messages to Sentry asynchronously, equivalent to usingresult: :none
inSentry.send_event/2
. However, if the number of queued events exceeds this threshold, the handler will switch to sync mode, where it starts usingresult: :sync
to block until the event is sent. If you always want to use sync mode, set this option to0
. This option effectively implements overload protection. The default value is100
.
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.