Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/sentry/application.ex
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ defmodule Sentry.Application do
end

if config[:oban][:capture_errors] do
Sentry.Integrations.Oban.ErrorReporter.attach()
Sentry.Integrations.Oban.ErrorReporter.attach(config[:oban])
end

if config[:quantum][:cron][:enabled] do
Expand Down
8 changes: 8 additions & 0 deletions lib/sentry/config.ex
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,14 @@ defmodule Sentry.Config do
tuples. *Available since 10.3.0*.
"""
],
oban_tags: [
type: :boolean,
default: false,
doc: """
Whether to include Oban job tags in Sentry error tags. When enabled, the `job.tags`
will be joined with a "," and added as an `oban_tags` tag to Sentry events.
"""
],
cron: [
doc: """
Configuration options for configuring [*crons*](https://docs.sentry.io/product/crons/)
Expand Down
25 changes: 17 additions & 8 deletions lib/sentry/integrations/oban/error_reporter.ex
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ defmodule Sentry.Integrations.Oban.ErrorReporter do
# See this blog post:
# https://getoban.pro/articles/enhancing-error-reporting

@spec attach() :: :ok
def attach do
@spec attach(keyword()) :: :ok
def attach(config \\ []) when is_list(config) do
_ =
:telemetry.attach(
__MODULE__,
[:oban, :job, :exception],
&__MODULE__.handle_event/4,
:no_config
config
)

:ok
Expand All @@ -21,32 +21,41 @@ defmodule Sentry.Integrations.Oban.ErrorReporter do
[atom(), ...],
term(),
%{required(:job) => struct(), optional(term()) => term()},
:no_config
keyword()
) :: :ok
def handle_event(
[:oban, :job, :exception],
_measurements,
%{job: job, kind: kind, reason: reason, stacktrace: stacktrace} = _metadata,
:no_config
config
) do
if report?(reason) do
report(job, kind, reason, stacktrace)
report(job, kind, reason, stacktrace, config)
else
:ok
end
end

defp report(job, kind, reason, stacktrace) do
defp report(job, kind, reason, stacktrace, config) do
stacktrace =
case {apply(Oban.Worker, :from_string, [job.worker]), stacktrace} do
{{:ok, atom_worker}, []} -> [{atom_worker, :process, 1, []}]
_ -> stacktrace
end

base_tags = %{oban_worker: job.worker, oban_queue: job.queue, oban_state: job.state}

tags =
if config[:oban_tags] === true and is_list(job.tags) and not Enum.empty?(job.tags) do
Map.put(base_tags, :oban_tags, Enum.join(job.tags, ","))
else
base_tags
end

opts =
[
stacktrace: stacktrace,
tags: %{oban_worker: job.worker, oban_queue: job.queue, oban_state: job.state},
tags: tags,
fingerprint: [job.worker, "{{ default }}"],
extra:
Map.take(job, [:args, :attempt, :id, :max_attempts, :meta, :queue, :tags, :worker]),
Expand Down
24 changes: 21 additions & 3 deletions test/sentry/integrations/oban/error_reporter_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ defmodule Sentry.Integrations.Oban.ErrorReporterTest do
alias Sentry.Integrations.Oban.ErrorReporter

defmodule MyWorker do
use Oban.Worker
use Oban.Worker, tags: ["tag1", "tag2"]

@impl Oban.Worker
def perform(%Oban.Job{}), do: :ok
Expand Down Expand Up @@ -154,11 +154,29 @@ defmodule Sentry.Integrations.Oban.ErrorReporterTest do
assert Sentry.Test.pop_sentry_reports() == []
end
end

test "includes oban_tags when config option is enabled" do
Sentry.Test.start_collecting()

emit_telemetry_for_failed_job(:error, %RuntimeError{message: "oops"}, [], oban_tags: true)

assert [event] = Sentry.Test.pop_sentry_reports()
assert event.tags.oban_tags == "tag1,tag2"
end

test "excludes oban_tags when config option is disabled" do
Sentry.Test.start_collecting()

emit_telemetry_for_failed_job(:error, %RuntimeError{message: "oops"}, [], oban_tags: false)

assert [event] = Sentry.Test.pop_sentry_reports()
assert is_nil(Map.get(event.tags, :oban_tags))
end
end

## Helpers

defp emit_telemetry_for_failed_job(kind, reason, stacktrace) do
defp emit_telemetry_for_failed_job(kind, reason, stacktrace, config \\ []) do
job =
%{"id" => "123", "entity" => "user", "type" => "delete"}
|> MyWorker.new()
Expand All @@ -169,7 +187,7 @@ defmodule Sentry.Integrations.Oban.ErrorReporterTest do
[:oban, :job, :exception],
%{},
%{job: job, kind: kind, reason: reason, stacktrace: stacktrace},
:no_config
config
)

job
Expand Down
3 changes: 2 additions & 1 deletion test/sentry/logger_handler_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -678,7 +678,8 @@ defmodule Sentry.LoggerHandlerTest do
%ArgumentError{
message:
":sync_threshold and :discard_threshold cannot be used together, one of them must be nil"
}, _}}} =
},
_}}} =
:logger.update_handler_config(
handler_name,
:config,
Expand Down