View Source Sentry (Sentry v10.6.0)

Provides the functionality to submit events to Sentry.

This library can be used to submit events to Sentry from any Elixir application. It supports several ways of reporting events:

usage

Usage

Add the following to your production configuration:

# In config/prod.exs
config :sentry, dsn: "https://public:secret@app.getsentry.com/1",
  environment_name: :prod,
  tags: %{
    env: "production"
  }

Sentry uses the :dsn option to determine whether it should record exceptions. If :dsn is set, then Sentry records exceptions. If it's not set or set to nil, then simply no events are sent to Sentry.

Included Environments

Before v10.0.0, the recommended way to control whether to report events to Sentry was the :included_environments option (a list of environments to report events for). This was used together with the :environment_name option to determine whether to send events. :included_environments is deprecated in v10.0.0 in favor of setting or not setting :dsn. It will be removed in v11.0.0.

You can even rely on more specific logic to determine the environment name. It's not uncommon for most applications to have a "staging" environment. In order to handle this without adding an additional Mix environment, you can set an environment variable that determines the release level. By default, Sentry picks up the SENTRY_ENVIRONMENT variable (at runtime, when starging). Otherwise, you can read the variable at runtime. Do this only in config/runtime.exs so that it will work both for local development as well as Mix releases.

# In config/runtime.exs
if config_env() == :prod do
  config :sentry, dsn: "https://public:secret@app.getsentry.com/1",
    environment_name: System.fetch_env!("RELEASE_LEVEL")
end

In this example, we are getting the environment name from the RELEASE_LEVEL environment variable. Now, on our servers, we can set the environment variable appropriately. The config_env() == :prod check ensures that we only set :dsn in production, effectively only enabling reporting in production-like environments.

Sentry supports many configuration options. See the Configuration section for complete documentation.

configuration

Configuration

You can configure Sentry through the application environment. Configure the following keys under the :sentry application. For example, you can do this in config/config.exs:

# config/config.exs
config :sentry,
  # ...

Sentry reads the configuration when the :sentry application starts, and will not pick up any changes after that. This is in line with how other Sentry SDKs (and many other Erlang/Elixir libraries) work. The reason for this choice is performance: the SDK performs validation on application start and then caches the configuration (in :persistent_term).

Updating Configuration at Runtime

If you must update configuration at runtime, use put_config/2. This function is not efficient (since it updates terms in :persistent_term), but it works in a pinch. For example, it's useful if you're verifying that you send the right events to Sentry in your test suite, so you need to change the :dsn configuration to point to a local server that you can verify requests on.

Below you can find all the available configuration options.

