Skip to content

Commit

Permalink
Add support for sending telemetry events on throws and exits
Browse files Browse the repository at this point in the history
  • Loading branch information
mtrudel committed Dec 27, 2024
1 parent 61d975d commit 267d8fe
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 21 deletions.
6 changes: 1 addition & 5 deletions lib/bandit/pipeline.ex
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,7 @@ defmodule Bandit.Pipeline do
exception ->
handle_error(:error, exception, __STACKTRACE__, transport, span, opts, conn)
catch
:throw, value ->
handle_error(:throw, value, __STACKTRACE__, transport, span, opts, conn)

:exit, value ->
handle_error(:exit, value, __STACKTRACE__, transport, span, opts, conn)
kind, value -> handle_error(kind, value, __STACKTRACE__, transport, span, opts, conn)
end
rescue
exception ->
Expand Down
15 changes: 7 additions & 8 deletions lib/bandit/telemetry.ex
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,8 @@ defmodule Bandit.Telemetry do
is also set and the nature of error is such that Bandit was unable to successfully build
the conn
* `kind`: The kind of unexpected condition, typically `:exit`
* `exception`: The exception which caused this unexpected termination
* `exception`: The exception which caused this unexpected termination. May be an exception
or an arbitrary value when the event was an uncaught throw or an exit
* `stacktrace`: The stacktrace of the location which caused this unexpected termination
## `[:bandit, :websocket, *]`
Expand Down Expand Up @@ -190,22 +191,20 @@ defmodule Bandit.Telemetry do

@spec span_exception(t(), Exception.kind(), Exception.t() | term(), Exception.stacktrace()) ::
:ok
def span_exception(span, :error, reason, stacktrace) when is_exception(reason) do
def span_exception(span, kind, reason, stacktrace) do
# Using :exit for backwards-compatibility with Bandit =< 1.5.7
kind = if kind == :error, do: :exit, else: kind

metadata =
Map.merge(span.start_metadata, %{
# Using :exit for backwards-compatibility with Bandit =< 1.5.7
kind: :exit,
kind: kind,
exception: reason,
stacktrace: stacktrace
})

span_event(span, :exception, %{}, metadata)
end

def span_exception(_span, _kind, _reason, _stacktrace) do
:ok
end

@doc false
@spec span_event(t(), span_name(), :telemetry.event_measurements(), :telemetry.event_metadata()) ::
:ok
Expand Down
30 changes: 26 additions & 4 deletions test/bandit/http1/request_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -2413,7 +2413,7 @@ defmodule HTTP1RequestTest do
assert output =~ "(RuntimeError) boom"
end

test "it should not send `exception` events for throwing requests", context do
test "it should send `exception` events for throwing requests", context do
output =
capture_log(fn ->
{:ok, collector_pid} =
Expand All @@ -2423,7 +2423,18 @@ defmodule HTTP1RequestTest do

Process.sleep(100)

assert [] = Bandit.TelemetryCollector.get_events(collector_pid)
assert Bandit.TelemetryCollector.get_events(collector_pid)
~> [
{[:bandit, :request, :exception], %{monotonic_time: integer()},
%{
connection_telemetry_span_context: reference(),
telemetry_span_context: reference(),
conn: struct_like(Plug.Conn, []),
kind: :throw,
exception: "thrown",
stacktrace: list()
}}
]
end)

assert output =~ "(throw) \"thrown\""
Expand All @@ -2433,7 +2444,7 @@ defmodule HTTP1RequestTest do
throw("thrown")
end

test "it should not send `exception` events for exiting requests", context do
test "it should send `exception` events for exiting requests", context do
output =
capture_log(fn ->
{:ok, collector_pid} =
Expand All @@ -2443,7 +2454,18 @@ defmodule HTTP1RequestTest do

Process.sleep(100)

assert [] = Bandit.TelemetryCollector.get_events(collector_pid)
assert Bandit.TelemetryCollector.get_events(collector_pid)
~> [
{[:bandit, :request, :exception], %{monotonic_time: integer()},
%{
connection_telemetry_span_context: reference(),
telemetry_span_context: reference(),
conn: struct_like(Plug.Conn, []),
kind: :exit,
exception: "exited",
stacktrace: list()
}}
]
end)

assert output =~ "(exit) \"exited\""
Expand Down
30 changes: 26 additions & 4 deletions test/bandit/http2/plug_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -1027,7 +1027,7 @@ defmodule HTTP2PlugTest do
raise "boom"
end

test "it should not send `exception` events for throwing requests", context do
test "it should send `exception` events for throwing requests", context do
output =
capture_log(fn ->
{:ok, collector_pid} =
Expand All @@ -1037,7 +1037,18 @@ defmodule HTTP2PlugTest do

Process.sleep(100)

assert [] = Bandit.TelemetryCollector.get_events(collector_pid)
assert Bandit.TelemetryCollector.get_events(collector_pid)
~> [
{[:bandit, :request, :exception], %{monotonic_time: integer()},
%{
connection_telemetry_span_context: reference(),
telemetry_span_context: reference(),
conn: struct_like(Plug.Conn, []),
kind: :throw,
exception: "thrown",
stacktrace: list()
}}
]
end)

assert output =~ "(throw) \"thrown\""
Expand All @@ -1047,7 +1058,7 @@ defmodule HTTP2PlugTest do
throw("thrown")
end

test "it should not send `exception` events for exiting requests", context do
test "it should send `exception` events for exiting requests", context do
output =
capture_log(fn ->
{:ok, collector_pid} =
Expand All @@ -1057,7 +1068,18 @@ defmodule HTTP2PlugTest do

Process.sleep(100)

assert [] = Bandit.TelemetryCollector.get_events(collector_pid)
assert Bandit.TelemetryCollector.get_events(collector_pid)
~> [
{[:bandit, :request, :exception], %{monotonic_time: integer()},
%{
connection_telemetry_span_context: reference(),
telemetry_span_context: reference(),
conn: struct_like(Plug.Conn, []),
kind: :exit,
exception: "exited",
stacktrace: list()
}}
]
end)

assert output =~ "(exit) \"exited\""
Expand Down

0 comments on commit 267d8fe

Please sign in to comment.