prop/lib/microwaveprop/prom_ex/plugins/phoenix.ex
Graham McIntire 33e2ccf51a
Some checks failed
Build base image / Build and push base image (push) Has been cancelled
Build and Push / Build CI test image (push) Has been cancelled
Build and Push / Build and Push Docker Image (push) Has been cancelled
fix: remove TLS verify_none, validate recovered map state, normalize PromEx transport tags
- giro_client: remove verify: :verify_none, default to OTP :verify_peer
- map_live: validate recovered_band against BandConfig and recovered_time
  against time_in_window?/2 to prevent stale-state breakage
- prom_ex: local fork of Plugins.Phoenix that normalizes transport tag
  values to prevent telemetry_metrics_prometheus_core dropping series
2026-08-06 17:04:15 -05:00

99 lines
3.1 KiB
Elixir

defmodule Microwaveprop.PromEx.Plugins.Phoenix do
@moduledoc """
Local fork of `PromEx.Plugins.Phoenix` that normalizes the `:transport` tag
value in socket and channel event metrics so non-`String.Chars` transport
values (e.g., `Phoenix.ChannelTest`'s tuple `{Module, pid}`) are not
silently dropped as "bad tag value" by `telemetry_metrics_prometheus_core`.
All other metric groups are delegated to the built-in plugin unchanged.
"""
use PromEx.Plugin
alias Phoenix.Socket
alias PromEx.Plugins.Phoenix, as: BuiltinPhoenix
@impl true
def event_metrics(opts) do
# Delegate everything to the built-in plugin (which also attaches the
# telemetry proxy handlers), then patch only the transport tag in the
# two affected groups.
opts
|> BuiltinPhoenix.event_metrics()
|> Enum.map(fn
%{group_name: :phoenix_channel_event_metrics} = event ->
%{event | metrics: fix_channel_transport(event.metrics)}
%{group_name: :phoenix_socket_event_metrics} = event ->
%{event | metrics: fix_socket_transport(event.metrics)}
event ->
event
end)
end
# ── Channel event metrics ──────────────────────────────────────────────
defp fix_channel_transport(metrics) do
Enum.map(metrics, fn
%{event_name: [:phoenix, :channel_joined]} = metric ->
%{
metric
| tag_values: fn %{
result: result,
socket: %Socket{transport: transport, endpoint: endpoint}
} ->
%{
transport: normalize_transport(transport),
result: result,
endpoint: normalize_module_name(endpoint)
}
end
}
other ->
other
end)
end
# ── Socket event metrics ───────────────────────────────────────────────
defp fix_socket_transport(metrics) do
Enum.map(metrics, fn
%{event_name: [:phoenix, :socket_connected]} = metric ->
%{
metric
| tag_values: fn %{result: result, endpoint: endpoint, transport: transport} ->
%{
transport: normalize_transport(transport),
result: result,
endpoint: normalize_module_name(endpoint)
}
end
}
other ->
other
end)
end
# ── Helpers ────────────────────────────────────────────────────────────
defp normalize_transport(transport) do
if String.Chars.impl_for(transport) do
to_string(transport)
else
inspect(transport)
end
end
defp normalize_module_name(name) when is_atom(name) do
name
|> Atom.to_string()
|> String.trim_leading("Elixir.")
end
defp normalize_module_name(name) do
String.trim_leading(name, "Elixir.")
end
end