Basic Options

  • :dsn (String.t/0 or nil) - The DSN for your Sentry project. If this is not set, Sentry will not be enabled. If the SENTRY_DSN environment variable is set, it will be used as the default value. If :test_mode is true, the :dsn option is sometimes ignored; see Sentry.Test for more information. The default value is nil.

  • :environment_name (String.t/0 or atom/0) - The current environment name. This is used to specify the environment that an event happened in. It can be any string shorter than 64 bytes, except the string "None". When Sentry receives an event with an environment, it creates that environment if it doesn't exist yet. If the SENTRY_ENVIRONMENT environment variable is set, it will be used as the value for this option. The default value is "production".

  • :included_environments (list of atom/0 or String.t/0, or the atom :all) - Deprecated. The environments in which Sentry can report events. If this is a list, then :environment_name needs to be in this list for events to be reported. If this is :all, then Sentry will report events regardless of the value of :environment_name. This will be removed in v11.0.0.

  • :release (String.t/0 or nil) - The release version of your application. This is used to correlate events with source code. If the SENTRY_RELEASE environment variable is set, it will be used as the default value. The default value is nil.

  • :json_library (module/0) - A module that implements the "standard" Elixir JSON behaviour, that is, exports the encode/1 and decode/1 functions. If you use the default, make sure to add :jason as a dependency of your application. The default value is Jason.

  • :server_name (String.t/0) - The name of the server running the application. Not used by default.

  • :sample_rate (float/0) - The percentage of events to send to Sentry. A value of 0.0 will deny sending any events, and a value of 1.0 will send 100% of events. Sampling is applied after the :before_send callback. See where the Sentry documentation suggests this. Must be between 0.0 and 1.0 (included). The default value is 1.0.

  • :tags (map of term/0 keys and term/0 values) - A map of tags to be sent with every event. The default value is %{}.

  • :max_breadcrumbs (non_neg_integer/0) - The maximum number of breadcrumbs to keep. See Sentry.Context.add_breadcrumb/1. The default value is 100.

  • :report_deps (boolean/0) - Whether to report application dependencies of your application alongside events. This list contains applications (alongside their version) that are loaded when the :sentry application starts. The default value is true.

  • :log_level - The level to use when Sentry fails to send an event due to an API failure or other reasons. The default value is :warning.

  • :in_app_module_allow_list (list of module/0) - A list of modules that is used to distinguish among stacktrace frames that belong to your app and ones that are part of libraries or core Elixir. This is used to better display the significant part of stacktraces. The logic is "greedy", so if your app's root module is MyApp and you configure this option to [MyApp], MyApp as well as any submodules (like MyApp.Submodule) would be considered part of your app. Defaults to []. The default value is [].

  • :filter (module/0) - A module that implements the Sentry.EventFilter behaviour. Defaults to Sentry.DefaultEventFilter. See the Filtering Exceptions section below. The default value is Sentry.DefaultEventFilter.

  • :dedup_events (boolean/0) - Whether to deduplicate events before reporting them to Sentry. If this option is true, then the SDK will store reported events for around 30 seconds after they're reported. Any time the SDK is about to report an event, it will check if it has already reported within the past 30 seconds. If it has, then it will not report the event again, and will log a message instead. Events are deduplicated by comparing their message, exception, stacktrace, and fingerprint. Available since v10.0.0. The default value is true.

  • :test_mode (boolean/0) - Whether to enable test mode. When test mode is enabled, the SDK will check whether there is a process collecting events and avoid sending those events if that's the case. This is useful for testing—see Sentry.Test. :test_mode works in tandem with :dsn; this is described in detail in Sentry.Test. The default value is false.

  • :integrations (keyword/0) - Configuration for integrations with third-party libraries. Every integration has its own option and corresponding configuration options. The default value is [].

    • :oban (keyword/0) - Configuration for the Oban integration. The Oban integration requires at minumum Oban Pro v0.14 or Oban v.2.17.6. Available since v10.2.0.

      • :capture_errors (boolean/0) - Whether to capture errors from Oban jobs. When enabled, the Sentry SDK will capture errors that happen in Oban jobs, including when errors return {:error, reason} tuples. Available since 10.3.0. The default value is false.

      • :cron (keyword/0) - Configuration options for configuring crons for Oban.

        • :enabled (boolean/0) - Whether to enable the Oban integration. When enabled, the Sentry SDK will capture check-ins for Oban jobs. Available since v10.2.0. The default value is false.
    • :quantum (keyword/0) - Configuration for the Quantum integration. Available since v10.2.0.

      • :cron (keyword/0) - Configuration options for configuring crons for Quantum.
        • :enabled (boolean/0) - Whether to enable the Quantum integration. When enabled, the Sentry SDK will capture check-ins for Quantum jobs. Available since v10.2.0. The default value is false.

Hook Options

These options control hooks that this SDK can call before or after sending events.

  • :before_send (before_send_event_callback/0) - Allows performing operations on the event before it is sent as well as filtering out the event altogether. If the callback returns nil or false, the event is not reported. If it returns an updated Sentry.Event, then the updated event is used instead. See the Event Callbacks section below for more information.

    :before_send is available since v10.0.0. Before, it was called :before_send_event.

  • :before_send_event (before_send_event_callback/0) - Exactly the same as :before_send, but has been deprecated since v10.0.0.

  • :after_send_event (after_send_event_callback/0) - Callback that is called after attempting to send an event. The result of the HTTP call as well as the event will be passed as arguments. The return value of the callback is not returned. See the Event Callbacks section below for more information.

Transport Options

