Structured log formatting utilities for the Jido telemetry system.
Provides functions to format durations, metadata, directives, and other telemetry data into human-readable, scannable log output.
Examples
iex> Jido.Telemetry.Formatter.format_duration(1_500_000)
"1.5ms"
iex> Jido.Telemetry.Formatter.format_metadata(%{agent_id: "abc123", trace_id: "xyz"})
"agent_id=abc123 trace_id=xyz"
Summary
Functions
Extract just the keys from a map for safe logging.
Summarize action for logging without exposing full data.
Format directive summary map for logging.
Convert native time to human-readable format.
Format a complete log line with standard telemetry fields.
Format metadata map into a scannable key=value string for logs.
Format signal type for logging.
Inspect a term with a length limit.
Returns a map of directive_type => count from a list of directives.
Convert native time to milliseconds.
Functions
Extract just the keys from a map for safe logging.
Useful when you want to log what fields are present without exposing values.
Examples
iex> Formatter.extract_keys(%{user_id: 123, secret: "password", data: %{}})
[:data, :secret, :user_id]
iex> Formatter.extract_keys(nil)
[]
iex> Formatter.extract_keys("not a map")
[]
Summarize action for logging without exposing full data.
Shows the action/module name and parameter keys but not values.
Examples
iex> Formatter.format_action({:analyze, %{query: "secret", context: %{}}})
"{:analyze, keys: [:context, :query]}"
iex> Formatter.format_action(MyApp.Actions.ProcessData)
"MyApp.Actions.ProcessData"
iex> Formatter.format_action(%{action: :run, params: %{x: 1}})
"{:run, keys: [:x]}"
Format directive summary map for logging.
Examples
iex> Formatter.format_directive_types(%{emit: 2, tool: 1, await: 1})
"Await=1 Emit=2 Tool=1"
iex> Formatter.format_directive_types(%{})
""
Convert native time to human-readable format.
Returns a string like "1.2ms", "342μs", or "2.1s" depending on the magnitude.
Examples
iex> Formatter.format_duration(1_000)
"1μs"
iex> Formatter.format_duration(1_500_000)
"1.5ms"
iex> Formatter.format_duration(2_500_000_000)
"2.5s"
Format a complete log line with standard telemetry fields.
Combines multiple formatting functions into a single log-ready string.
Examples
iex> Formatter.format_log_line(%{
...> agent_id: "agent-1",
...> trace_id: "trace-abc",
...> signal_type: :user_request,
...> duration: 1_500_000
...> })
"agent_id=agent-1 duration=1.5ms signal_type=user_request trace_id=trace-abc"
Format metadata map into a scannable key=value string for logs.
Handles nil values gracefully and truncates long values.
Options
:max_value_length- Maximum length for individual values (default: 50)
Examples
iex> Formatter.format_metadata(%{agent_id: "abc123", trace_id: "xyz"})
"agent_id=abc123 trace_id=xyz"
iex> Formatter.format_metadata(%{key: nil, other: "value"})
"other=value"
iex> Formatter.format_metadata(nil)
""
Format signal type for logging.
Handles atoms and strings, converting to a readable format.
Examples
iex> Formatter.format_signal_type(:user_request)
"user_request"
iex> Formatter.format_signal_type("api_call")
"api_call"
iex> Formatter.format_signal_type(nil)
"unknown"
@spec safe_inspect(term(), pos_integer()) :: String.t()
Inspect a term with a length limit.
Safely inspects any term and truncates if necessary.
Examples
iex> Formatter.safe_inspect(%{a: 1, b: 2})
"%{a: 1, b: 2}"
iex> Formatter.safe_inspect(String.duplicate("x", 200), 50)
"\"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx..."
Returns a map of directive_type => count from a list of directives.
Examples
iex> directives = [%{type: :emit}, %{type: :emit}, %{type: :tool}]
iex> Formatter.summarize_directives(directives)
%{emit: 2, tool: 1}
iex> Formatter.summarize_directives([])
%{}
Convert native time to milliseconds.
Returns an integer for times >= 1ms, otherwise a float with precision.
Examples
iex> Formatter.to_ms(1_500_000)
1.5
iex> Formatter.to_ms(5_000_000)
5