Skip to content

Commit ffb408b

Browse files
authored
feat: implement client reports in Telemetry Processor (#995)
1 parent 4e3d5bc commit ffb408b

3 files changed

Lines changed: 94 additions & 0 deletions

File tree

lib/sentry/telemetry/buffer.ex

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ defmodule Sentry.Telemetry.Buffer do
2121
use GenServer
2222

2323
alias __MODULE__
24+
25+
alias Sentry.ClientReport
2426
alias Sentry.Telemetry.Category
2527

2628
@enforce_keys [:category, :capacity, :batch_size]
@@ -177,6 +179,12 @@ defmodule Sentry.Telemetry.Buffer do
177179
defp offer(%Buffer{size: size, capacity: capacity} = state, item)
178180
when size >= capacity do
179181
{{:value, _dropped}, items} = :queue.out(state.items)
182+
183+
ClientReport.Sender.record_discarded_events(
184+
:cache_overflow,
185+
Category.data_category(state.category)
186+
)
187+
180188
%{state | items: :queue.in(item, items)}
181189
end
182190

lib/sentry/telemetry/category.ex

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,4 +150,27 @@ defmodule Sentry.Telemetry.Category do
150150
"""
151151
@spec priorities() :: [priority()]
152152
def priorities, do: @priorities
153+
154+
@doc """
155+
Returns the Sentry data category string for a given telemetry category.
156+
157+
These strings are used in client reports and rate limiting.
158+
159+
## Examples
160+
161+
iex> Sentry.Telemetry.Category.data_category(:error)
162+
"error"
163+
164+
iex> Sentry.Telemetry.Category.data_category(:check_in)
165+
"monitor"
166+
167+
iex> Sentry.Telemetry.Category.data_category(:log)
168+
"log_item"
169+
170+
"""
171+
@spec data_category(t()) :: String.t()
172+
def data_category(:error), do: "error"
173+
def data_category(:check_in), do: "monitor"
174+
def data_category(:transaction), do: "transaction"
175+
def data_category(:log), do: "log_item"
153176
end

test/sentry/telemetry_processor_integration_test.exs

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,61 @@ defmodule Sentry.TelemetryProcessorIntegrationTest do
269269
end
270270
end
271271

272+
describe "buffer overflow client reports" do
273+
setup ctx do
274+
stop_supervised!(ctx.processor)
275+
276+
uid = System.unique_integer([:positive])
277+
processor_name = :"test_overflow_#{uid}"
278+
279+
start_supervised!(
280+
{TelemetryProcessor,
281+
name: processor_name, buffer_configs: %{log: %{capacity: 2, batch_size: 1}}},
282+
id: processor_name
283+
)
284+
285+
Process.put(:sentry_telemetry_processor, processor_name)
286+
287+
send(Process.whereis(Sentry.ClientReport.Sender), :send_report)
288+
289+
_ = :sys.get_state(Sentry.ClientReport.Sender)
290+
291+
flush_ref_messages(ctx.ref)
292+
293+
%{processor: processor_name}
294+
end
295+
296+
test "sends cache_overflow client report when log buffer overflows", ctx do
297+
scheduler = TelemetryProcessor.get_scheduler(ctx.processor)
298+
:sys.suspend(scheduler)
299+
300+
TelemetryProcessor.add(ctx.processor, make_log_event("log-1"))
301+
TelemetryProcessor.add(ctx.processor, make_log_event("log-2"))
302+
TelemetryProcessor.add(ctx.processor, make_log_event("log-3"))
303+
304+
log_buffer = TelemetryProcessor.get_buffer(ctx.processor, :log)
305+
306+
_ = Buffer.size(log_buffer)
307+
_ = :sys.get_state(Sentry.ClientReport.Sender)
308+
309+
send(Process.whereis(Sentry.ClientReport.Sender), :send_report)
310+
311+
ref = ctx.ref
312+
assert_receive {^ref, body}, 2000
313+
314+
items = decode_envelope!(body)
315+
assert [{%{"type" => "client_report"}, client_report}] = items
316+
317+
cache_overflow =
318+
Enum.find(client_report["discarded_events"], &(&1["reason"] == "cache_overflow"))
319+
320+
assert cache_overflow["category"] == "log_item"
321+
assert cache_overflow["quantity"] == 1
322+
323+
:sys.resume(scheduler)
324+
end
325+
end
326+
272327
defp make_transaction do
273328
now = System.system_time(:microsecond)
274329

@@ -281,6 +336,14 @@ defmodule Sentry.TelemetryProcessorIntegrationTest do
281336
}
282337
end
283338

339+
defp flush_ref_messages(ref) do
340+
receive do
341+
{^ref, _body} -> flush_ref_messages(ref)
342+
after
343+
100 -> :ok
344+
end
345+
end
346+
284347
defp make_log_event(body) do
285348
%LogEvent{
286349
timestamp: System.system_time(:nanosecond) / 1_000_000_000,

0 commit comments

Comments
 (0)