@@ -1743,4 +1743,228 @@ defmodule LoggerHandlerKit.Act do
17431743 end
17441744
17451745 def metadata_serialization ( case ) , do: Logger . metadata ( extra: Map . fetch! ( @ metadata_types , case ) )
1746+
1747+ @ doc """
1748+ Starts a web server powered by Cowboy or Bandit and sends a request that triggers an error during the Plug pipeline.
1749+
1750+ See [Plug integration guide](guides/plug-integration.md) for more details.
1751+
1752+ <!-- tabs-open -->
1753+
1754+ ### Example Test
1755+
1756+ ```elixir
1757+ # You only need to create your own router if you want to test custom plugs that somehow affect logging
1758+ defmodule MyPlug do
1759+ use Plug.Router
1760+
1761+ plug MyCustomPlug
1762+ plug :match
1763+ plug :dispatch
1764+
1765+ forward "/", to: LoggerHandlerKit.Plug
1766+ end
1767+
1768+ test "Bandit: plug exception", %{handler_ref: ref, io_ref: io_ref} do
1769+ LoggerHandlerKit.Act.plug_error(:exception, Bandit, MyPlug)
1770+ LoggerHandlerKit.Assert.assert_logged(ref)
1771+
1772+ # handler-specific assertions
1773+ end
1774+ ```
1775+
1776+ ### Example Log Event (Bandit)
1777+
1778+ ```elixir
1779+ %{
1780+ meta: %{
1781+ line: 242,
1782+ pid: #PID<0.556.0>,
1783+ time: 1750196815012775,
1784+ file: ~c"lib/bandit/pipeline.ex",
1785+ gl: #PID<0.69.0>,
1786+ domain: [:elixir, :bandit],
1787+ application: :bandit,
1788+ mfa: {Bandit.Pipeline, :handle_error, 7},
1789+ plug: {LoggerHandlerKit.Plug, %{test_pid: #PID<0.240.0>}},
1790+ conn: %Plug.Conn{...},
1791+ crash_reason: {%RuntimeError{message: "oops"},
1792+ [
1793+ {LoggerHandlerKit.Plug, :"-do_match/4-fun-1-", 2,
1794+ [
1795+ file: ~c"lib/logger_handler_kit/plug.ex",
1796+ line: 8,
1797+ error_info: %{module: Exception}
1798+ ]},
1799+ {LoggerHandlerKit.Plug, :"-dispatch/2-fun-0-", 4,
1800+ [file: ~c"deps/plug/lib/plug/router.ex", line: 246]},
1801+ {:telemetry, :span, 3,
1802+ [
1803+ file: ~c"/Users/user/projects/logger_handler_kit/deps/telemetry/src/telemetry.erl",
1804+ line: 324
1805+ ]},
1806+ {LoggerHandlerKit.Plug, :dispatch, 2,
1807+ [file: ~c"deps/plug/lib/plug/router.ex", line: 242]},
1808+ {LoggerHandlerKit.Plug, :plug_builder_call, 2,
1809+ [file: ~c"lib/logger_handler_kit/plug.ex", line: 1]},
1810+ {Bandit.Pipeline, :call_plug!, 2,
1811+ [file: ~c"lib/bandit/pipeline.ex", line: 131]},
1812+ {Bandit.Pipeline, :run, 5, [file: ~c"lib/bandit/pipeline.ex", line: 42]},
1813+ {Bandit.HTTP1.Handler, :handle_data, 3,
1814+ [file: ~c"lib/bandit/http1/handler.ex", line: 13]},
1815+ {Bandit.DelegatingHandler, :handle_data, 3,
1816+ [file: ~c"lib/bandit/delegating_handler.ex", line: 18]},
1817+ {Bandit.DelegatingHandler, :handle_continue, 2,
1818+ [file: ~c"lib/bandit/delegating_handler.ex", line: 8]},
1819+ {:gen_server, :try_handle_continue, 3,
1820+ [file: ~c"gen_server.erl", line: 2335]},
1821+ {:gen_server, :loop, 7, [file: ~c"gen_server.erl", line: 2244]},
1822+ {:proc_lib, :init_p_do_apply, 3, [file: ~c"proc_lib.erl", line: 329]}
1823+ ]}
1824+ },
1825+ msg: {:string,
1826+ "** (RuntimeError) oops\n (logger_handler_kit 0.2.0) lib/logger_handler_kit/plug.ex:8: anonymous fn/2 in LoggerHandlerKit.Plug.do_match/4\n (logger_handler_kit 0.2.0) deps/plug/lib/plug/router.ex:246: anonymous fn/4 in LoggerHandlerKit.Plug.dispatch/2\n (telemetry 1.3.0) /Users/user/projects/logger_handler_kit/deps/telemetry/src/telemetry.erl:324: :telemetry.span/3\n (logger_handler_kit 0.2.0) deps/plug/lib/plug/router.ex:242: LoggerHandlerKit.Plug.dispatch/2\n (logger_handler_kit 0.2.0) lib/logger_handler_kit/plug.ex:1: LoggerHandlerKit.Plug.plug_builder_call/2\n (bandit 1.7.0) lib/bandit/pipeline.ex:131: Bandit.Pipeline.call_plug!/2\n (bandit 1.7.0) lib/bandit/pipeline.ex:42: Bandit.Pipeline.run/5\n (bandit 1.7.0) lib/bandit/http1/handler.ex:13: Bandit.HTTP1.Handler.handle_data/3\n (bandit 1.7.0) lib/bandit/delegating_handler.ex:18: Bandit.DelegatingHandler.handle_data/3\n (bandit 1.7.0) lib/bandit/delegating_handler.ex:8: Bandit.DelegatingHandler.handle_continue/2\n (stdlib 6.2.2) gen_server.erl:2335: :gen_server.try_handle_continue/3\n (stdlib 6.2.2) gen_server.erl:2244: :gen_server.loop/7\n (stdlib 6.2.2) proc_lib.erl:329: :proc_lib.init_p_do_apply/3\n "},
1827+ level: :error
1828+ }
1829+ ```
1830+
1831+ ### Example Log Event (Cowboy) (Elixir 1.19+)
1832+
1833+ ```elixir
1834+ %{
1835+ meta: %{
1836+ error_logger: %{tag: :error},
1837+ pid: #PID<0.454.0>,
1838+ time: 1750197653870258,
1839+ gl: #PID<0.69.0>,
1840+ domain: [:cowboy],
1841+ report_cb: &Logger.Utils.translated_cb/1,
1842+ conn: %Plug.Conn{...},
1843+ crash_reason: {%RuntimeError{message: "oops"},
1844+ [
1845+ {LoggerHandlerKit.Plug, :"-do_match/4-fun-1-", 2,
1846+ [
1847+ file: ~c"lib/logger_handler_kit/plug.ex",
1848+ line: 8,
1849+ error_info: %{module: Exception}
1850+ ]},
1851+ {LoggerHandlerKit.Plug, :"-dispatch/2-fun-0-", 4,
1852+ [file: ~c"deps/plug/lib/plug/router.ex", line: 246]},
1853+ {:telemetry, :span, 3,
1854+ [
1855+ file: ~c"/Users/user/projects/logger_handler_kit/deps/telemetry/src/telemetry.erl",
1856+ line: 324
1857+ ]},
1858+ {LoggerHandlerKit.Plug, :dispatch, 2,
1859+ [file: ~c"deps/plug/lib/plug/router.ex", line: 242]},
1860+ {LoggerHandlerKit.Plug, :plug_builder_call, 2,
1861+ [file: ~c"lib/logger_handler_kit/plug.ex", line: 1]},
1862+ {Plug.Cowboy.Handler, :init, 2,
1863+ [file: ~c"lib/plug/cowboy/handler.ex", line: 11]},
1864+ {:cowboy_handler, :execute, 2,
1865+ [
1866+ file: ~c"/Users/user/projects/logger_handler_kit/deps/cowboy/src/cowboy_handler.erl",
1867+ line: 37
1868+ ]},
1869+ {:cowboy_stream_h, :execute, 3,
1870+ [
1871+ file: ~c"/Users/user/projects/logger_handler_kit/deps/cowboy/src/cowboy_stream_h.erl",
1872+ line: 310
1873+ ]},
1874+ {:cowboy_stream_h, :request_process, 3,
1875+ [
1876+ file: ~c"/Users/user/projects/logger_handler_kit/deps/cowboy/src/cowboy_stream_h.erl",
1877+ line: 299
1878+ ]},
1879+ {:proc_lib, :init_p_do_apply, 3, [file: ~c"proc_lib.erl", line: 329]}
1880+ ]}
1881+ },
1882+ msg: {:report,
1883+ %{
1884+ args: [
1885+ LoggerHandlerKit.Plug.HTTP,
1886+ #PID<0.454.0>,
1887+ 1,
1888+ #PID<0.455.0>,
1889+ {{{%RuntimeError{message: "oops"},
1890+ [
1891+ {LoggerHandlerKit.Plug, :"-do_match/4-fun-1-", 2,
1892+ [
1893+ file: ~c"lib/logger_handler_kit/plug.ex",
1894+ line: 8,
1895+ error_info: %{module: Exception}
1896+ ]},
1897+ {LoggerHandlerKit.Plug, :"-dispatch/2-fun-0-", 4,
1898+ [file: ~c"deps/plug/lib/plug/router.ex", line: 246]},
1899+ {:telemetry, :span, 3,
1900+ [
1901+ file: ~c"/Users/user/projects/logger_handler_kit/deps/telemetry/src/telemetry.erl",
1902+ line: 324
1903+ ]},
1904+ {LoggerHandlerKit.Plug, :dispatch, 2,
1905+ [file: ~c"deps/plug/lib/plug/router.ex", line: 242]},
1906+ {LoggerHandlerKit.Plug, :plug_builder_call, 2,
1907+ [file: ~c"lib/logger_handler_kit/plug.ex", line: 1]},
1908+ {Plug.Cowboy.Handler, :init, 2,
1909+ [file: ~c"lib/plug/cowboy/handler.ex", line: 11]},
1910+ {:cowboy_handler, :execute, 2,
1911+ [
1912+ file: ~c"/Users/user/projects/logger_handler_kit/deps/cowboy/src/cowboy_handler.erl",
1913+ line: 37
1914+ ]},
1915+ {:cowboy_stream_h, :execute, 3,
1916+ [
1917+ file: ~c"/Users/user/projects/logger_handler_kit/deps/cowboy/src/cowboy_stream_h.erl",
1918+ line: 310
1919+ ]},
1920+ {:cowboy_stream_h, :request_process, 3,
1921+ [
1922+ file: ~c"/Users/user/projects/logger_handler_kit/deps/cowboy/src/cowboy_stream_h.erl",
1923+ line: 299
1924+ ]},
1925+ {:proc_lib, :init_p_do_apply, 3,
1926+ [file: ~c"proc_lib.erl", line: 329]}
1927+ ]},
1928+ {LoggerHandlerKit.Plug, :call,
1929+ [
1930+ %Plug.Conn{},
1931+ %{test_pid: #PID<0.238.0>}
1932+ ]}}, []}
1933+ ],
1934+ label: {:error_logger, :error_msg},
1935+ format: ~c"Ranch listener ~p, connection process ~p, stream ~p had its request process ~p exit with reason ~0p~n",
1936+ elixir_translation: [
1937+ "#PID<0.455.0>",
1938+ " running ",
1939+ "LoggerHandlerKit.Plug",
1940+ [" (connection ", "#PID<0.454.0>", ", stream id ", "1", 41],
1941+ " terminated\n ",
1942+ [
1943+ ["Server: ", "localhost", ":", "8001", 32, 40, "http", 41, 10],
1944+ ["Request: ", "GET", 32, "/exception", 10]
1945+ ] |
1946+ "** (exit) an exception was raised:\n ** (RuntimeError) oops\n (logger_handler_kit 0.2.0) lib/logger_handler_kit/plug.ex:8: anonymous fn/2 in LoggerHandlerKit.Plug.do_match/4\n (logger_handler_kit 0.2.0) deps/plug/lib/plug/router.ex:246: anonymous fn/4 in LoggerHandlerKit.Plug.dispatch/2\n (telemetry 1.3.0) /Users/user/projects/logger_handler_kit/deps/telemetry/src/telemetry.erl:324: :telemetry.span/3\n (logger_handler_kit 0.2.0) deps/plug/lib/plug/router.ex:242: LoggerHandlerKit.Plug.dispatch/2\n (logger_handler_kit 0.2.0) lib/logger_handler_kit/plug.ex:1: LoggerHandlerKit.Plug.plug_builder_call/2\n (plug_cowboy 2.7.3) lib/plug/cowboy/handler.ex:11: Plug.Cowboy.Handler.init/2\n (cowboy 2.13.0) /Users/user/projects/logger_handler_kit/deps/cowboy/src/cowboy_handler.erl:37: :cowboy_handler.execute/2\n (cowboy 2.13.0) /Users/user/projects/logger_handler_kit/deps/cowboy/src/cowboy_stream_h.erl:310: :cowboy_stream_h.execute/3\n (cowboy 2.13.0) /Users/user/projects/logger_handler_kit/deps/cowboy/src/cowboy_stream_h.erl:299: :cowboy_stream_h.request_process/3\n (stdlib 6.2.2) proc_lib.erl:329: :proc_lib.init_p_do_apply/3"
1947+ ]
1948+ }},
1949+ level: :error
1950+ }
1951+ ```
1952+
1953+ <!-- tabs-close -->
1954+ """
1955+ @ doc group: "Plug"
1956+ @ spec plug_error ( :exception | :throw | :exit , Bandit | Plug.Cowboy , module ( ) ) :: :ok
1957+ def plug_error (
1958+ flavour \\ :exception ,
1959+ web_server \\ Bandit ,
1960+ router_plug \\ LoggerHandlerKit.Plug
1961+ ) do
1962+ ExUnit.Callbacks . start_supervised! (
1963+ { web_server , [ plug: { router_plug , % { test_pid: self ( ) } } , scheme: :http , port: 8001 ] }
1964+ )
1965+
1966+ { :ok , conn } = Mint.HTTP . connect ( :http , "localhost" , 8001 )
1967+ { :ok , _conn , _request_ref } = Mint.HTTP . request ( conn , "GET" , "/#{ flavour } " , [ ] , nil )
1968+ :ok
1969+ end
17461970end
0 commit comments