Skip to content

Commit daf4c2e

Browse files
Merge pull request #364 from getsentry/more-typespecs
before_send_event filter
2 parents dfcbf23 + 1777b63 commit daf4c2e

File tree

5 files changed

+99
-17
lines changed

5 files changed

+99
-17
lines changed

lib/sentry.ex

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,9 +117,9 @@ defmodule Sentry do
117117
@spec capture_exception(Exception.t() | atom() | {atom(), atom()}, Keyword.t()) :: send_result
118118
def capture_exception(exception, opts \\ []) do
119119
filter_module = Config.filter()
120-
{source, opts} = Keyword.pop(opts, :event_source)
120+
event_source = Keyword.get(opts, :event_source)
121121

122-
if filter_module.exclude_exception?(exception, source) do
122+
if filter_module.exclude_exception?(exception, event_source) do
123123
:excluded
124124
else
125125
exception

lib/sentry/client.ex

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,10 @@ defmodule Sentry.Client do
4040

4141
require Logger
4242

43-
@type send_event_result :: {:ok, Task.t() | String.t() | pid()} | :error | :unsampled
43+
@type send_event_result ::
44+
{:ok, Task.t() | String.t() | pid()} | :error | :unsampled | :excluded
4445
@type dsn :: {String.t(), String.t(), String.t()} | :error
46+
@type result :: :sync | :none | :async
4547
@sentry_version 5
4648
@max_attempts 4
4749
@hackney_pool_name :sentry_pool
@@ -66,13 +68,19 @@ defmodule Sentry.Client do
6668

6769
event = maybe_call_before_send_event(event)
6870

69-
if sample_event?(sample_rate) do
70-
encode_and_send(event, result)
71-
else
72-
:unsampled
71+
case {event, sample_event?(sample_rate)} do
72+
{false, _} ->
73+
:excluded
74+
75+
{%Event{}, false} ->
76+
:unsampled
77+
78+
{%Event{}, true} ->
79+
encode_and_send(event, result)
7380
end
7481
end
7582

83+
@spec encode_and_send(Event.t(), result()) :: send_event_result()
7684
defp encode_and_send(event, result) do
7785
json_library = Config.json_library()
7886

@@ -88,6 +96,7 @@ defmodule Sentry.Client do
8896
end
8997
end
9098

99+
@spec do_send_event(Event.t(), map(), :async) :: {:ok, Task.t()} | :error
91100
defp do_send_event(event, body, :async) do
92101
case get_headers_and_endpoint() do
93102
{endpoint, auth_headers} ->
@@ -102,6 +111,7 @@ defmodule Sentry.Client do
102111
end
103112
end
104113

114+
@spec do_send_event(Event.t(), map(), :sync) :: {:ok, String.t()} | :error
105115
defp do_send_event(event, body, :sync) do
106116
case get_headers_and_endpoint() do
107117
{endpoint, auth_headers} ->
@@ -113,6 +123,8 @@ defmodule Sentry.Client do
113123
end
114124
end
115125

126+
@spec do_send_event(Event.t(), map(), :none) ::
127+
{:ok, DynamicSupervisor.on_start_child()} | :error
116128
defp do_send_event(event, body, :none) do
117129
case get_headers_and_endpoint() do
118130
{endpoint, auth_headers} ->
@@ -128,6 +140,12 @@ defmodule Sentry.Client do
128140
end
129141
end
130142

143+
@spec try_request(
144+
String.t(),
145+
list({String.t(), String.t()}),
146+
{Event.t(), String.t()},
147+
pos_integer()
148+
) :: {:ok, String.t()} | :error
131149
defp try_request(url, headers, event_body_tuple, current_attempt \\ 1)
132150

133151
defp try_request(_, _, _, current_attempt)
@@ -206,6 +224,7 @@ defmodule Sentry.Client do
206224
"Sentry " <> query
207225
end
208226

227+
@spec authorization_headers(String.t(), String.t()) :: list({String.t(), String.t()})
209228
defp authorization_headers(public_key, secret_key) do
210229
[
211230
{"User-Agent", @sentry_client},
@@ -257,14 +276,14 @@ defmodule Sentry.Client do
257276
result
258277
end
259278

260-
@spec maybe_call_before_send_event(Event.t()) :: Event.t()
279+
@spec maybe_call_before_send_event(Event.t()) :: Event.t() | false
261280
def maybe_call_before_send_event(event) do
262281
case Config.before_send_event() do
263282
function when is_function(function, 1) ->
264-
function.(event)
283+
function.(event) || false
265284

266285
{module, function} ->
267-
apply(module, function, [event])
286+
apply(module, function, [event]) || false
268287

269288
nil ->
270289
event
@@ -345,11 +364,13 @@ defmodule Sentry.Client do
345364
)
346365
end
347366

367+
@spec sleep(pos_integer()) :: :ok
348368
defp sleep(1), do: :timer.sleep(2000)
349369
defp sleep(2), do: :timer.sleep(4000)
350370
defp sleep(3), do: :timer.sleep(8000)
351371
defp sleep(_), do: :timer.sleep(8000)
352372

373+
@spec sample_event?(number()) :: boolean()
353374
defp sample_event?(1), do: true
354375
defp sample_event?(1.0), do: true
355376
defp sample_event?(0), do: false

