fix(web): suppress HEAD request logs

The log_level(%{method: \"HEAD\"}) clause never matched because
Plug.Head rewrites the method to \"GET\" before Plug.Telemetry's
register_before_send callback fires, so by log time conn.method is
\"GET\". Stash the original method in private before Plug.Head runs
and key the filter off it.
This commit is contained in:
Graham McIntire 2026-04-22 16:50:50 -05:00
parent 024db2a5b4
commit 93b526c761
No known key found for this signature in database
GPG key ID: F4ABF488E6029E59
2 changed files with 39 additions and 1 deletions

View file

@ -46,6 +46,12 @@ defmodule MicrowavepropWeb.Endpoint do
plug Plug.RequestId
plug MicrowavepropWeb.Plugs.RemoteIp
# Plug.Head (below) rewrites method=HEAD to "GET" before
# Plug.Telemetry's register_before_send callback fires, so a
# `log_level(%{method: "HEAD"})` clause never matches. Capture
# the original method in private here so the log filter can still
# see HEAD requests and suppress them.
plug :stash_request_method
plug Plug.Telemetry, event_prefix: [:phoenix, :endpoint], log: {__MODULE__, :log_level, []}
plug Plug.Parsers,
@ -71,6 +77,10 @@ defmodule MicrowavepropWeb.Endpoint do
def log_level(%{request_path: "/live"}), do: false
def log_level(%{request_path: "/metrics"}), do: false
def log_level(%{request_path: "/metrics/" <> _}), do: false
def log_level(%{method: "HEAD"}), do: false
def log_level(%{private: %{original_method: "HEAD"}}), do: false
def log_level(_conn), do: :info
defp stash_request_method(conn, _opts) do
Plug.Conn.put_private(conn, :original_method, conn.method)
end
end

View file

@ -71,4 +71,32 @@ defmodule MicrowavepropWeb.MetricsLogSuppressionTest do
assert MicrowavepropWeb.Endpoint.log_level(rewritten) == false
end
test "log_level/1 returns false when the original method stashed before Plug.Head was HEAD" do
# Plug.Head runs BEFORE Plug.Telemetry's register_before_send fires
# and rewrites HEAD→GET, so matching `method: \"HEAD\"` at log time
# never hits. Endpoint now stashes the original method in private
# before Plug.Head runs; assert the filter keys off it.
conn = %{
request_path: "/some/page",
method: "GET",
private: %{original_method: "HEAD"}
}
assert MicrowavepropWeb.Endpoint.log_level(conn) == false
end
test "HEAD request to a real route does not emit a Phoenix endpoint Sent log line", %{
conn: conn
} do
log =
capture_log([level: :info], fn ->
conn = dispatch(conn, MicrowavepropWeb.Endpoint, "HEAD", "/")
assert conn.status in [200, 302]
end)
refute log =~ "Sent 200"
refute log =~ "Sent 302"
refute log =~ "HEAD /"
end
end