Set Up Logs

Structured logs allow you to send, view and query logs sent from your applications within Sentry.

With Sentry Structured Logs, you can send text-based log information from your applications to Sentry. Once in Sentry, these logs can be viewed alongside relevant errors, searched by text-string, or searched using their individual attributes.

Logs for Elixir are supported in Sentry Elixir SDK version 12.0.0 and above.

Copied
mix deps.get sentry

Or add it to your mix.exs:

Copied
defp deps do
  [
    {:sentry, "~> 12.0"}
  ]
end

To enable logging, set enable_logs: true in your Sentry configuration:

Copied
# In config/config.exs or config/runtime.exs
config :sentry,
  dsn: "___PUBLIC_DSN___",
  enable_logs: true

When enable_logs is true, the SDK automatically attaches a Sentry.LoggerHandler (registered as :sentry_log_handler) on application startup. No manual handler setup is required.

To configure the minimum log level and other options, use the :logs key:

Copied
config :sentry,
  dsn: "___PUBLIC_DSN___",
  enable_logs: true,
  logs: [
    level: :info,         # minimum log level (default: :info)
    excluded_domains: [], # logger domains to exclude (default: [])
    metadata: []          # metadata keys to include as attributes (default: [])
  ]

Once enable_logs: true is set in your Sentry configuration, you can send logs using Elixir's standard Logger module.

The logs will be sent to Sentry at or above the level configured by the :level option under :logs (default: :info). The supported log levels in Elixir are: debug, info, notice, warning, error, critical, alert, and emergency.

Copied
require Logger

Logger.info("Updated global cache")

Logger.debug("Cache miss for user", user_id: 123)

Logger.warning("Rate limit reached for endpoint", endpoint: "/api/results/")

Logger.error("Failed to process payment", order_id: "or_2342", amount: 99.99)

You can use message templates with positional or named parameters. To use message templates, pass parameters via the :sentry metadata key with :log_parameters:

Copied
# Using named parameters (Elixir format)
Logger.info("User %{name} logged in",
  sentry: [log_parameters: %{name: "Jane Doe"}]
)

# Using positional parameters
Logger.info("User %s logged in",
  sentry: [log_parameters: ["Jane Doe"]]
)

Any metadata passed to Logger calls will be included as log attributes if configured via the :metadata option under :logs. To include all metadata as attributes:

Copied
config :sentry,
  enable_logs: true,
  logs: [
    level: :info,
    metadata: :all  # or [:user_id, :request_id] for specific keys
  ]

Then all metadata will be sent as extra attributes that Sentry Logs UI displays:

Copied
# Here `user_id` and `action` will be sent as extra attributes
Logger.info("User logged in", user_id: 123, action: "create")

If you're using tracing with OpenTelemetry, you can correlate logs with traces so that log events appear alongside spans in the Sentry Trace Explorer.

To enable this, add the opentelemetry_logger_metadata package to your dependencies:

mix.exs
Copied
defp deps do
  [
    {:opentelemetry_logger_metadata, "~> 0.2"},
    # ... your other dependencies
  ]
end

Then call OpentelemetryLoggerMetadata.setup() in your application's start/2 callback:

lib/my_app/application.ex
Copied
def start(_type, _args) do
  OpentelemetryLoggerMetadata.setup()

  # ... rest of your application setup
end

This package injects the active OpenTelemetry trace_id and span_id into Elixir's logger metadata. The Sentry SDK automatically picks up these IDs and includes them in every log event sent to Sentry, linking your logs to the trace they occurred within.

Logs are sent to Sentry through Erlang's :logger system via Sentry.LoggerHandler. When enable_logs: true is set in your Sentry configuration, the SDK automatically attaches the handler — no manual setup is needed. Any logs from your application or libraries that use Elixir's Logger or Erlang's :logger will be captured and sent to Sentry at or above the configured level.

The logs behavior is configured globally via the :logs key — not through the handler config map:

Copied
config :sentry,
  enable_logs: true,
  logs: [
    level: :info,
    metadata: [:request_id, :user_id]
  ]

With this configuration, logs at or above :info will be sent to Sentry:

You can exclude specific logger domains from being sent to Sentry using the :excluded_domains option under :logs:

Copied
config :sentry,
  enable_logs: true,
  logs: [
    level: :info,
    excluded_domains: [:ecto, :phoenix]
  ]

