Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
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
41 changes: 40 additions & 1 deletion lib/sentry/config.ex
Original file line number Diff line number Diff line change
Expand Up @@ -742,7 +742,7 @@ defmodule Sentry.Config do
"""
],
telemetry_buffer_capacities: [
type: {:map, {:in, [:error, :check_in, :transaction, :log, :metric]}, :pos_integer},
type: {:custom, __MODULE__, :__validate_telemetry_buffer_capacities__, []},
default: %{},
type_doc: "`%{category => pos_integer()}`",
doc: """
Expand Down Expand Up @@ -1493,6 +1493,45 @@ defmodule Sentry.Config do
{:error, "expected a Regex or a string pattern, got: #{inspect(term)}"}
end

def __validate_telemetry_buffer_capacities__(capacities) when is_map(capacities) do
Enum.reduce_while(capacities, {:ok, capacities}, fn {category, capacity}, acc ->
case validate_buffer_capacity(category, capacity) do
:ok -> {:cont, acc}
{:error, _reason} = error -> {:halt, error}
end
end)
end

def __validate_telemetry_buffer_capacities__(other) do
{:error, "expected a map of category to capacity, got: #{inspect(other)}"}
end

defp validate_buffer_capacity(category, _capacity)
when category not in [:error, :check_in, :transaction, :log, :metric] do
{:error,
"expected category to be one of [:error, :check_in, :transaction, :log, :metric], " <>
"got: #{inspect(category)}"}
end

defp validate_buffer_capacity(category, capacity)
when not is_integer(capacity) or capacity < 1 do
{:error,
"expected capacity for #{inspect(category)} to be a positive integer, " <>
"got: #{inspect(capacity)}"}
end

defp validate_buffer_capacity(category, capacity) do
batch_size = Sentry.Telemetry.Category.default_config(category).batch_size

if capacity < batch_size do
{:error,
"capacity for #{inspect(category)} must be at least its batch size of #{batch_size}, " <>
"got: #{inspect(capacity)}"}
else
:ok
end
end

def __validate_oban_tags_to_sentry_tags__(nil), do: {:ok, nil}

def __validate_oban_tags_to_sentry_tags__(fun) when is_function(fun, 1) do
Expand Down
6 changes: 6 additions & 0 deletions lib/sentry/telemetry/buffer.ex
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,12 @@ defmodule Sentry.Telemetry.Buffer do
last_flush_time: System.monotonic_time(:millisecond)
}

if state.batch_size > state.capacity do
raise ArgumentError,
":batch_size (#{state.batch_size}) cannot be greater than :capacity " <>
"(#{state.capacity}) for the #{inspect(category)} buffer"
end

{:ok, state}
end

Expand Down
8 changes: 8 additions & 0 deletions test/sentry/config_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,14 @@ defmodule Sentry.ConfigTest do
assert_raise ArgumentError, ~r/telemetry_buffer_capacities/, fn ->
Config.validate!(telemetry_buffer_capacities: %{log: 0})
end

assert_raise ArgumentError, ~r/telemetry_buffer_capacities/, fn ->
Config.validate!(telemetry_buffer_capacities: %{log: 50})
end

assert Config.validate!(telemetry_buffer_capacities: %{log: 100})[
:telemetry_buffer_capacities
] == %{log: 100}
end

test ":namespace with valid resolver" do
Expand Down
31 changes: 29 additions & 2 deletions test/sentry/telemetry/buffer_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,21 @@ defmodule Sentry.Telemetry.BufferTest do
GenServer.stop(pid)
end

test "refuses a capacity smaller than the batch size" do
Process.flag(:trap_exit, true)

assert {:error, {%ArgumentError{message: message}, _stacktrace}} =
Buffer.start_link(
category: :log,
name: :test_buffer_capacity_below_batch,
capacity: 2,
batch_size: 5
)

assert message =~ ":batch_size"
assert message =~ ":capacity"
end

test "allows overriding capacity, batch_size, and timeout" do
assert {:ok, pid} =
Buffer.start_link(
Expand Down Expand Up @@ -135,7 +150,14 @@ defmodule Sentry.Telemetry.BufferTest do

describe "overflow behavior" do
test "drops oldest item when buffer is full" do
{:ok, pid} = Buffer.start_link(category: :log, name: :test_buffer_overflow, capacity: 2)
{:ok, pid} =
Buffer.start_link(
category: :log,
name: :test_buffer_overflow,
capacity: 2,
batch_size: 1
)

Buffer.add(pid, make_item("e1"))
Buffer.add(pid, make_item("e2"))
Buffer.add(pid, make_item("e3"))
Expand Down Expand Up @@ -172,7 +194,12 @@ defmodule Sentry.Telemetry.BufferTest do

test "FIFO ordering is preserved after overflow" do
{:ok, pid} =
Buffer.start_link(category: :log, name: :test_buffer_fifo_overflow, capacity: 3)
Buffer.start_link(
category: :log,
name: :test_buffer_fifo_overflow,
capacity: 3,
batch_size: 1
)

for i <- 1..5, do: Buffer.add(pid, make_item("e#{i}"))

Expand Down
Loading