Packages
sentry
12.0.2
13.3.0
13.2.0
13.1.0
13.0.1
13.0.0
12.0.3
12.0.2
12.0.1
12.0.0
11.0.4
11.0.3
11.0.2
11.0.1
11.0.0
10.10.0
10.9.0
10.8.1
10.8.0
10.7.1
10.7.0
10.6.2
10.6.1
10.6.0
10.5.0
10.4.0
10.3.0
10.2.1
10.2.0
10.2.0-rc.2
10.2.0-rc.1
10.1.0
10.0.3
10.0.2
10.0.1
10.0.0
9.1.0
9.0.0
8.1.0
8.0.6
8.0.5
8.0.4
8.0.3
8.0.2
8.0.1
8.0.0
8.0.0-rc.2
8.0.0-rc.1
8.0.0-rc.0
retired
7.2.5
7.2.4
7.2.3
7.2.2
7.2.1
7.2.0
7.1.0
7.0.6
7.0.5
7.0.4
7.0.3
7.0.2
7.0.1
7.0.0
6.4.2
6.4.1
6.4.0
6.3.0
6.2.1
6.2.0
6.1.0
6.0.5
6.0.4
6.0.3
6.0.2
6.0.1
6.0.0
5.0.1
5.0.0
4.0.3
4.0.2
4.0.1
4.0.0
3.0.0
2.2.0
2.1.0
2.0.2
2.0.1
2.0.0
1.1.2
1.1.1
1.1.0
1.0.0
0.3.2
0.3.1
0.3.0
0.2.0
0.1.3
0.1.2
0.1.1
0.1.0
The Official Elixir client for Sentry
Current section
Files
Jump to
Current section
Files
lib/sentry/application.ex
defmodule Sentry.Application do
@moduledoc false
use Application
require Logger
alias Sentry.Config
@impl true
def start(_type, _opts) do
config = Config.validate!()
:ok = Config.persist(config)
Config.put_config(
:in_app_module_allow_list,
Config.in_app_module_allow_list() ++ resolve_in_app_module_allow_list()
)
http_client = Keyword.fetch!(config, :client)
maybe_http_client_spec =
if {:module, http_client} == Code.ensure_loaded(http_client) and
function_exported?(http_client, :child_spec, 0) do
[http_client.child_spec()]
else
[]
end
integrations_config = Config.integrations()
maybe_span_storage =
if Config.tracing?() do
[Sentry.OpenTelemetry.SpanStorage]
else
[]
end
telemetry_processor =
[
{Sentry.TelemetryProcessor,
[
buffer_capacities: Config.telemetry_buffer_capacities(),
scheduler_weights: Config.telemetry_scheduler_weights(),
transport_capacity: Config.transport_capacity()
]}
]
children =
[
{Registry, keys: :unique, name: Sentry.Transport.SenderRegistry},
Sentry.Sources,
Sentry.Dedupe,
Sentry.ClientReport.Sender,
{Sentry.Integrations.CheckInIDMappings,
[
max_expected_check_in_time:
Keyword.fetch!(integrations_config, :max_expected_check_in_time)
]}
] ++
maybe_http_client_spec ++
maybe_span_storage ++
telemetry_processor ++
maybe_rate_limiter() ++
[Sentry.Transport.SenderPool]
cache_loaded_applications()
with {:ok, pid} <-
Supervisor.start_link(children, strategy: :one_for_one, name: Sentry.Supervisor) do
start_integrations(integrations_config)
maybe_add_logger_handler()
{:ok, pid}
end
end
defp cache_loaded_applications do
apps_with_vsns =
if Config.report_deps?() do
Map.new(Application.loaded_applications(), fn {app, _description, vsn} ->
{Atom.to_string(app), to_string(vsn)}
end)
else
%{}
end
:persistent_term.put({:sentry, :loaded_applications}, apps_with_vsns)
end
defp start_integrations(config) do
if config[:oban][:cron][:enabled] do
Sentry.Integrations.Oban.Cron.attach_telemetry_handler(config[:oban][:cron])
end
if config[:oban][:capture_errors] do
Sentry.Integrations.Oban.ErrorReporter.attach(config[:oban])
end
if config[:quantum][:cron][:enabled] do
Sentry.Integrations.Quantum.Cron.attach_telemetry_handler()
end
if config[:telemetry][:report_handler_failures] do
Sentry.Integrations.Telemetry.attach()
end
end
defp resolve_in_app_module_allow_list do
Enum.flat_map(Config.in_app_otp_apps(), fn app ->
case :application.get_key(app, :modules) do
{:ok, modules} -> modules
_ -> []
end
end)
end
defp maybe_add_logger_handler do
if Config.enable_logs?() do
unless sentry_logger_handler_registered?() do
case :logger.add_handler(:sentry_log_handler, Sentry.LoggerHandler, %{config: %{}}) do
:ok ->
:ok
{:error, reason} ->
Logger.warning("[Sentry] Failed to add logger handler: #{inspect(reason)}")
end
end
else
_ = :logger.remove_handler(:sentry_log_handler)
end
:ok
end
defp sentry_logger_handler_registered? do
:logger.get_handler_config()
|> Enum.any?(fn %{module: module} -> module == Sentry.LoggerHandler end)
end
# In tests, we do not run a global rate limiter; tests start their own when
# they need it.
if Mix.env() == :test do
defp maybe_rate_limiter, do: []
else
defp maybe_rate_limiter, do: [Sentry.Transport.RateLimiter]
end
end