Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 10 additions & 24 deletions lib/legion_web/usage_aggregator.ex
Original file line number Diff line number Diff line change
Expand Up @@ -78,11 +78,9 @@ defmodule LegionWeb.UsageAggregator do
@doc """
Plain-text hover card for a list of usage entries.

A time line, then aligned columns for tokens and cost. One entry gets its
request time; several get the request count and their time span. Meant for
`white-space: pre` rendering in a monospace font.
Aligned columns for tokens and cost; several entries open with their request
count. Meant for `white-space: pre` rendering in a monospace font.

22:15:58 UTC
input 4,930 cached 4,000
output 132 reasoning 640
cost $0.003 estimated at list prices
Expand All @@ -92,24 +90,18 @@ defmodule LegionWeb.UsageAggregator do
totals = totals(entries)

Enum.join(
[
time_line(entries),
row("input", format_count(totals.input), "cached", format_count(totals.cached)),
row("output", format_count(totals.output), "reasoning", format_count(totals.reasoning)),
cost_line(totals.cost)
],
count_line(entries) ++
[
row("input", format_count(totals.input), "cached", format_count(totals.cached)),
row("output", format_count(totals.output), "reasoning", format_count(totals.reasoning)),
cost_line(totals.cost)
],
"\n"
)
end

defp time_line([entry]), do: "#{format_time(entry["at"])} UTC"

defp time_line(entries) do
first = List.first(entries)
last = List.last(entries)

"#{length(entries)} requests · #{format_time(first["at"])} – #{format_time(last["at"])} UTC"
end
defp count_line([_]), do: []
defp count_line(entries), do: ["#{length(entries)} requests"]

defp row(label, value, second_label, second_value) do
String.pad_trailing(label, 6) <>
Expand All @@ -126,12 +118,6 @@ defmodule LegionWeb.UsageAggregator do
String.pad_leading(format_cost(cost), 8) <> " estimated at list prices"
end

defp format_time(ms) when is_integer(ms) do
ms |> DateTime.from_unix!(:millisecond) |> Calendar.strftime("%H:%M:%S")
end

defp format_time(_), do: "--:--:--"

defp add_cost(acc, cost) when is_number(cost), do: (acc || 0) + cost
defp add_cost(acc, _), do: acc
end
2 changes: 1 addition & 1 deletion test/legion_web/components/trace_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ defmodule LegionWeb.Components.TraceTest do
html = render_component(&Trace.render/1, items: [step("x", [usage])], language: nil)

assert html =~ "↑4.9k"
assert html =~ "22:15:58 UTC"
assert html =~ "input 4,930"
end

test "renders no chip on a step without usage" do
Expand Down
3 changes: 1 addition & 2 deletions test/legion_web/components/usage_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ defmodule LegionWeb.Components.UsageTest do
assert html =~ "↑4.9k"
assert html =~ "↓132"
assert html =~ "$0.003"
assert html =~ "22:15:58 UTC"
assert html =~ "reasoning 640"
end

Expand All @@ -80,7 +79,7 @@ defmodule LegionWeb.Components.UsageTest do
assert html =~ "↑10.0k"
assert html =~ "↓544"
assert html =~ "$0.007"
assert html =~ "2 requests · 22:15:58 – 22:16:07 UTC"
assert html =~ "2 requests"
end
end
end
8 changes: 3 additions & 5 deletions test/legion_web/usage_aggregator_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -78,21 +78,19 @@ defmodule LegionWeb.UsageAggregatorTest do
"at" => 1_700_000_158_000
}

test "lays one request out as aligned columns under its time" do
test "lays one request out as aligned columns" do
assert Usage.card([@entry]) ==
"""
22:15:58 UTC
input 4,930 cached 4,000
output 132 reasoning 640
cost $0.003 estimated at list prices\
"""
end

test "opens with the request count and time span for several entries" do
test "opens with the request count for several entries" do
second = %{@entry | "at" => 1_700_000_167_000, "input_tokens" => 5_070}

assert Usage.card([@entry, second]) |> String.split("\n") |> hd() ==
"2 requests · 22:15:58 – 22:16:07 UTC"
assert Usage.card([@entry, second]) |> String.split("\n") |> hd() == "2 requests"
end

test "counts missing counters as zero" do
Expand Down
Loading