These options control how this Sentry SDK sends events to the Sentry server.

  • :send_result (send_type/0) - Controls what to return when reporting exceptions to Sentry. The default value is :none.

  • :client (module/0) - A module that implements the Sentry.HTTPClient behaviour. Defaults to Sentry.HackneyClient, which uses hackney as the HTTP client. The default value is Sentry.HackneyClient.

  • :send_max_attempts (pos_integer/0) - The maximum number of attempts to send an event to Sentry. The default value is 4.

  • :hackney_opts (keyword/0) - Options to be passed to hackney. Only applied if :client is set to Sentry.HackneyClient. The default value is [pool: :sentry_pool].

  • :hackney_pool_timeout (timeout/0) - The maximum time to wait for a connection to become available. Only applied if :client is set to Sentry.HackneyClient. The default value is 5000.

  • :hackney_pool_max_connections (pos_integer/0) - The maximum number of connections to keep in the pool. Only applied if :client is set to Sentry.HackneyClient. The default value is 50.

Source Code Context Options

These options control how source code context is reported alongside events.

  • :enable_source_code_context (boolean/0) - Whether to report source code context alongside events. The default value is false.

  • :root_source_code_paths (list of Path.t/0) - Aa list of paths to the root of your application's source code. This is used to determine the relative path of files in stack traces. Usually, you'll want to set this to [File.cwd!()]. For umbrella apps, you should set this to all the application paths in your umbrella (such as [Path.join(File.cwd!(), "apps/app1"), ...]). Required if :enabled_source_code_context is true. The default value is [].

  • :source_code_path_pattern (String.t/0) - A glob pattern used to determine which files to report source code context for. The glob "starts" from :root_source_code_paths. The default value is "**/*.ex".

  • :source_code_exclude_patterns (list of Regex.t/0) - A list of regular expressions used to determine which files to exclude from source code context. The default value is [~r/\/_build\//, ~r/\/deps\//, ~r/\/priv\//, ~r/\/test\//].

  • :source_code_map_path (Path.t/0) - The path to the source code map file. See mix sentry.package_source_code. Defaults to a private path inside Sentry's priv directory. Available since v10.2.0.

  • :context_lines (pos_integer/0) - The number of lines of source code before and after the line that caused the exception to report. The default value is 3.

Configuration Through System Environment

Sentry supports loading some configuration from the system environment. The supported environment variables are: SENTRY_RELEASE, SENTRY_ENVIRONMENT, and SENTRY_DSN. See the :release, :environment_name, and :dsn configuration options respectively for more information.

filtering-exceptions

Filtering Exceptions

If you would like to prevent Sentry from sending certain exceptions, you can use the :before_send configuration option. See the Event Callbacks section below.

Before v9.0.0, the recommended way to filter out exceptions was to use a filter, that is, a module implementing the Sentry.EventFilter behaviour. This is still supported, but is not deprecated. See Sentry.EventFilter for more information.

event-callbacks

Event Callbacks

You can configure the :before_send and :after_send_event options to customize what happens before and/or after sending an event. The :before_send callback must be of type before_send_event_callback/0 and the :after_send_event callback must be of type after_send_event_callback/0. For example, you can set:

config :sentry,
  before_send: {MyModule, :before_send},
  after_send_event: {MyModule, :after_send}

MyModule could look like this:

defmodule MyModule do
  def before_send(event) do
    metadata = Map.new(Logger.metadata())
    %Sentry.Event{event | extra: Map.merge(event.extra, metadata)}
  end

  def after_send_event(event, result) do
    case result do
      {:ok, id} ->
        Logger.info("Successfully sent event!")

      {:error, _reason} ->
        Logger.info(fn -> "Did not successfully send event! #{inspect(event)}" end)
    end
  end
end

reporting-source-code

Reporting Source Code

Sentry supports reporting the source code of (and around) the line that caused an issue. An example configuration to enable this functionality is:

config :sentry,
  dsn: "https://public:secret@app.getsentry.com/1",
  enable_source_code_context: true,
  root_source_code_paths: [File.cwd!()],
  context_lines: 5

To support this functionality, Sentry needs to package source code and store it so that it's available in the compiled application. Packaging source code is an active step you have to take; use the mix sentry.package_source_code Mix task to do that.

Sentry stores the packaged source code in its priv directory. This is included by default in Mix releases. Once the source code is packaged and ready to ship with your release, Sentry will load it when the :sentry application starts. If there are issues with loading the packaged code, Sentry will log some warnings but will boot up normally and it just won't report source code context.

Prune Large File Trees

Due to Sentry reading the file system and defaulting to a recursive search of directories, it is important to check your configuration and compilation environment to avoid a folder recursion issue. You might see problems when deploying to the root folder, so it is best to follow the practice of compiling your application in its own folder. Modifying the :source_code_path_pattern configuration option from its default is also an avenue to avoid compile problems, as well as pruning unnecessary files with :source_code_exclude_patterns.

Link to this section Summary

Types

A callback to use with the :after_send_event configuration option.

A callback to use with the :before_send configuration option. configuration options.k

The strategy to use when sending an event to Sentry.

Functions

Captures a check-in built with the given options.

Parses and submits an exception to Sentry.

Reports a message to Sentry.

Returns the currently-set Sentry DSN, if set (or nil otherwise).

Gets the last event ID sent to the server from the process dictionary. Since it uses the process dictionary, it will only return the last event ID sent within the current process.

Updates the value of key in the configuration at runtime.

Puts the last event ID sent to the server for the current process in the process dictionary.

Sends an event to Sentry.

Link to this section Types

Link to this type

after_send_event_callback()

View Source (since 9.0.0)
@type after_send_event_callback() ::
  (Sentry.Event.t(), result :: term() -> term())
  | {module(), function_name :: atom()}

A callback to use with the :after_send_event configuration option.

If this is {module, function_name}, then module.function_name(event, result) will be called, where event is of type Sentry.Event.t/0.

Link to this type

before_send_event_callback()

View Source (since 9.0.0)
@type before_send_event_callback() ::
  (Sentry.Event.t() -> as_boolean(Sentry.Event.t()))
  | {module(), function_name :: atom()}

A callback to use with the :before_send configuration option. configuration options.k

If this is {module, function_name}, then module.function_name(event) will be called, where event is of type Sentry.Event.t/0.

See the Configuration section in the module documentation for more information on configuration.

@type send_result() ::
  {:ok, event_or_envelope_id :: String.t()}
  | {:error, term()}
  | :ignored
  | :unsampled
  | :excluded
Link to this type

send_type()

View Source (since 9.0.0)
@type send_type() :: :sync | :none

The strategy to use when sending an event to Sentry.

Link to this section Functions

Link to this function

capture_check_in(options)

View Source (since 10.2.0)
@spec capture_check_in(keyword()) ::
  {:ok, check_in_id :: String.t()} | :ignored | {:error, term()}

Captures a check-in built with the given options.

Check-ins are used to report the status of a monitor to Sentry. This is used to track the health and progress of cron jobs. This function is somewhat low level, and mostly useful when you want to report the status of a cron but you are not using any common library to manage your cron jobs.

This function performs a synchronous HTTP request to Sentry. If the request performs successfully, it returns {:ok, check_in_id} where check_in_id is the ID of the check-in that was sent to Sentry. You can use this ID to send updates about the same check-in. If the request fails, it returns {:error, reason}.

Setting the DSN

If the :dsn configuration is not set, this function won't report the check-in to Sentry and will instead return :ignored. This behaviour is consistent with the rest of the SDK (such as capture_exception/2).

options

Options

This functions supports all the options mentioned in Sentry.CheckIn.new/1.

examples

Examples

Say you have a GenServer which periodically sends a message to itself to execute some job. You could monitor the health of this GenServer by reporting a check-in to Sentry.

For example:

@impl GenServer
def handle_info(:execute_periodic_job, state) do
  # Report that the job started.
  {:ok, check_in_id} = Sentry.capture_check_in(status: :in_progress, monitor_slug: "genserver-job")

  :ok = do_job(state)

  # Report that the job ended successfully.
  Sentry.capture_check_in(check_in_id: check_in_id, status: :ok, monitor_slug: "genserver-job")

  {:noreply, state}
end
Link to this function

capture_exception(exception, opts \\ [])

View Source
@spec capture_exception(
  Exception.t(),
  keyword()
) :: send_result()

Parses and submits an exception to Sentry.

This only sends the exception if the :dsn configuration option is set and is not nil. See the Configuration section in the module documentation.

The opts argument is passed as the second argument to send_event/2.

Link to this function

capture_message(message, opts \\ [])

View Source
@spec capture_message(
  String.t(),
  keyword()
) :: send_result()

Reports a message to Sentry.

opts argument is passed as the second argument to send_event/2.

interpolation-since-v10-1-0

Interpolation (since v10.1.0)

The message argument supports interpolation. You can pass a string with formatting markers as %s, ant then pass in the :interpolation_parameters option as a list of positional parameters to interpolate. For example:

Sentry.capture_message("Error with user %s", interpolation_parameters: ["John"])

This way, Sentry will group the messages based on the non-interpolated string, but it will show the interpolated string in the UI.

Missing or Extra Parameters

If the message string has more %s markers than parameters, the extra %s markers are included as is and the SDK doesn't raise any error. If you pass in more interpolation parameters than %s markers, the extra parameters are ignored as well. This is because the SDK doesn't want to be the cause of even more errors in your application when what you're trying to do is report an error in the first place.

Link to this function

get_dsn()

View Source (since 10.6.0)
@spec get_dsn() :: String.t() | nil

Returns the currently-set Sentry DSN, if set (or nil otherwise).

This is useful in situations like capturing user feedback.

Link to this function

get_last_event_id_and_source()

View Source
@spec get_last_event_id_and_source() :: {String.t(), atom() | nil} | nil

Gets the last event ID sent to the server from the process dictionary. Since it uses the process dictionary, it will only return the last event ID sent within the current process.

Link to this function

put_config(key, value)

View Source (since 10.0.0)
@spec put_config(atom(), term()) :: :ok

Updates the value of key in the configuration at runtime.

Once the :sentry application starts, it validates and caches the value of the configuration options you start it with. Because of this, updating configuration at runtime requires this function as opposed to just changing the application environment.

This Function Is Slow

This function updates terms in :persistent_term, which is what this SDK uses to cache configuration. Updating terms in :persistent_term is slow and can trigger full GC sweeps. We recommend only using this function in rare cases, or during tests.

examples

Examples

For example, if you're using Bypass to test that you send the correct events to Sentry:

test "reports the correct event to Sentry" do
  bypass = Bypass.open()

  Bypass.expect(...)

  Sentry.put_config(:dsn, "http://public:secret@localhost:#{bypass.port}/1")
  Sentry.put_config(:send_result, :sync)

  my_function_to_test()
end
Link to this function

put_last_event_id_and_source(event_id, source \\ nil)

View Source

Puts the last event ID sent to the server for the current process in the process dictionary.

Link to this function

send_event(event, opts \\ [])

View Source
@spec send_event(
  Sentry.Event.t(),
  keyword()
) :: send_result()

Sends an event to Sentry.

An event is the most generic payload you can send to Sentry. It encapsulates information about an exception, a message, or any other event that you want to report. To manually build events, see the functions in Sentry.Event.

options

Options

  • :result - Allows specifying how the result should be returned. The possible values are:

    • :sync - Sentry will make an API call synchronously (including retries) and will return {:ok, event_id} if successful.

    • :none - Sentry will send the event in the background, in a fire-and-forget fashion. The function will return {:ok, ""} regardless of whether the API call ends up being successful or not.

  • :sample_rate (float/0) - Same as the global :sample_rate configuration, but applied only to this call. See the module documentation. Available since v10.0.0.

  • :before_send (before_send_event_callback/0) - Same as the global :before_send configuration, but applied only to this call. See the module documentation. Available since v10.0.0.

  • :after_send_event (t:after_send_event_callback/1) - Same as the global :after_send_event configuration, but applied only to this call. See the module documentation. Available since v10.0.0.

  • :client (module/0) - Same as the global :client configuration, but applied only to this call. See the module documentation. Available since v10.0.0.

Async Send

Before v9.0.0 of this library, the :result option also supported the :async value. This would spawn a Task to make the API call, and would return a {:ok, Task.t()} tuple. You could use Task operations to wait for the result asynchronously. Since v9.0.0, this option is not present anymore. Instead, you can spawn a task yourself that then calls this function with result: :sync. The effect is exactly the same.

Sending Exceptions and Messages

This function is low-level, and mostly intended for library developers, or folks that want to have full control on what they report to Sentry. For most use cases, use capture_exception/2 or capture_message/2.