@@ -66,7 +66,7 @@ defmodule Sentry.Test do
6666 Opens a Bypass on a random port, configures the DSN to point to it,
6767 wires up `before_send` / `before_send_log` callbacks to capture structs
6868 in an isolated ETS table, and starts a per-test `Sentry.TelemetryProcessor`
69- (via `setup_telemetry_processor/0 `) so that assertions work for events
69+ (via `setup_telemetry_processor/1 `) so that assertions work for events
7070 that travel through the TelemetryProcessor pipeline (logs, metrics, or
7171 `send_result: :none`).
7272
@@ -80,6 +80,12 @@ defmodule Sentry.Test do
8080 Any extra Sentry config options (e.g., `dedup_events: false`, `traces_sample_rate: 1.0`)
8181 will be forwarded to the test config.
8282
83+ The reserved `:telemetry_processor` option is *not* forwarded to the test
84+ config. Instead, its value (a keyword list) is passed to the per-test
85+ `Sentry.TelemetryProcessor` (e.g. `buffer_configs`, `buffer_capacities`,
86+ `scheduler_weights`, `transport_capacity`). This replaces the need to
87+ manually `stop_supervised!/1` and re-`start_supervised!/2` the processor.
88+
8389 ## Examples
8490
8591 setup do
@@ -90,19 +96,12 @@ defmodule Sentry.Test do
9096 Sentry.Test.setup_sentry(dedup_events: false)
9197 end
9298
93- Replacing the auto-started processor with a custom-configured one :
99+ Configuring the per-test processor (e.g. a smaller log batch size) :
94100
95101 setup do
96- %{telemetry_processor: name} = ctx = Sentry.Test.setup_sentry()
97- stop_supervised!(name)
98-
99- start_supervised!(
100- {Sentry.TelemetryProcessor,
101- name: name, buffer_configs: %{log: %{batch_size: 1}}},
102- id: name
102+ Sentry.Test.setup_sentry(
103+ telemetry_processor: [buffer_configs: %{log: %{batch_size: 1}}]
103104 )
104-
105- ctx
106105 end
107106
108107 """
@@ -112,6 +111,8 @@ defmodule Sentry.Test do
112111 ensure_bypass_loaded! ( )
113112 ensure_nimble_ownership_loaded! ( )
114113
114+ { tp_opts , extra_config } = Keyword . pop ( extra_config , :telemetry_processor , [ ] )
115+
115116 # Open a per-test Bypass and stub the envelope endpoint
116117 bypass = Bypass . open ( )
117118
@@ -121,7 +122,7 @@ defmodule Sentry.Test do
121122
122123 # Start a per-test TelemetryProcessor before setup_collector/1 so that
123124 # the collector wires this test's scheduler into its registry.
124- processor_name = setup_telemetry_processor ( )
125+ processor_name = setup_telemetry_processor ( tp_opts )
125126
126127 # Set up collector with DSN pointing to this test's Bypass
127128 bypass_config = [ dsn: "http://public:secret@localhost:#{ bypass . port } /1" ]
@@ -154,34 +155,69 @@ defmodule Sentry.Test do
154155 Must be called from within an ExUnit test because it uses
155156 `ExUnit.Callbacks.start_supervised!/2` for automatic cleanup.
156157
157- If a per-test processor is already registered for this test (for example
158- when using `Sentry.Case`), this function is idempotent and returns the
159- existing processor name instead of starting a new one.
158+ ## Options
159+
160+ `tp_opts` is a keyword list forwarded to the per-test
161+ `Sentry.TelemetryProcessor` child spec (e.g. `buffer_configs`,
162+ `buffer_capacities`, `scheduler_weights`, `transport_capacity`).
163+
164+ Idempotency depends on `tp_opts`:
165+
166+ * with no `tp_opts`, an already-registered live processor (for example
167+ one started by `Sentry.Case`) is reused and its name returned;
168+ * with `tp_opts`, an already-registered live processor is stopped and
169+ restarted under the same name with the given options, so callers no
170+ longer need to `stop_supervised!/1` + `start_supervised!/2` manually.
160171 """
161172 @ doc since: "13.0.0"
162- @ spec setup_telemetry_processor ( ) :: atom ( )
163- def setup_telemetry_processor do
173+ @ spec setup_telemetry_processor ( keyword ( ) ) :: atom ( )
174+ def setup_telemetry_processor ( tp_opts \\ [ ] ) do
164175 case Process . get ( :sentry_telemetry_processor ) do
165176 name when is_atom ( name ) and not is_nil ( name ) ->
166- if processor_alive? ( name ) , do: name , else: start_telemetry_processor ( )
177+ cond do
178+ not processor_alive? ( name ) -> start_telemetry_processor ( tp_opts )
179+ tp_opts == [ ] -> name
180+ true -> restart_telemetry_processor ( name , tp_opts )
181+ end
167182
168183 _ ->
169- start_telemetry_processor ( )
184+ start_telemetry_processor ( tp_opts )
170185 end
171186 end
172187
173- defp start_telemetry_processor do
188+ defp start_telemetry_processor ( tp_opts ) do
174189 uid = System . unique_integer ( [ :positive ] )
175190 processor_name = :"test_telemetry_processor_#{ uid } "
176191
177- ExUnit.Callbacks . start_supervised! (
178- { Sentry.TelemetryProcessor ,
179- name: processor_name , processor_resolver: & Sentry.Test.Registry . lookup_processor_for / 1 } ,
180- id: processor_name
181- )
192+ start_processor_child ( processor_name , tp_opts )
182193
194+ # Must be set before tag_scheduler/1, which reads
195+ # `:sentry_telemetry_processor` from this process's dictionary via
196+ # `fetch_owner_processor/1`. Tagging would otherwise be a silent no-op.
183197 Process . put ( :sentry_telemetry_processor , processor_name )
184198
199+ tag_scheduler ( processor_name )
200+ processor_name
201+ end
202+
203+ defp restart_telemetry_processor ( name , tp_opts ) do
204+ ExUnit.Callbacks . stop_supervised! ( name )
205+ start_processor_child ( name , tp_opts )
206+ # The process dictionary already holds `name`; the new scheduler pid
207+ # must be re-tagged since the old one died with the old supervisor.
208+ tag_scheduler ( name )
209+ name
210+ end
211+
212+ defp start_processor_child ( name , tp_opts ) do
213+ opts =
214+ [ name: name , processor_resolver: & Sentry.Test.Registry . lookup_processor_for / 1 ]
215+ |> Keyword . merge ( tp_opts )
216+
217+ ExUnit.Callbacks . start_supervised! ( { Sentry.TelemetryProcessor , opts } , id: name )
218+ end
219+
220+ defp tag_scheduler ( processor_name ) do
185221 scheduler_pid = Sentry.TelemetryProcessor . get_scheduler ( processor_name )
186222
187223 if scheduler_pid do
@@ -192,7 +228,7 @@ defmodule Sentry.Test do
192228 tag_processor_for_allowed_pid ( self ( ) , scheduler_pid )
193229 end
194230
195- processor_name
231+ :ok
196232 end
197233
198234 defp processor_alive? ( name ) do
@@ -378,9 +414,9 @@ defmodule Sentry.Test do
378414 # callback drops the event.
379415 #
380416 # The owner's processor name is looked up from its process
381- # dictionary; tests set it in `setup_telemetry_processor/0 `. If the
417+ # dictionary; tests set it in `setup_telemetry_processor/1 `. If the
382418 # owner has no per-test processor (e.g. legacy
383- # `start_collecting/1` without `setup_telemetry_processor/0 `), the
419+ # `start_collecting/1` without `setup_telemetry_processor/1 `), the
384420 # tag is skipped and the buffered event still falls back to the
385421 # global processor — the same behaviour as before this change.
386422 defp tag_processor_for_allowed_pid ( owner_pid , allowed_pid ) do
0 commit comments