defmodule TelemetryTest do @moduledoc """ For example usage please refer to [test/examples](https://github.com/highmobility/telemetry_test/tree/main/test/examples) directory """ use ExUnit.Case alias TelemetryTest.Server defguardp is_event(value) when is_list(value) and is_atom(hd(value)) @doc """ ExUnit setup callback function which attaches to telemetry events """ @doc since: "0.1.0" def telemetry_listen(%{telemetry_listen: event, test: test_name}) when is_event(event) do attach_helper(test_name, event, self(), &__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 @doc false # 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 @doc false # This function is only public to avoid a warning about optimization def __send_to_self_handler__(event, measurements, metadata, config_test_pid) do args = %{event: event, measurements: measurements, metadata: metadata} send(config_test_pid, {:telemetry_event, args}) end end