defmodule Chaperon.Export.CSV do
@moduledoc """
CSV metrics export module.
"""
@behaviour Chaperon.Exporter
alias Chaperon.Util
alias Chaperon.Scenario.Metrics
@separator ","
@delimiter "\n"
@doc """
Encodes metrics of given `session` into CSV format.
"""
@impl Chaperon.Exporter
def encode(session, opts \\ []) do
separator = opts |> Keyword.get(:separator, @separator)
delimiter = opts |> Keyword.get(:delimiter, @delimiter)
data = encode_header(separator) <> delimiter <> (session |> encode_rows(separator, delimiter))
{:ok, data}
end
@impl Chaperon.Exporter
def write_output(lt_mod, options, data, filename) do
runtime_config = Keyword.get(options, :config, %{})
Chaperon.write_output_to_file(lt_mod, runtime_config, data, filename <> ".csv")
end
@header_fields [
"session_action_name",
"total_count",
"max",
"mean",
"min"
] ++ for(p <- Metrics.percentiles(), do: "percentile_#{p}")
@columns [
:total_count,
:max,
:mean,
:min
] ++ for(p <- Metrics.percentiles(), do: {:percentile, p})
defp encode_header(separator) do
@header_fields
|> Enum.join(separator)
end
defp encode_rows(session, separator, delimiter) do
session.metrics
|> Enum.flat_map(fn
{{:call, {mod, func}}, vals} ->
mod_name = Util.shortened_module_name(mod)
encode_runs(vals, "call(#{mod_name}.#{func})", separator)
{{{:error, {:http, code}}, {action, url}}, vals} ->
encode_runs(vals, "Error HTTP #{code} #{action}(#{url})", separator)
{{action, url}, vals} ->
encode_runs(vals, "#{action}(#{url})", separator)
{action, vals} ->
encode_runs(vals, "#{action}", separator)
end)
|> Enum.join(delimiter)
end
defp encode_runs(runs, action_name, separator) when is_list(runs) do
runs
|> Enum.map(&encode_row(&1, action_name, separator))
end
defp encode_runs(run, action_name, separator) do
[encode_row(run, action_name, separator)]
end
defp encode_row(vals, action_name, separator) when is_map(vals) do
session_name = vals[:session_name]
"#{session_name} #{action_name}" <> separator <> encode_row_values(vals, separator)
end
defp encode_row_values(vals, separator) do
Enum.map_join(@columns, separator, &round(vals[&1]))
end
end