IMT TAF Fiabilité : Test de charge
# Dependencies
Mix.install([
{:kino, "~> 0.6.2"},
{:kino_vega_lite, "~> 0.1.0"},
{:nimble_csv, "~> 1.2"},
{:explorer, "~> 0.3.1"}
])
# Data
NimbleCSV.define(DataParser, [])
alias VegaLite, as: Vl
alias Explorer.DataFrame
alias Explorer.Series
Analyse des données
Table
df =
DataFrame.from_csv!("data/stats.csv", header: false, parse_dates: true)
|> DataFrame.rename(["id", "ts", "path", "latency", "res", "res_desc"])
ts = df["ts"] |> Series.transform(&"#{DateTime.from_unix!(&1, :millisecond)}")
grouppath = df["path"] |> Series.transform(&"/#{&1 |> String.split("/") |> Enum.at(1)}")
df =
df
|> DataFrame.mutate([{"ts", ts}])
|> DataFrame.mutate([{"grouppath", grouppath}])
DataFrame.table(df)
Analyse de latences par route
df
|> DataFrame.group_by("grouppath")
|> DataFrame.summarise_with(
&[
{"min", Series.min(&1["latency"])},
{"max", Series.max(&1["latency"])},
{"mean", Series.mean(&1["latency"])},
{"median", Series.median(&1["latency"])}
]
)
|> DataFrame.table()
Visualisation
Latence
data =
"data/stats.csv"
|> File.stream!()
|> DataParser.parse_stream(skip_headers: false)
|> Stream.zip(Stream.iterate(0, &(&1 + 1)))
|> Enum.map(fn {[id, ts, path, latency, res, res_desc], pos} ->
%{
pos: pos,
id: id,
ts: ts,
path: path,
latency: String.to_integer(latency),
res: res,
res_desc: res_desc
}
end)
encode_color = fn vl ->
Vl.encode_field(vl, :color, "lat_nom",
type: :nominal,
title: "Latency",
scale: %{
domain: ["failed", "t<20ms", "20ms200ms"],
range: ["#ff0000", "#4eac5b", "#608ece", "#fffc54", "#ef7b36"]
}
)
end
vl_data =
Vl.new(width: 700)
|> Vl.data_from_values(data)
|> Vl.transform(
calculate:
"datum.res == \"ko\" ? \"failed\" : datum.latency < 20 ? \"t<20ms\" : datum.latency < 40 ? \"20ms200ms\"",
as: "lat_nom"
)
|> Vl.transform(calculate: "join(split(datum.path, \"/\", 2), \"/\")", as: "grouppath")
vl_data
|> encode_color.()
|> Vl.encode_field(:x, "lat_nom",
sort: ["failed", "t<20ms", "20ms200ms"],
title: "Latency"
)
|> Vl.encode_field(:y, "id", aggregate: :count)
|> Vl.mark(:bar)
vl_data
|> encode_color.()
|> Vl.mark(:arc)
|> Vl.encode_field(:theta, "id", aggregate: :count)
vl_data
|> Vl.mark(:line, point: true)
|> Vl.encode_field(:color, "grouppath", type: :nominal)
|> Vl.encode_field(:y, "latency", type: :quantitative)
|> Vl.encode_field(:x, "pos")
vl_data
|> Vl.mark(:boxplot, median: %{color: :white}, ticks: true)
|> Vl.encode_field(:color, "grouppath", type: :nominal, legend: nil)
|> Vl.encode_field(:x, "grouppath", type: :nominal)
|> Vl.encode_field(:y, "latency", type: :quantitative)