Skip to content

Commit 57ab1d0

Browse files
authored
Send async events right away without queueing (#612)
1 parent 2892eaf commit 57ab1d0

File tree

5 files changed

+37
-88
lines changed

5 files changed

+37
-88
lines changed

lib/sentry/client.ex

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,9 +84,7 @@ defmodule Sentry.Client do
8484
end
8585

8686
defp encode_and_send(%Event{} = event, _result_type = :sync, request_retries) do
87-
envelope = Envelope.new([event])
88-
89-
send_result = Transport.post_envelope(envelope, request_retries)
87+
send_result = [event] |> Envelope.new() |> Transport.post_envelope(request_retries)
9088

9189
if match?({:ok, _}, send_result) do
9290
Sentry.put_last_event_id_and_source(event.event_id, event.source)

lib/sentry/envelope.ex

Lines changed: 28 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,13 @@ defmodule Sentry.Envelope do
1313
defstruct [:event_id, :items]
1414

1515
@doc """
16-
Creates a new envelope containing the given events.
16+
Creates a new envelope containing the given event.
17+
18+
Envelopes can only have a single element of type "event", so that's why we
19+
restrict on a single-element list.
1720
"""
1821
@spec new([Event.t(), ...]) :: t()
19-
def new([%Event{event_id: event_id} | _rest] = events) do
22+
def new([%Event{event_id: event_id}] = events) do
2023
%__MODULE__{
2124
event_id: event_id,
2225
items: events
@@ -25,36 +28,33 @@ defmodule Sentry.Envelope do
2528

2629
@doc """
2730
Encodes the envelope into its binary representation.
31+
32+
For now, we support only envelopes with a single event in them.
2833
"""
2934
@spec to_binary(t()) :: {:ok, binary()} | {:error, any()}
30-
def to_binary(%__MODULE__{} = envelope) do
35+
def to_binary(%__MODULE__{items: [%Event{} = event]} = envelope) do
3136
json_library = Config.json_library()
3237

33-
encoded_items =
34-
Enum.map(envelope.items, fn item ->
35-
case encode_item(item, json_library) do
36-
{:ok, encoded_item} ->
37-
type =
38-
if is_struct(item, Event) do
39-
"event"
40-
else
41-
raise "unexpected item in envelope: #{inspect(item)}"
42-
end
43-
44-
[
45-
~s({"type": "#{type}", "length": #{byte_size(encoded_item)}}\n),
46-
encoded_item,
47-
?\n
48-
]
49-
50-
{:error, _reason} = error ->
51-
throw(error)
52-
end
53-
end)
54-
55-
{:ok, IO.iodata_to_binary([encode_headers(envelope) | encoded_items])}
56-
catch
57-
{:error, reason} -> {:error, reason}
38+
headers_iodata =
39+
case envelope.event_id do
40+
nil -> "{{}}\n"
41+
event_id -> ~s({"event_id":"#{event_id}"}\n)
42+
end
43+
44+
case event |> Sentry.Client.render_event() |> json_library.encode() do
45+
{:ok, encoded_event} ->
46+
body = [
47+
headers_iodata,
48+
~s({"type": "event", "length": #{byte_size(encoded_event)}}\n),
49+
encoded_event,
50+
?\n
51+
]
52+
53+
{:ok, IO.iodata_to_binary(body)}
54+
55+
{:error, _reason} = error ->
56+
error
57+
end
5858
end
5959

6060
@doc """
@@ -79,23 +79,6 @@ defmodule Sentry.Envelope do
7979
end
8080
end
8181

82-
#
83-
# Encoding
84-
#
85-
86-
defp encode_headers(%__MODULE__{} = envelope) do
87-
case envelope.event_id do
88-
nil -> "{{}}\n"
89-
event_id -> ~s({"event_id":"#{event_id}"}\n)
90-
end
91-
end
92-
93-
defp encode_item(%Event{} = event, json_library) do
94-
event
95-
|> Sentry.Client.render_event()
96-
|> json_library.encode()
97-
end
98-
9982
#
10083
# Decoding
10184
#

lib/sentry/transport/sender.ex

Lines changed: 5 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,6 @@ defmodule Sentry.Transport.Sender do
99

1010
@registry Sentry.Transport.SenderRegistry
1111

12-
@async_queue_max_size 10
13-
@async_queue_timeout 500
14-
1512
# This behaviour is only present for mocks in tests.
1613
defmodule Behaviour do
1714
@moduledoc false
@@ -39,54 +36,27 @@ defmodule Sentry.Transport.Sender do
3936

4037
## State
4138

42-
defstruct async_queue: :queue.new()
39+
defstruct []
4340

4441
## Callbacks
4542

4643
@impl GenServer
4744
def init([]) do
48-
Process.send_after(self(), :flush_async_queue, @async_queue_timeout)
4945
{:ok, %__MODULE__{}}
5046
end
5147

5248
@impl GenServer
5349
def handle_cast({:send, %Event{} = event}, %__MODULE__{} = state) do
54-
state = update_in(state.async_queue, &:queue.in(event, &1))
55-
56-
state =
57-
if :queue.len(state.async_queue) >= @async_queue_max_size do
58-
flush_async_queue(state)
59-
else
60-
state
61-
end
50+
[event]
51+
|> Envelope.new()
52+
|> Transport.post_envelope()
53+
|> maybe_log_send_result([event])
6254

6355
{:noreply, state}
6456
end
6557

66-
@impl GenServer
67-
def handle_info(:flush_async_queue, %__MODULE__{} = state) do
68-
state = flush_async_queue(state)
69-
Process.send_after(self(), :flush_async_queue, @async_queue_timeout)
70-
{:noreply, state}
71-
end
72-
7358
## Helpers
7459

75-
defp flush_async_queue(%__MODULE__{async_queue: events_queue} = state) do
76-
if :queue.is_empty(events_queue) do
77-
state
78-
else
79-
events = :queue.to_list(events_queue)
80-
81-
events
82-
|> Envelope.new()
83-
|> Transport.post_envelope()
84-
|> maybe_log_send_result(events)
85-
86-
%__MODULE__{state | async_queue: :queue.new()}
87-
end
88-
end
89-
9060
defp maybe_log_send_result(send_result, events) do
9161
if Enum.any?(events, &(&1.source == :logger)) do
9262
:ok

test/envelope_test.exs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,8 @@ defmodule Sentry.EnvelopeTest do
7171

7272
{:ok, raw_envelope} =
7373
[event]
74-
|> Sentry.Envelope.new()
75-
|> Sentry.Envelope.to_binary()
74+
|> Envelope.new()
75+
|> Envelope.to_binary()
7676

7777
{:ok, envelope} = Envelope.from_binary(raw_envelope)
7878

test/sentry/transport_test.exs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,7 @@ defmodule Sentry.TransportTest do
1515
test "sends a POST request with the right headers and payload", %{bypass: bypass} do
1616
envelope =
1717
Envelope.new([
18-
Event.create_event(message: "Hello 1"),
19-
Event.create_event(message: "Hello 2"),
20-
Event.create_event(message: "Hello 3")
18+
Event.create_event(message: "Hello 1")
2119
])
2220

2321
Bypass.expect_once(bypass, fn conn ->

0 commit comments

Comments
 (0)