Packages
sentry
13.3.0
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/mix/tasks/sentry.install.ex
defmodule Mix.Tasks.Sentry.Install.Docs do
@moduledoc false
def short_doc do
"Installs sentry. Requires igniter to be installed."
end
def example do
"mix sentry.install --dsn <your_dsn>"
end
def long_doc do
"""
#{short_doc()}
This installer is built with, and requires, igniter to be used. Igniter is a tool
for biulding package installers. For information on how to add igniter to your
project, see the documentation https://hexdocs.pm/igniter/readme.html#installation.
## Example
```bash
#{example()}
```
## Options
* `--dsn` - Your Sentry DSN.
"""
end
end
if Code.ensure_loaded?(Igniter) do
defmodule Mix.Tasks.Sentry.Install do
@shortdoc "#{__MODULE__.Docs.short_doc()}"
@moduledoc __MODULE__.Docs.long_doc()
use Igniter.Mix.Task
@impl Igniter.Mix.Task
def info(_argv, _composing_task) do
%Igniter.Mix.Task.Info{
group: :sentry,
adds_deps: [{:jason, "~> 1.4"}, {:finch, "~> 0.21"}],
example: __MODULE__.Docs.example(),
schema: [dsn: :string],
defaults: [dsn: "<your_dsn>"]
}
end
@impl Igniter.Mix.Task
def igniter(igniter) do
igniter
|> Igniter.Project.Config.configure(
"prod.exs",
:sentry,
[:dsn],
igniter.args.options[:dsn]
)
|> Igniter.Project.Config.configure(
"prod.exs",
:sentry,
[:environment_name],
{:code, quote(do: config_env())}
)
|> Igniter.Project.Config.configure(
"prod.exs",
:sentry,
[:enable_source_code_context],
true
)
|> Igniter.Project.Config.configure(
"prod.exs",
:sentry,
[:root_source_code_paths],
{:code, quote(do: [File.cwd!()])}
)
|> configure_phoenix()
|> add_logger_handler()
|> Igniter.add_notice("""
Sentry:
Add a call to
mix sentry.package_source_code
in your release script to make sure the stacktraces you receive
are correctly categorized.
""")
end
defp add_logger_handler(igniter) do
app_module = Igniter.Project.Application.app_module(igniter)
Igniter.Project.Module.find_and_update_module(igniter, app_module, fn zipper ->
with {:ok, zipper} <- Igniter.Code.Function.move_to_def(zipper, :start, 2),
:error <-
Igniter.Code.Function.move_to_function_call_in_current_scope(
zipper,
{:logger, :add_handler},
[2, 3, 4],
&Igniter.Code.Function.argument_equals?(&1, 1, Sentry.LoggerHandler)
) do
code =
"""
:logger.add_handler(:sentry_handler, Sentry.LoggerHandler, %{
config: %{metadata: [:file, :line]}
})
"""
{:ok, Igniter.Code.Common.add_code(zipper, code, placement: :before)}
else
_ -> {:ok, zipper}
end
end)
|> case do
{:ok, igniter} -> igniter
_ -> igniter
end
end
defp configure_phoenix(igniter) do
{igniter, routers} =
Igniter.Libs.Phoenix.list_routers(igniter)
{igniter, endpoints} =
Enum.reduce(routers, {igniter, []}, fn router, {igniter, endpoints} ->
{igniter, new_endpoints} = Igniter.Libs.Phoenix.endpoints_for_router(igniter, router)
{igniter, endpoints ++ new_endpoints}
end)
Enum.reduce(endpoints, igniter, fn endpoint, igniter ->
igniter
|> setup_endpoint(endpoint)
end)
end
defp setup_endpoint(igniter, endpoint) do
# Sentry.PlugCapture is only recommended for Cowboy; on Bandit it can
# result in duplicate errors.
uses_cowboy? = Igniter.Project.Deps.has_dep?(igniter, :plug_cowboy)
Igniter.Project.Module.find_and_update_module!(igniter, endpoint, fn zipper ->
zipper
|> maybe_add_plug_capture(uses_cowboy?)
|> Igniter.Code.Common.within(&add_plug_context/1)
|> then(&{:ok, &1})
end)
end
defp maybe_add_plug_capture(zipper, true) do
Igniter.Code.Common.within(zipper, &add_plug_capture/1)
end
defp maybe_add_plug_capture(zipper, false), do: zipper
defp add_plug_capture(zipper) do
with :error <- Igniter.Code.Module.move_to_use(zipper, Sentry.PlugCapture),
{:ok, zipper} <- Igniter.Code.Module.move_to_use(zipper, Phoenix.Endpoint) do
Igniter.Code.Common.add_code(zipper, "use Sentry.PlugCapture", placement: :before)
else
_ ->
zipper
end
end
defp add_plug_context(zipper) do
with :error <-
Igniter.Code.Function.move_to_function_call_in_current_scope(
zipper,
:plug,
[1, 2],
&Igniter.Code.Function.argument_equals?(&1, 0, Sentry.PlugContext)
),
{:ok, zipper} <-
Igniter.Code.Function.move_to_function_call_in_current_scope(
zipper,
:plug,
[1, 2],
&Igniter.Code.Function.argument_equals?(&1, 0, Plug.Parsers)
) do
Igniter.Code.Common.add_code(zipper, "plug Sentry.PlugContext", placement: :after)
else
_ ->
zipper
end
end
end
else
defmodule Mix.Tasks.Sentry.Install do
@shortdoc "#{__MODULE__.Docs.short_doc()} | Install `igniter` to use"
@moduledoc __MODULE__.Docs.long_doc()
use Mix.Task
def run(_argv) do
Mix.shell().error("""
The task 'sentry.install' requires igniter. Please install igniter and try again.
For more information, see: https://hexdocs.pm/igniter/readme.html#installation
""")
exit({:shutdown, 1})
end
end
end