lib/sentry/event.ex

Lines changed: 41 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ defmodule Sentry.Event do
2020
server_name: nil,
2121
environment: nil,
2222
exception: nil,
23+
original_exception: nil,
2324
release: nil,
2425
stacktrace: %{
2526
frames: []
@@ -29,9 +30,34 @@ defmodule Sentry.Event do
2930
user: %{},
3031
breadcrumbs: [],
3132
fingerprint: [],
32-
modules: %{}
33-
34-
@type t :: %__MODULE__{}
33+
modules: %{},
34+
event_source: nil
35+
36+
@type sentry_exception :: %{type: String.t(), value: String.t(), module: any()}
37+
@type t :: %__MODULE__{
38+
event_id: String.t() | nil,
39+
culprit: String.t() | nil,
40+
timestamp: String.t() | nil,
41+
message: String.t() | nil,
42+
tags: map(),
43+
level: String.t(),
44+
platform: String.t(),
45+
server_name: any(),
46+
environment: any(),
47+
exception: [sentry_exception()],
48+
original_exception: Exception.t() | nil,
49+
release: any(),
50+
stacktrace: %{
51+
frames: [map()]
52+
},
53+
request: map(),
54+
extra: map(),
55+
user: map(),
56+
breadcrumbs: list(),
57+
fingerprint: list(),
58+
modules: map(),
59+
event_source: any()
60+
}
3561

3662
alias Sentry.{Config, Event, Util}
3763
@source_code_context_enabled Config.enable_source_code_context()
@@ -47,14 +73,16 @@ defmodule Sentry.Event do
4773
@doc """
4874
Creates an Event struct out of context collected and options
4975
## Options
50-
* `:exception` - expection
76+
* `:exception` - Sentry-formatted exception
77+
* `:original_exception` - Original exception
5178
* `:message` - message
5279
* `:stacktrace` - a list of Exception.stacktrace()
5380
* `:extra` - map of extra context
5481
* `:user` - map of user context
5582
* `:tags` - map of tags context
5683
* `:request` - map of request context
5784
* `:breadcrumbs` - list of breadcrumbs
85+
* `:event_source` - the source of the event
5886
* `:level` - error level
5987
* `:fingerprint` - list of the fingerprint for grouping this event
6088
"""
@@ -69,9 +97,12 @@ defmodule Sentry.Event do
6997
} = Sentry.Context.get_all()
7098

7199
exception = Keyword.get(opts, :exception)
100+
original_exception = Keyword.get(opts, :original_exception)
72101

73102
message = Keyword.get(opts, :message)
74103

104+
event_source = Keyword.get(opts, :event_source)
105+
75106
stacktrace =
76107
Keyword.get(opts, :stacktrace, [])
77108
|> coerce_stacktrace()
@@ -113,6 +144,7 @@ defmodule Sentry.Event do
113144
environment: env,
114145
server_name: server_name,
115146
exception: exception,
147+
original_exception: original_exception,
116148
stacktrace: %{
117149
frames: stacktrace_to_frames(stacktrace)
118150
},
@@ -123,7 +155,8 @@ defmodule Sentry.Event do
123155
breadcrumbs: breadcrumbs,
124156
request: request,
125157
fingerprint: fingerprint,
126-
modules: Util.mix_deps_versions(@deps)
158+
modules: Util.mix_deps_versions(@deps),
159+
event_source: event_source
127160
}
128161
|> add_metadata()
129162
end
@@ -163,7 +196,7 @@ defmodule Sentry.Event do
163196
end
164197

165198
module = Keyword.get(opts, :module)
166-
exception = [%{type: type, value: value, module: module}]
199+
transformed_exception = [%{type: type, value: value, module: module}]
167200

168201
message =
169202
:error
@@ -172,8 +205,9 @@ defmodule Sentry.Event do
172205
|> String.trim()
173206

174207
opts
175-
|> Keyword.put(:exception, exception)
208+
|> Keyword.put(:exception, transformed_exception)
176209
|> Keyword.put(:message, message)
210+
|> Keyword.put(:original_exception, exception)
177211
|> create_event()
178212
end
179213

test/client_test.exs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,23 @@ defmodule Sentry.ClientTest do
182182
end
183183
end
184184

185+
test "falsey before_send_event does not send event" do
186+
modify_env(
187+
:sentry,
188+
before_send_event: {Sentry.BeforeSendEventTest, :before_send_event_ignore_arithmetic},
189+
client: Sentry.Client
190+
)
191+
192+
try do
193+
:random.uniform() + "1"
194+
rescue
195+
e ->
196+
capture_log(fn ->
197+
assert Sentry.capture_exception(e, result: :sync) == :excluded
198+
end)
199+
end
200+
end
201+
185202
test "calls anonymous after_send_event synchronously" do
186203
bypass = Bypass.open()
187204

test/support/test_before_send_event.exs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,14 @@ defmodule Sentry.BeforeSendEventTest do
33
metadata = Map.new(Logger.metadata())
44
%{event | extra: Map.merge(event.extra, metadata)}
55
end
6+
7+
def before_send_event_ignore_arithmetic(event) do
8+
case event.original_exception do
9+
%ArithmeticError{} ->
10+
false
11+
12+
_ ->
13+
event
14+
end
15+
end
616
end

0 commit comments

Comments
 (0)