To use Hammox telemetry for performance tracing (e.g., with Spandex), implement a handle_event/4 function. You can capture start events to begin a span, stop events to finish it, and exception events to record errors in the trace.
Note that [:hammox, :expect, :start] provides metadata like :mock and :function_name, while measurements typically contains timing information like :system_time or :duration.
defmodule HammoxTelemetryHandler do
alias Spandex.Tracer
def handle_event([:hammox, :expect, :start], measurements, metadata, _config) do
when is_map(measurements)
mock_name = Map.get(metadata, :mock)
func_name = Map.get(metadata, :name)
expect_count = Map.get(metadata, :count) |> to_string()
tags =
[]
|> tags_put(:mock, mock_name)
|> tags_put(:func_name, func_name)
|> tags_put(:expect_count, expect_count)
system_time = get_time(measurements, :system_time)
if Tracer.current_trace_id() do
span_string = "#{mock_name}.#{func_name}" |> String.trim_leading("Elixir.")
span_string = "expect #{span_string}"
_span_context = Tracer.start_span(span_string, service: :hammox, tags: tags)
Tracer.update_span(start: system_time)
end
end
def handle_event([:hammox, :expect, :stop], measurements, _metadata, _config) do
handle_exception(measurements)
end
def handle_event([:hammox, :expect, :exception], measurements, _metadata, _config) do
handle_exception(measurements)
end
defp handle_exception(measurements) do
error_message = "Exception occurred during hammox execution"
Logger.error(error_message)
if Tracer.current_trace_id() do
current_span = Tracer.current_span([])
Tracer.update_span_with_error(error_message, current_span)
end
handle_stop(measurements)
end
defp handle_stop(measurements, tags \ []) do
duration_time = get_time(measurements, :duration)
case Tracer.current_span([]) do
%{start: start_time} ->
completion_time = start_time + duration_time
Tracer.update_span(tags: tags, completion_time: completion_time)
Tracer.finish_span()
_no_current_span ->
:ok
end
end
defp get_time(log_entry, key) do
Map.get(log_entry, key)
end
end