@@ -251,19 +251,83 @@ defmodule Sentry.Test do
251251 end
252252
253253 @ doc """
254- Allows `pid_to_allow` to collect events back to the root process via `owner_pid`.
254+ Allows `pid_to_allow` to collect events back to `owner_pid`'s test scope.
255+
256+ Use this when an unrelated process — one that does not appear in the
257+ current test's `$callers` chain — needs to have its captured events
258+ routed into this test's collector. Typical examples include Broadway
259+ workers, processes started by `phoenix_test_playwright`, or
260+ long-lived `GenServer`s that outlive the calling test process.
261+
262+ `pid_to_allow` may be a pid or a zero-arity function returning a pid;
263+ the function form is resolved on call and is convenient when the pid
264+ is not known until later.
265+
266+ This function is idempotent for the same `owner_pid`. It raises
267+ `ArgumentError` when `owner_pid` has not yet called `setup_sentry/1`
268+ (or `start_collecting_sentry_reports/0`), and raises when a different
269+ live test scope already owns `pid_to_allow`.
270+
271+ Cleanup is automatic: allow entries are removed when the test exits
272+ via the same `on_exit` callback registered by `setup_sentry/1`.
273+
274+ ## Example
275+
276+ setup do
277+ Sentry.Test.setup_sentry()
278+ end
279+
280+ test "events from a Broadway worker are captured" do
281+ {:ok, worker_pid} = MyApp.Worker.start_link()
282+ :ok = Sentry.Test.allow_sentry_reports(self(), worker_pid)
283+
284+ send(worker_pid, :do_work_that_reports)
285+
286+ assert_receive {:done, _}
287+ assert [%Sentry.Event{}] = Sentry.Test.pop_sentry_reports()
288+ end
255289
256- > #### Deprecated {: .warning}
257- >
258- > This function is deprecated and will be removed in v13.0.0.
259- > Child processes are automatically tracked via the `$callers` mechanism.
260- > There is no need to explicitly allow processes.
261290 """
262- @ doc since: "10.2.0"
263- @ doc deprecated: "Child processes are now automatically tracked via $callers"
291+ @ doc since: "13.0.2"
264292 @ spec allow_sentry_reports ( pid ( ) , pid ( ) | ( -> pid ( ) ) ) :: :ok
265- def allow_sentry_reports ( _owner_pid , _pid_to_allow ) do
266- :ok
293+ def allow_sentry_reports ( owner_pid , pid_or_fun ) when is_pid ( owner_pid ) do
294+ allowed_pid = resolve_allowed_pid ( pid_or_fun )
295+
296+ case Sentry.Test.Registry . claim_collector_allow ( owner_pid , allowed_pid ) do
297+ :ok ->
298+ # Also route per-test config overrides (DSN, before_send hooks,
299+ # the internal collector callback, etc.) through the owner's
300+ # scope so that Sentry callbacks invoked from `allowed_pid`
301+ # resolve to the same configuration the test set up.
302+ Sentry.Test.Config . allow ( owner_pid , allowed_pid )
303+ :ok
304+
305+ { :error , :no_collector } ->
306+ raise ArgumentError ,
307+ "owner #{ inspect ( owner_pid ) } is not collecting Sentry reports; " <>
308+ "call Sentry.Test.setup_sentry/1 or " <>
309+ "Sentry.Test.start_collecting_sentry_reports/0 first"
310+
311+ { :error , { :taken , existing_owner } } ->
312+ raise ArgumentError ,
313+ "cannot allow #{ inspect ( allowed_pid ) } for #{ inspect ( owner_pid ) } : " <>
314+ "already allowed by another live test scope " <>
315+ "(owner: #{ inspect ( existing_owner ) } )"
316+ end
317+ end
318+
319+ defp resolve_allowed_pid ( pid ) when is_pid ( pid ) , do: pid
320+
321+ defp resolve_allowed_pid ( fun ) when is_function ( fun , 0 ) do
322+ case fun . ( ) do
323+ pid when is_pid ( pid ) ->
324+ pid
325+
326+ other ->
327+ raise ArgumentError ,
328+ "expected the function passed to allow_sentry_reports/2 to return a pid, " <>
329+ "got: #{ inspect ( other ) } "
330+ end
267331 end
268332
269333 @ doc """
@@ -698,6 +762,10 @@ defmodule Sentry.Test do
698762 :ok
699763 end
700764 end
765+
766+ # Drop any allow_sentry_reports/2 entries pointing at this test's
767+ # collector table.
768+ :ets . match_delete ( @ registry_table , { :_ , collector_table } )
701769 end
702770
703771 if :ets . whereis ( collector_table ) != :undefined do
0 commit comments