mirror of
https://github.com/plausible/analytics.git
synced 2024-09-11 18:07:33 +03:00
Add debug_replay_info context to Sentry Stats reports (#3189)
* Add debug_replay_info context to Sentry Stats reports * Test limit
This commit is contained in:
parent
eb3222f840
commit
82f356f387
51
lib/plausible/debug_replay_info.ex
Normal file
51
lib/plausible/debug_replay_info.ex
Normal file
@ -0,0 +1,51 @@
|
||||
defmodule Plausible.DebugReplayInfo do
|
||||
@moduledoc """
|
||||
Function execution context (with arguments) to Sentry reports.
|
||||
"""
|
||||
|
||||
require Logger
|
||||
|
||||
defmacro __using__(_) do
|
||||
quote do
|
||||
require Plausible.DebugReplayInfo
|
||||
import Plausible.DebugReplayInfo, only: [include_sentry_replay_info: 0]
|
||||
end
|
||||
end
|
||||
|
||||
defmacro include_sentry_replay_info() do
|
||||
module = __CALLER__.module
|
||||
{function, arity} = __CALLER__.function
|
||||
f = Function.capture(module, function, arity)
|
||||
|
||||
quote bind_quoted: [f: f] do
|
||||
replay_info =
|
||||
{f, binding()}
|
||||
|> :erlang.term_to_iovec([:compressed])
|
||||
|> IO.iodata_to_binary()
|
||||
|> Base.encode64()
|
||||
|
||||
payload_size = byte_size(replay_info)
|
||||
|
||||
if payload_size <= 10_000 do
|
||||
Sentry.Context.set_extra_context(%{
|
||||
debug_replay_info: replay_info,
|
||||
debug_replay_info_size: payload_size
|
||||
})
|
||||
else
|
||||
Sentry.Context.set_extra_context(%{
|
||||
debug_replay_info: :too_large,
|
||||
debug_replay_info_size: payload_size
|
||||
})
|
||||
end
|
||||
|
||||
:ok
|
||||
end
|
||||
end
|
||||
|
||||
@spec deserialize(String.t()) :: any()
|
||||
def deserialize(replay_info) do
|
||||
replay_info
|
||||
|> Base.decode64!()
|
||||
|> :erlang.binary_to_term()
|
||||
end
|
||||
end
|
@ -1,10 +1,42 @@
|
||||
defmodule Plausible.Stats do
|
||||
defdelegate breakdown(site, query, prop, metrics, pagination), to: Plausible.Stats.Breakdown
|
||||
defdelegate aggregate(site, query, metrics), to: Plausible.Stats.Aggregate
|
||||
defdelegate timeseries(site, query, metrics), to: Plausible.Stats.Timeseries
|
||||
defdelegate current_visitors(site), to: Plausible.Stats.CurrentVisitors
|
||||
defdelegate funnel(site, query, funnel), to: Plausible.Stats.Funnel
|
||||
alias Plausible.Stats.{
|
||||
Breakdown,
|
||||
Aggregate,
|
||||
Timeseries,
|
||||
CurrentVisitors,
|
||||
Funnel,
|
||||
FilterSuggestions
|
||||
}
|
||||
|
||||
defdelegate filter_suggestions(site, query, filter_name, filter_search),
|
||||
to: Plausible.Stats.FilterSuggestions
|
||||
use Plausible.DebugReplayInfo
|
||||
|
||||
def breakdown(site, query, prop, metrics, pagination) do
|
||||
include_sentry_replay_info()
|
||||
Breakdown.breakdown(site, query, prop, metrics, pagination)
|
||||
end
|
||||
|
||||
def aggregate(site, query, metrics) do
|
||||
include_sentry_replay_info()
|
||||
Aggregate.aggregate(site, query, metrics)
|
||||
end
|
||||
|
||||
def timeseries(site, query, metrics) do
|
||||
include_sentry_replay_info()
|
||||
Timeseries.timeseries(site, query, metrics)
|
||||
end
|
||||
|
||||
def current_visitors(site) do
|
||||
include_sentry_replay_info()
|
||||
CurrentVisitors.current_visitors(site)
|
||||
end
|
||||
|
||||
def funnel(site, query, funnel) do
|
||||
include_sentry_replay_info()
|
||||
Funnel.funnel(site, query, funnel)
|
||||
end
|
||||
|
||||
def filter_suggestions(site, query, filter_name, filter_search) do
|
||||
include_sentry_replay_info()
|
||||
FilterSuggestions.filter_suggestions(site, query, filter_name, filter_search)
|
||||
end
|
||||
end
|
||||
|
48
test/plausible/debug_replay_info_test.exs
Normal file
48
test/plausible/debug_replay_info_test.exs
Normal file
@ -0,0 +1,48 @@
|
||||
defmodule Plausible.DebugReplayInfoTest do
|
||||
use Plausible.DataCase, async: true
|
||||
|
||||
defmodule SampleModule do
|
||||
use Plausible.DebugReplayInfo
|
||||
|
||||
def task(site, query, report_to) do
|
||||
include_sentry_replay_info()
|
||||
send(report_to, {:task_done, Sentry.Context.get_all()})
|
||||
{:ok, {site, query}}
|
||||
end
|
||||
end
|
||||
|
||||
test "adds replayable sentry context" do
|
||||
site = build(:site)
|
||||
query = Plausible.Stats.Query.from(site, %{"period" => "day"})
|
||||
{:ok, {^site, ^query}} = SampleModule.task(site, query, self())
|
||||
|
||||
assert_receive {:task_done, context}
|
||||
|
||||
assert is_integer(context.extra.debug_replay_info_size)
|
||||
assert info = context.extra.debug_replay_info
|
||||
|
||||
{function, input} = Plausible.DebugReplayInfo.deserialize(info)
|
||||
|
||||
assert function == (&SampleModule.task/3)
|
||||
|
||||
assert input[:site] == site
|
||||
assert input[:query] == query
|
||||
assert input[:report_to] == self()
|
||||
|
||||
assert apply(function, [input[:site], input[:query], input[:report_to]])
|
||||
assert_receive {:task_done, ^context}
|
||||
end
|
||||
|
||||
test "won't add replay info, if serialized input too large" do
|
||||
{:ok, _} =
|
||||
SampleModule.task(
|
||||
:crypto.strong_rand_bytes(10_000),
|
||||
:crypto.strong_rand_bytes(10_000),
|
||||
self()
|
||||
)
|
||||
|
||||
assert_receive {:task_done, context}
|
||||
assert context.extra.debug_replay_info == :too_large
|
||||
assert context.extra.debug_replay_info_size > 10_000
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue
Block a user