defmodule TelemetryTest do @moduledoc """ Telemetry Test Helper For example usage please refer to test/examples directory """ use ExUnit.Case alias TelemetryTest.Server defguard is_event(value) when is_list(value) and is_atom(hd(value)) def telemetry_listen(%{telemetry_listen: event, test: test_name}) when is_event(event) do attach_helper(test_name, event, :this_is_a_config, &__MODULE__.send_to_self_handler/4) end def telemetry_listen(%{telemetry_listen: {event_name, telemetry_listen_fn}, test: test_name}) when is_function(telemetry_listen_fn) do test_ref = make_ref() attach_helper(test_name, event_name, test_ref, &__MODULE__.push_handler/4) on_exit(fn -> {:ok, result} = Server.pop(test_ref) telemetry_listen_fn.(result) end) end def telemetry_listen(%{telemetry_listen: {event_name, {mod, fun_name, args}}, test: test_name}) do test_ref = make_ref() attach_helper(test_name, event_name, test_ref, &__MODULE__.push_handler/4) on_exit(fn -> {:ok, result} = Server.pop(test_ref) apply(mod, fun_name, [result | args]) end) end def telemetry_listen(%{telemetry_listen: matchers} = context) do for matcher <- matchers do new_context = Map.put(context, :telemetry_listen, matcher) telemetry_listen(new_context) end context end def telemetry_listen(context), do: context defp attach_helper(test_name, event_name, config, callback_fn) do handler_name = "#{test_name}-#{:rand.uniform()}-handler" :ok = :telemetry.attach(handler_name, event_name, callback_fn, config) on_exit(fn -> :ok = :telemetry.detach(handler_name) end) end # This function is only public to avoid a warning about optimization def push_handler(event, measurements, metadata, test_ref) do args = %{event: event, measurements: measurements, metadata: metadata} :ok = Server.push(test_ref, args) end # This function is only public to avoid a warning about optimization def send_to_self_handler(event, measurements, metadata, _config) do args = %{event: event, measurements: measurements, metadata: metadata} send(self(), {:telemetry_event, args}) end end