@@ -3,17 +3,15 @@ defmodule Sentry.Integrations.Phoenix.ObanTest do
33 use Oban.Testing , repo: PhoenixApp.Repo
44
55 import ExUnit.CaptureLog
6+ import Sentry.Test.Assertions
67 import Sentry.TestHelpers
78
89 require OpenTelemetry.Tracer
910
1011 alias Sentry.Integrations.Oban.ErrorReporter
1112
1213 setup do
13- % { bypass: bypass } = setup_bypass ( traces_sample_rate: 1.0 )
14- ref = setup_bypass_envelope_collector ( bypass )
15-
16- % { bypass: bypass , ref: ref }
14+ Sentry.Test . setup_sentry ( collect_envelopes: true , traces_sample_rate: 1.0 )
1715 end
1816
1917 defmodule TestWorker do
@@ -47,43 +45,29 @@ defmodule Sentry.Integrations.Phoenix.ObanTest do
4745 end
4846 end
4947
50- test "captures Oban worker execution as transaction" , % { ref: ref } do
48+ test "captures Oban worker execution as transaction" do
5149 :ok = perform_job ( TestWorker , % { test: "args" } )
5250
53- envelopes = collect_envelopes ( ref , 1 )
54- transactions = extract_transactions ( envelopes )
55- assert length ( transactions ) == 1
56-
57- [ tx ] = transactions
51+ tx =
52+ assert_sentry_report ( :transaction ,
53+ transaction: "Sentry.Integrations.Phoenix.ObanTest.TestWorker" ,
54+ transaction_info: % { source: :custom }
55+ )
5856
59- assert tx [ "transaction" ] == "Sentry.Integrations.Phoenix.ObanTest.TestWorker"
60- assert tx [ "transaction_info" ] == % { "source" => "custom" }
57+ trace = tx . contexts . trace
58+ assert trace . origin == "opentelemetry_oban"
59+ assert trace . op == "queue.process"
60+ assert trace . description == "Sentry.Integrations.Phoenix.ObanTest.TestWorker"
61+ assert trace . data [ "oban.job.job_id" ]
62+ assert trace . data [ "messaging.destination.name" ] == "default"
63+ assert trace . data [ "oban.job.attempt" ] == 1
6164
62- trace = tx [ "contexts" ] [ "trace" ]
63- assert trace [ "origin" ] == "opentelemetry_oban"
64- assert trace [ "op" ] == "queue.process"
65- assert trace [ "description" ] == "Sentry.Integrations.Phoenix.ObanTest.TestWorker"
66- assert trace [ "data" ] [ "oban.job.job_id" ]
67- assert trace [ "data" ] [ "messaging.destination.name" ] == "default"
68- assert trace [ "data" ] [ "oban.job.attempt" ] == 1
69-
70- assert tx [ "spans" ] == [ ]
65+ assert tx . spans == [ ]
7166 end
7267
73- test "captures Oban worker with trace links" , % { bypass: bypass } do
68+ test "captures Oban worker with trace links" , % { ref: ref } do
7469 # This test verifies that when an Oban job is inserted within an active trace,
7570 # the consumer span has links back to the producer span.
76- test_pid = self ( )
77-
78- Bypass . stub ( bypass , "POST" , "/api/1/envelope/" , fn conn ->
79- { :ok , body , conn } = Plug.Conn . read_body ( conn )
80-
81- for { headers , body_json } <- decode_envelope! ( body ) do
82- send ( test_pid , { headers [ "type" ] , body_json } )
83- end
84-
85- Plug.Conn . send_resp ( conn , 200 , ~s< {"id": "340"}> )
86- end )
8771
8872 # Insert within an active span so trace context is propagated into job metadata
8973 OpenTelemetry.Tracer . with_span "test.request" do
@@ -96,9 +80,8 @@ defmodule Sentry.Integrations.Phoenix.ObanTest do
9680 # Drain the queue to execute the job
9781 Oban . drain_queue ( queue: :default )
9882
99- # Multiple transactions are sent (test.request, DB queries, Oban consumer),
100- # so we need to find the Oban consumer transaction specifically
101- oban_tx = receive_oban_transaction ( )
83+ transactions = collect_sentry_transactions ( ref , 100 , timeout: 500 )
84+ oban_tx = find_sentry_report! ( transactions , contexts: % { trace: % { origin: "opentelemetry_oban" } } )
10285
10386 trace = oban_tx [ "contexts" ] [ "trace" ]
10487 assert trace [ "op" ] == "queue.process"
@@ -116,70 +99,34 @@ defmodule Sentry.Integrations.Phoenix.ObanTest do
11699 end
117100 end
118101
119- test "captures Oban worker with child spans" , % { ref: ref } do
102+ test "captures Oban worker with child spans" do
120103 :ok = perform_job ( WorkerWithDatabaseQuery , % { } )
121104
122- envelopes = collect_envelopes ( ref , 1 )
123- transactions = extract_transactions ( envelopes )
124- assert length ( transactions ) == 1
125-
126- [ tx ] = transactions
127-
128- assert tx [ "transaction" ] ==
129- "Sentry.Integrations.Phoenix.ObanTest.WorkerWithDatabaseQuery"
130-
131- # Should have child spans from the database query
132- assert length ( tx [ "spans" ] ) > 0
105+ tx =
106+ assert_sentry_report ( :transaction ,
107+ transaction: "Sentry.Integrations.Phoenix.ObanTest.WorkerWithDatabaseQuery"
108+ )
133109
134- # Verify at least one db span exists
135- assert Enum . any? ( tx [ "spans" ] , fn span ->
136- span [ "op" ] == "db"
137- end )
138- end
110+ assert length ( tx . spans ) > 0
139111
140- defp receive_oban_transaction do
141- receive do
142- { "transaction" , tx } ->
143- if tx [ "contexts" ] [ "trace" ] [ "origin" ] == "opentelemetry_oban" do
144- tx
145- else
146- receive_oban_transaction ( )
147- end
148- after
149- 2000 -> flunk ( "expected an Oban consumer transaction" )
150- end
112+ assert Enum . any? ( tx . spans , fn span -> span . op == "db" end )
151113 end
152114
153115 describe "should_report_error_callback config" do
154- setup % { bypass: bypass } do
116+ setup do
155117 :telemetry . detach ( ErrorReporter )
156118
157- ref = setup_bypass_envelope_collector ( bypass , type: "event" )
158-
159119 on_exit ( fn ->
160120 _ = :telemetry . detach ( ErrorReporter )
161121 ErrorReporter . attach ( [ ] )
162122 end )
163123
164- % { ref: ref }
165- end
124+ :ok
125+ end
166126
167- test "skips error reporting when callback returns false" , % { bypass: bypass , ref: ref } do
127+ test "skips error reporting when callback returns false" do
168128 test_pid = self ( )
169129
170- # Allow transaction envelopes through but assert no error events are sent
171- Bypass . stub ( bypass , "POST" , "/api/1/envelope/" , fn conn ->
172- { :ok , body , conn } = Plug.Conn . read_body ( conn )
173- items = decode_envelope! ( body )
174-
175- for { headers , _body } <- items do
176- assert headers [ "type" ] != "event" ,
177- "Should not send error events when callback returns false"
178- end
179-
180- Plug.Conn . send_resp ( conn , 200 , ~s< {"id": "340"}> )
181- end )
182-
183130 ErrorReporter . attach (
184131 should_report_error_callback: fn worker , job ->
185132 send ( test_pid , { :callback_invoked , worker , job } )
@@ -199,11 +146,10 @@ defmodule Sentry.Integrations.Phoenix.ObanTest do
199146 assert % Oban.Job { } = received_job
200147 assert received_job . args == % { "should_fail" => true }
201148
202- envelopes = collect_envelopes ( ref , 10 , timeout: 500 )
203- assert extract_events ( envelopes ) == [ ]
149+ assert [ ] == Sentry.Test . pop_sentry_reports ( )
204150 end
205151
206- test "reports error when callback returns true" , % { ref: ref } do
152+ test "reports error when callback returns true" do
207153 test_pid = self ( )
208154
209155 ErrorReporter . attach (
@@ -222,18 +168,16 @@ defmodule Sentry.Integrations.Phoenix.ObanTest do
222168
223169 assert_receive { :callback_invoked , _worker , _job }
224170
225- envelopes = collect_envelopes ( ref , 10 , timeout: 500 )
226- events = extract_events ( envelopes )
227- assert [ event ] = events
228-
229- assert [ % { "type" => "RuntimeError" , "value" => "intentional failure for testing" } | _ ] =
230- event [ "exception" ]
171+ event =
172+ find_sentry_report! ( Sentry.Test . pop_sentry_reports ( ) ,
173+ tags: % { oban_worker: "Sentry.Integrations.Phoenix.ObanTest.FailingWorker" }
174+ )
231175
232- assert event [ "tags" ] [ "oban_worker" ] = =
233- "Sentry.Integrations.Phoenix.ObanTest.FailingWorker"
176+ assert [ % Sentry.Interfaces.Exception { type: "RuntimeError" , value: "intentional failure for testing" } | _ ] =
177+ event . exception
234178 end
235179
236- test "callback receives worker module and full job struct" , % { ref: ref } do
180+ test "callback receives worker module and full job struct" do
237181 test_pid = self ( )
238182
239183 ErrorReporter . attach (
@@ -262,27 +206,11 @@ defmodule Sentry.Integrations.Phoenix.ObanTest do
262206 assert job . max_attempts == 3
263207 assert is_integer ( job . attempt )
264208 assert is_integer ( job . id )
265-
266- # Drain envelopes to avoid Bypass errors
267- collect_envelopes ( ref , 10 , timeout: 500 )
268209 end
269210
270- test "callback can make decisions based on attempt number" , % { bypass: bypass , ref: ref } do
211+ test "callback can make decisions based on attempt number" do
271212 test_pid = self ( )
272213
273- # Allow transaction envelopes through but assert no error events are sent
274- Bypass . stub ( bypass , "POST" , "/api/1/envelope/" , fn conn ->
275- { :ok , body , conn } = Plug.Conn . read_body ( conn )
276- items = decode_envelope! ( body )
277-
278- for { headers , _body } <- items do
279- assert headers [ "type" ] != "event" ,
280- "Should not send error events when callback returns false"
281- end
282-
283- Plug.Conn . send_resp ( conn , 200 , ~s< {"id": "340"}> )
284- end )
285-
286214 ErrorReporter . attach (
287215 should_report_error_callback: fn _worker , job ->
288216 should_report = job . attempt >= job . max_attempts
@@ -303,11 +231,10 @@ defmodule Sentry.Integrations.Phoenix.ObanTest do
303231 assert max_attempts == 3
304232 assert should_report == false
305233
306- envelopes = collect_envelopes ( ref , 10 , timeout: 500 )
307- assert extract_events ( envelopes ) == [ ]
234+ assert [ ] == Sentry.Test . pop_sentry_reports ( )
308235 end
309236
310- test "handles callback errors gracefully and defaults to reporting" , % { ref: ref } do
237+ test "handles callback errors gracefully and defaults to reporting" do
311238 log =
312239 capture_log ( fn ->
313240 ErrorReporter . attach (
@@ -328,15 +255,16 @@ defmodule Sentry.Integrations.Phoenix.ObanTest do
328255 assert log =~ "FailingWorker"
329256 assert log =~ "callback crashed!"
330257
331- envelopes = collect_envelopes ( ref , 10 , timeout: 500 )
332- events = extract_events ( envelopes )
333- assert [ event ] = events
258+ event =
259+ find_sentry_report! ( Sentry.Test . pop_sentry_reports ( ) ,
260+ tags: % { oban_worker: "Sentry.Integrations.Phoenix.ObanTest.FailingWorker" }
261+ )
334262
335- assert [ % { " type" => "RuntimeError" , " value" => "intentional failure for testing" } | _ ] =
336- event [ " exception" ]
263+ assert [ % Sentry.Interfaces.Exception { type: "RuntimeError" , value: "intentional failure for testing" } | _ ] =
264+ event . exception
337265 end
338266
339- test "reports error when no callback is configured" , % { ref: ref } do
267+ test "reports error when no callback is configured" do
340268 ErrorReporter . attach ( [ ] )
341269
342270 { :ok , _job } =
@@ -346,30 +274,18 @@ defmodule Sentry.Integrations.Phoenix.ObanTest do
346274
347275 Oban . drain_queue ( queue: :default )
348276
349- envelopes = collect_envelopes ( ref , 10 , timeout: 500 )
350- events = extract_events ( envelopes )
351- assert [ event ] = events
277+ event =
278+ find_sentry_report! ( Sentry.Test . pop_sentry_reports ( ) ,
279+ tags: % { oban_worker: "Sentry.Integrations.Phoenix.ObanTest.FailingWorker" }
280+ )
352281
353- assert [ % { " type" => "RuntimeError" , " value" => "intentional failure for testing" } | _ ] =
354- event [ " exception" ]
282+ assert [ % Sentry.Interfaces.Exception { type: "RuntimeError" , value: "intentional failure for testing" } | _ ] =
283+ event . exception
355284 end
356285
357- test "callback can filter based on worker type" , % { bypass: bypass , ref: ref } do
286+ test "callback can filter based on worker type" do
358287 test_pid = self ( )
359288
360- # Allow transaction envelopes through but assert no error events are sent
361- Bypass . stub ( bypass , "POST" , "/api/1/envelope/" , fn conn ->
362- { :ok , body , conn } = Plug.Conn . read_body ( conn )
363- items = decode_envelope! ( body )
364-
365- for { headers , _body } <- items do
366- assert headers [ "type" ] != "event" ,
367- "Should not send error events when callback returns false"
368- end
369-
370- Plug.Conn . send_resp ( conn , 200 , ~s< {"id": "340"}> )
371- end )
372-
373289 ErrorReporter . attach (
374290 should_report_error_callback: fn worker , _job ->
375291 should_report = worker != FailingWorker
@@ -387,11 +303,10 @@ defmodule Sentry.Integrations.Phoenix.ObanTest do
387303
388304 assert_receive { :worker_check , FailingWorker , false }
389305
390- envelopes = collect_envelopes ( ref , 10 , timeout: 500 )
391- assert extract_events ( envelopes ) == [ ]
306+ assert [ ] == Sentry.Test . pop_sentry_reports ( )
392307 end
393308
394- test "callback receives nil and logs warning for non-existent worker module" , % { ref: ref } do
309+ test "callback receives nil and logs warning for non-existent worker module" do
395310 test_pid = self ( )
396311
397312 log =
@@ -432,10 +347,12 @@ defmodule Sentry.Integrations.Phoenix.ObanTest do
432347 assert worker == nil
433348 assert received_job . worker == "NonExistent.Worker.Module"
434349
435- envelopes = collect_envelopes ( ref , 1 )
436- events = extract_events ( envelopes )
437- assert [ event ] = events
438- assert event [ "tags" ] [ "oban_worker" ] == "NonExistent.Worker.Module"
350+ event =
351+ assert_sentry_report ( :event ,
352+ tags: % { oban_worker: "NonExistent.Worker.Module" }
353+ )
354+
355+ assert event . tags [ :oban_worker ] == "NonExistent.Worker.Module"
439356 end
440357 end
441358
0 commit comments