Packages
sentry
10.0.3
13.3.0
13.2.0
13.1.0
13.0.1
13.0.0
12.0.3
12.0.2
12.0.1
12.0.0
11.0.4
11.0.3
11.0.2
11.0.1
11.0.0
10.10.0
10.9.0
10.8.1
10.8.0
10.7.1
10.7.0
10.6.2
10.6.1
10.6.0
10.5.0
10.4.0
10.3.0
10.2.1
10.2.0
10.2.0-rc.2
10.2.0-rc.1
10.1.0
10.0.3
10.0.2
10.0.1
10.0.0
9.1.0
9.0.0
8.1.0
8.0.6
8.0.5
8.0.4
8.0.3
8.0.2
8.0.1
8.0.0
8.0.0-rc.2
8.0.0-rc.1
8.0.0-rc.0
retired
7.2.5
7.2.4
7.2.3
7.2.2
7.2.1
7.2.0
7.1.0
7.0.6
7.0.5
7.0.4
7.0.3
7.0.2
7.0.1
7.0.0
6.4.2
6.4.1
6.4.0
6.3.0
6.2.1
6.2.0
6.1.0
6.0.5
6.0.4
6.0.3
6.0.2
6.0.1
6.0.0
5.0.1
5.0.0
4.0.3
4.0.2
4.0.1
4.0.0
3.0.0
2.2.0
2.1.0
2.0.2
2.0.1
2.0.0
1.1.2
1.1.1
1.1.0
1.0.0
0.3.2
0.3.1
0.3.0
0.2.0
0.1.3
0.1.2
0.1.1
0.1.0
The Official Elixir client for Sentry
Current section
Files
Jump to
Current section
Files
lib/sentry/envelope.ex
defmodule Sentry.Envelope do
@moduledoc false
# https://develop.sentry.dev/sdk/envelopes/
alias Sentry.{Config, Event, UUID}
@type t() :: %__MODULE__{
event_id: UUID.t(),
items: [Event.t(), ...]
}
@enforce_keys [:event_id, :items]
defstruct [:event_id, :items]
@doc """
Creates a new envelope containing the given event.
Envelopes can only have a single element of type "event", so that's why we
restrict on a single-element list.
"""
@spec new([Event.t(), ...]) :: t()
def new([%Event{event_id: event_id}] = events) do
%__MODULE__{
event_id: event_id,
items: events
}
end
@doc """
Encodes the envelope into its binary representation.
For now, we support only envelopes with a single event in them.
"""
@spec to_binary(t()) :: {:ok, binary()} | {:error, any()}
def to_binary(%__MODULE__{items: [%Event{} = event]} = envelope) do
json_library = Config.json_library()
headers_iodata =
case envelope.event_id do
nil -> "{{}}\n"
event_id -> ~s({"event_id":"#{event_id}"}\n)
end
case event |> Sentry.Client.render_event() |> json_library.encode() do
{:ok, encoded_event} ->
body = [
headers_iodata,
~s({"type": "event", "length": #{byte_size(encoded_event)}}\n),
encoded_event,
?\n
]
{:ok, IO.iodata_to_binary(body)}
{:error, _reason} = error ->
error
end
end
@doc """
Decodes the envelope from its binary representation.
"""
@spec from_binary(String.t()) :: {:ok, t()} | {:error, :invalid_envelope}
def from_binary(binary) when is_binary(binary) do
json_library = Config.json_library()
[raw_headers | raw_items] = String.split(binary, "\n")
with {:ok, headers} <- json_library.decode(raw_headers),
{:ok, items} <- decode_items(raw_items, json_library) do
{:ok,
%__MODULE__{
event_id: headers["event_id"] || nil,
items: items
}}
else
{:error, _json_error} -> {:error, :invalid_envelope}
end
end
#
# Decoding
#
# Steps over the item pairs in the envelope body. The item header is decoded
# first so it can be used to decode the item following it.
defp decode_items(raw_items, json_library) do
items =
raw_items
|> Enum.chunk_every(2, 2, :discard)
|> Enum.map(fn [k, v] ->
with {:ok, item_header} <- json_library.decode(k),
{:ok, item} <- decode_item(item_header, v, json_library) do
item
else
{:error, _reason} = error -> throw(error)
end
end)
{:ok, items}
catch
{:error, reason} -> {:error, reason}
end
defp decode_item(%{"type" => "event"}, data, json_library) do
result = json_library.decode(data)
case result do
{:ok, fields} ->
{:ok,
%Event{
breadcrumbs: fields["breadcrumbs"],
culprit: fields["culprit"],
environment: fields["environment"],
event_id: fields["event_id"],
source: fields["event_source"],
exception: List.wrap(fields["exception"]),
extra: fields["extra"],
fingerprint: fields["fingerprint"],
level: fields["level"],
message: fields["message"],
modules: fields["modules"],
original_exception: fields["original_exception"],
platform: fields["platform"],
release: fields["release"],
request: fields["request"],
server_name: fields["server_name"],
tags: fields["tags"],
timestamp: fields["timestamp"],
user: fields["user"]
}}
{:error, e} ->
{:error, "Failed to decode event item: #{e}"}
end
end
defp decode_item(%{"type" => type}, _data, _json_library),
do: {:error, "unexpected item type '#{type}'"}
defp decode_item(_, _data, _json_library), do: {:error, "Missing item type header"}
end