From 350d36a86d283dbc3fbe258b456d17ef62865840 Mon Sep 17 00:00:00 2001 From: Gonzalo <456459+grzuy@users.noreply.github.com> Date: Mon, 19 Aug 2024 13:12:13 -0300 Subject: [PATCH] feat: properly handles Plug.Cowboy handled throws and exits --- lib/tower/logger_handler.ex | 4 +++ test/plug/tower_plug_test.exs | 62 ++++++++++++++++++++++++++++++++++- test/support/test_plug.ex | 12 +++++++ 3 files changed, 77 insertions(+), 1 deletion(-) diff --git a/lib/tower/logger_handler.ex b/lib/tower/logger_handler.ex index 7fad7d9..bb74f22 100644 --- a/lib/tower/logger_handler.ex +++ b/lib/tower/logger_handler.ex @@ -40,6 +40,10 @@ defmodule Tower.LoggerHandler do Tower.handle_exit(exit_reason, stacktrace, log_event: log_event) end + def log(%{level: :error, meta: %{crash_reason: exit_reason}} = log_event, _config) do + Tower.handle_exit(exit_reason, [], log_event: log_event) + end + def log(%{level: level, msg: {:string, reason_chardata}} = log_event, _config) do if should_handle?(level) do Tower.handle_message(level, IO.chardata_to_string(reason_chardata), log_event: log_event) diff --git a/test/plug/tower_plug_test.exs b/test/plug/tower_plug_test.exs index a08c2d7..69e5841 100644 --- a/test/plug/tower_plug_test.exs +++ b/test/plug/tower_plug_test.exs @@ -13,7 +13,7 @@ defmodule TowerPlugTest do end @tag capture_log: true - test "reports arithmetic error when a Plug.Conn IS present" do + test "reports arithmetic error during plug dispatch" do # An ephemeral port hopefully not being in the host running this code plug_port = 51111 url = "http://127.0.0.1:#{plug_port}/arithmetic-error" @@ -42,6 +42,66 @@ defmodule TowerPlugTest do assert Plug.Conn.request_url(plug_conn) == url end + @tag capture_log: true + test "reports uncaught throw during plug dispatch" do + # An ephemeral port hopefully not being in the host running this code + plug_port = 51111 + url = "http://127.0.0.1:#{plug_port}/uncaught-throw" + + start_link_supervised!({Plug.Cowboy, plug: Tower.TestPlug, scheme: :http, port: plug_port}) + + {:ok, _response} = :httpc.request(url) + + assert_eventually( + [ + %{ + id: id, + datetime: datetime, + level: :error, + kind: :throw, + reason: "something", + stacktrace: stacktrace, + plug_conn: %Plug.Conn{} = plug_conn + } + ] = Tower.EphemeralReporter.events() + ) + + assert String.length(id) == 36 + assert recent_datetime?(datetime) + assert is_list(stacktrace) + assert Plug.Conn.request_url(plug_conn) == url + end + + @tag capture_log: true + test "reports abnormal exit during plug dispatch" do + # An ephemeral port hopefully not being in the host running this code + plug_port = 51111 + url = "http://127.0.0.1:#{plug_port}/abnormal-exit" + + start_link_supervised!({Plug.Cowboy, plug: Tower.TestPlug, scheme: :http, port: plug_port}) + + {:ok, _response} = :httpc.request(url) + + assert_eventually( + [ + %{ + id: id, + datetime: datetime, + level: :error, + kind: :exit, + reason: :abnormal, + stacktrace: stacktrace, + plug_conn: %Plug.Conn{} = plug_conn + } + ] = Tower.EphemeralReporter.events() + ) + + assert String.length(id) == 36 + assert recent_datetime?(datetime) + assert is_list(stacktrace) + assert Plug.Conn.request_url(plug_conn) == url + end + test "reports message plug_conn manually" do Tower.handle_message( :info, diff --git a/test/support/test_plug.ex b/test/support/test_plug.ex index 694e949..40945b2 100644 --- a/test/support/test_plug.ex +++ b/test/support/test_plug.ex @@ -10,6 +10,18 @@ defmodule Tower.TestPlug do send_resp(conn, 200, "OK") end + get "/abnormal-exit" do + exit(:abnormal) + + send_resp(conn, 200, "OK") + end + + get "/uncaught-throw" do + throw("something") + + send_resp(conn, 200, "OK") + end + match _ do send_resp(conn, 404, "Not Found") end