defmodule MicrowavepropWeb.TelemetryTest do use Microwaveprop.DataCase, async: false alias Ecto.Adapters.SQL.Sandbox alias MicrowavepropWeb.Telemetry describe "metrics/0" do test "returns a flat list of Telemetry.Metrics structs" do metrics = Telemetry.metrics() assert metrics != [] assert Enum.any?(metrics) for m <- metrics do assert %{name: _, event_name: event_name, measurement: _} = m # Every metric carries its event path as a list of atoms. assert event_name != [] assert Enum.all?(event_name, &is_atom/1) end end test "covers each of the metric categories defined in the module" do # The categories are private functions that build distinct event # name prefixes; check one canonical metric per category exists. names = Enum.map(Telemetry.metrics(), & &1.name) name_strings = Enum.map(names, &Enum.join(&1, ".")) assert "phoenix.endpoint.stop.duration" in name_strings assert "microwaveprop.repo.query.total_time" in name_strings assert Enum.any?(name_strings, &String.starts_with?(&1, "vm.")) assert Enum.any?(name_strings, &String.starts_with?(&1, "microwaveprop.oban.")) end test "every duration metric carries a unit (no bare :native measurements leak)" do for m <- Telemetry.metrics(), String.ends_with?(to_string(List.last(m.name)), "duration") do assert m.unit != :unit, "#{inspect(m.name)} should declare a display unit" end end end describe "dispatch_oban_queue_depth/0" do test "emits one `oban.queue.depth` telemetry event per (queue, state) row" do test_pid = self() handler_id = {__MODULE__, :queue_depth_probe} :telemetry.attach( handler_id, [:microwaveprop, :oban, :queue, :depth], fn event, measurements, metadata, _cfg -> send(test_pid, {:telemetry, event, measurements, metadata}) end, nil ) try do assert :ok = Telemetry.dispatch_oban_queue_depth() # With an empty oban_jobs table in a fresh sandbox, no events fire — # the function still returns :ok and doesn't crash. If any rows # happen to be there, each must carry a queue+state tag. receive do {:telemetry, [:microwaveprop, :oban, :queue, :depth], %{count: n}, meta} -> assert is_integer(n) assert byte_size(meta.queue) > 0 assert Map.has_key?(meta, :state) after 200 -> :ok end after :telemetry.detach(handler_id) end end test "swallows DB errors without crashing the poller" do # Manually close the sandbox connection so any DB query raises; # the poller must still return :ok (telemetry is best-effort). Sandbox.checkin(Microwaveprop.Repo) assert :ok = Telemetry.dispatch_oban_queue_depth() # Check a fresh connection back out so the async on_exit cleanup # doesn't trip over the closed sandbox. Sandbox.checkout(Microwaveprop.Repo) end end describe "start_link/1" do test "start_link/1 is defined and can be called" do # The Telemetry supervisor uses name: __MODULE__, so it may already be # started by the application. Verify the function handles either case. case Telemetry.start_link(:ok) do {:ok, pid} -> Process.unlink(pid) Process.exit(pid, :kill) {:error, {:already_started, _pid}} -> :ok end end end end