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