Skip to content
Merged
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
2 changes: 2 additions & 0 deletions lib/sentry/application.ex
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ defmodule Sentry.Application do

alias Sentry.Config
alias Sentry.LoggerUtils
alias Sentry.Metric

@compile {:no_warn_undefined, [NimbleOwnership]}

Expand Down Expand Up @@ -82,6 +83,7 @@ defmodule Sentry.Application do
[Sentry.Transport.SenderPool]

cache_loaded_applications()
Metric.init_sequence()

with {:ok, pid} <-
Supervisor.start_link(children, strategy: :one_for_one, name: Sentry.Supervisor) do
Expand Down
19 changes: 18 additions & 1 deletion lib/sentry/metric.ex
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ defmodule Sentry.Metric do

@sdk_version Mix.Project.config()[:version]

@sequence_key {:sentry, :metric_sequence}

@doc """
Attaches default attributes to a metric.

Expand All @@ -64,7 +66,22 @@ defmodule Sentry.Metric do
|> maybe_put_attr("server.address", Config.server_name())

# Merge with user attributes (user attributes take precedence)
%{metric | attributes: Map.merge(default_attrs, metric.attributes)}
attributes =
default_attrs
|> Map.merge(metric.attributes)
|> Map.put("sentry.timestamp.sequence", next_sequence())

%{metric | attributes: attributes}
end

@doc false
@spec init_sequence() :: :ok
def init_sequence do
:persistent_term.put(@sequence_key, :atomics.new(1, signed: true))
end

defp next_sequence do
:atomics.add_get(:persistent_term.get(@sequence_key), 1, 1) - 1
end

defp maybe_put_attr(attrs, _key, nil), do: attrs
Expand Down
37 changes: 37 additions & 0 deletions test/sentry/metric_sequence_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
defmodule Sentry.MetricSequenceTest do
use Sentry.Case, async: false

alias Sentry.Metric

setup do
Metric.init_sequence()
:ok
end

test "starts at 0 and increments by 1 for every metric captured" do
assert sequence_of(build(:counter)) == 0
assert sequence_of(build(:gauge)) == 1
assert sequence_of(build(:distribution)) == 2
end

test "cannot be overridden by a user-supplied attribute" do
assert sequence_of(build(:counter, %{"sentry.timestamp.sequence" => 999})) == 0
end

defp build(type, attributes \\ %{}) do
%Metric{
type: type,
name: "test.#{type}",
value: 1,
timestamp: 1_234_567_890.0,
attributes: attributes
}
end

defp sequence_of(metric) do
metric
|> Metric.attach_default_attributes()
|> Map.fetch!(:attributes)
|> Map.fetch!("sentry.timestamp.sequence")
end
end
Loading