To filter or modify logs before they are sent to Sentry, use the before_send_log callback. Return false to skip a log, or return the log event to send it.

Copied
config :sentry,
  dsn: "___PUBLIC_DSN___",
  enable_logs: true,
  before_send_log: fn log_event ->
    # Skip info logs
    if log_event.level == :info do
      false
    else
      log_event
    end
  end

You can also use a module/function tuple:

Copied
config :sentry,
  dsn: "___PUBLIC_DSN___",
  enable_logs: true,
  before_send_log: {MyApp.Sentry, :before_send_log}

# In lib/my_app/sentry.ex
defmodule MyApp.Sentry do
  def before_send_log(%Sentry.LogEvent{} = log_event) do
    # Filter out logs from specific domains or modify attributes
    if String.contains?(log_event.body, "sensitive") do
      false
    else
      log_event
    end
  end
end

Logs behavior is configured under the :logs key in your Sentry configuration. These options control the auto-attached Sentry.LoggerHandler:

  • :level - The minimum log level to send to Sentry's Logs Protocol. Default: :info. Supported values: :debug, :info, :notice, :warning, :error, :critical, :alert, :emergency.

  • :excluded_domains - A list of logger domains to exclude from logs sent to Sentry. Default: [].

  • :metadata - Logger metadata keys to include as attributes in log events. Set to :all to include all metadata, or a list of specific keys like [:request_id, :user_id]. Default: [].

Copied
config :sentry,
  dsn: "___PUBLIC_DSN___",
  enable_logs: true,
  logs: [
    level: :info,
    excluded_domains: [:ecto],
    metadata: [:request_id, :user_id] # or :all
  ]

These options are set in your Sentry configuration (config :sentry):

  • :enable_logs - Set to true to enable the logs feature. When enabled, the SDK automatically attaches a Sentry.LoggerHandler and routes log events through the SDK's Telemetry Processor. Default is false.

  • :before_send_log - A callback function to filter or modify log events before they are sent.

Log events are buffered by the Telemetry Processor with a capacity of 1000 entries and flushed in batches of 100 or every 5 seconds, whichever comes first. You can customize these defaults through the Telemetry Processor options.

Copied
config :sentry,
  dsn: "___PUBLIC_DSN___",
  enable_logs: true,
  before_send_log: {MyApp.Sentry, :before_send_log}

The Elixir SDK automatically sets several default attributes on all log entries to provide context and improve debugging:

  • environment: The environment set in the SDK if defined. This is sent from the SDK as sentry.environment.
  • release: The release set in the SDK if defined. This is sent from the SDK as sentry.release.
  • sdk.name: The name of the SDK that sent the log. This is sent from the SDK as sentry.sdk.name.
  • sdk.version: The version of the SDK that sent the log. This is sent from the SDK as sentry.sdk.version.

If the log was parameterized, Sentry adds the message template and parameters as log attributes.

  • message.template: The parameterized template string. This is sent from the SDK as sentry.message.template.
  • message.parameter.X: The parameters to fill the template string. X can either be the number that represent the parameter's position in the template string (sentry.message.parameter.0, sentry.message.parameter.1, etc) or the parameter's name (sentry.message.parameter.item_id, sentry.message.parameter.user_id, etc). This is sent from the SDK as sentry.message.parameter.X.

  • server.address: The address of the server that sent the log. Equivalent to server_name that gets attached to Sentry errors.

If you're using OpenTelemetry with the opentelemetry_logger_metadata package, the following attributes are automatically included:

  • trace_id: The OpenTelemetry trace ID from the active trace context. Links the log to a specific trace in Sentry's Trace Explorer.
  • span_id: The OpenTelemetry span ID from the active span context. Links the log to a specific span within the trace.

These attributes allow you to navigate from a log entry directly to the trace it occurred within, and vice versa.

If no OpenTelemetry context is available (for example, if opentelemetry_logger_metadata is not installed or the log occurs outside a traced operation), the SDK generates a random trace_id for each log event. In this case, span_id is not set, and logs are not connected to any trace in Sentry.

Was this helpful?
Help improve this content
Our documentation is open source and available on GitHub. Your contributions are welcome, whether fixing a typo (drat!) or suggesting an update ("yeah, this would be better").