feat: expand shusub2 log metrics

This commit is contained in:
2026-07-27 20:50:55 +08:00
parent b248a6c9c1
commit 4d8d117fb1
5 changed files with 83 additions and 22 deletions
+55 -13
View File
@@ -19,7 +19,7 @@ from typing import Any
APP_NAME = "shusub2"
FALLBACK_VERSION = "0.2.9"
FALLBACK_VERSION = "0.2.10"
DEFAULT_API_URL = "http://127.0.0.1:18318/api/tui/accounts"
DEFAULT_CONFIG_FILE = "~/.config/shusub2/api-url"
DEFAULT_STATUS_CONFIG_FILE = "~/.config/shusub2/status-url"
@@ -397,13 +397,12 @@ def log_type_label(item: dict[str, Any]) -> str:
return text or "-"
def log_cache_tokens(item: dict[str, Any]) -> int:
return as_int(item.get("cache_creation_tokens")) + as_int(item.get("cache_read_tokens"))
def log_total_tokens(item: dict[str, Any]) -> int:
return (
as_int(item.get("input_tokens"))
+ as_int(item.get("output_tokens"))
+ as_int(item.get("cache_creation_tokens"))
+ as_int(item.get("cache_read_tokens"))
)
return as_int(item.get("input_tokens")) + as_int(item.get("output_tokens")) + log_cache_tokens(item)
def log_tokens_per_second(item: dict[str, Any]) -> float:
@@ -583,6 +582,7 @@ def normalize_log_rows(payload: dict[str, Any], filter_text: str = "") -> list[d
"output_tokens": as_int(item.get("output_tokens")),
"cache_creation_tokens": as_int(item.get("cache_creation_tokens")),
"cache_read_tokens": as_int(item.get("cache_read_tokens")),
"cache_tokens": log_cache_tokens(item),
"cost": as_float(item.get("total_cost")),
"actual_cost": as_float(item.get("actual_cost")),
"duration_ms": as_int(item.get("duration_ms")),
@@ -629,7 +629,7 @@ def log_detail_line(row: dict[str, Any]) -> str:
f"tokens in {format_count(row['input_tokens'])} out {format_count(row['output_tokens'])} "
f"cache_w {format_count(row['cache_creation_tokens'])} cache_r {format_count(row['cache_read_tokens'])} | "
f"cost {format_cost(row['cost'])} (actual {format_cost(row['actual_cost'])}) | "
f"first {format_seconds(row['first_token_ms'])} latency {format_seconds(row['duration_ms'])} "
f"first {format_seconds(row['first_token_ms'])} duration {format_seconds(row['duration_ms'])} "
f"{format_rate(row['tokens_per_second'])}"
)
if row["request_id"]:
@@ -640,7 +640,7 @@ def log_detail_line(row: dict[str, Any]) -> str:
def print_logs_once(payload: dict[str, Any], filter_text: str = "") -> None:
rows = normalize_log_rows(payload, filter_text)
print(logs_summary_line(payload, len(rows)))
print("key account model effort type tokens cost first latency tok/s time age")
print("key account model effort type input output cache tokens cost first duration tok/s time age")
for row in rows:
print(
f"{row['key'][:20]:<21} "
@@ -648,10 +648,13 @@ def print_logs_once(payload: dict[str, Any], filter_text: str = "") -> None:
f"{row['model'][:24]:<25} "
f"{row['effort']:<7} "
f"{row['type']:<7} "
f"{format_count(row['input_tokens']):<8} "
f"{format_count(row['output_tokens']):<8} "
f"{format_count(row['cache_tokens']):<8} "
f"{format_count(row['tokens']):<8} "
f"{format_cost(row['cost']):<10} "
f"{format_seconds(row['first_token_ms']):<8} "
f"{format_seconds(row['duration_ms']):<8} "
f"{format_seconds(row['duration_ms']):<10} "
f"{format_rate(row['tokens_per_second']):<8} "
f"{row['time']:<11} "
f"{row['age']}"
@@ -1277,7 +1280,21 @@ def run_textual(
)
self.configure_table(
self.query_one("#logs", DataTable),
("LOG KEY", "Account", "Model", "Cost", "Latency", "Time", "Age"),
(
"LOG KEY",
"Account",
"Model",
"First",
"Duration",
"Tok/s",
"Input",
"Output",
"Cache",
"Tokens",
"Cost",
"Time",
"Age",
),
)
self.configure_table(
self.query_one("#errors", DataTable),
@@ -1445,8 +1462,14 @@ def run_textual(
Text(row["key"], style=color) if color else row["key"],
row["account"],
row["model"],
format_cost(row["cost"]),
format_seconds(row["first_token_ms"]),
format_seconds(row["duration_ms"]),
format_rate(row["tokens_per_second"]),
format_count(row["input_tokens"]),
format_count(row["output_tokens"]),
format_count(row["cache_tokens"]),
format_count(row["tokens"]),
format_cost(row["cost"]),
row["time"],
row["age"],
key=key,
@@ -1772,7 +1795,23 @@ def run_textual(
table = self.query_one("#logs", DataTable)
table.cursor_type = "row"
table.zebra_stripes = True
table.add_columns("Key", "Account", "Model", "Effort", "Type", "Tokens", "Cost", "First", "Latency", "Tok/s", "Time", "Age")
table.add_columns(
"Key",
"Account",
"Model",
"Effort",
"Type",
"Input",
"Output",
"Cache",
"Tokens",
"Cost",
"First",
"Duration",
"Tok/s",
"Time",
"Age",
)
self.refresh_data()
self.set_interval(logs_refresh_seconds, self.refresh_data)
@@ -1826,6 +1865,9 @@ def run_textual(
row["model"],
row["effort"],
row["type"],
format_count(row["input_tokens"]),
format_count(row["output_tokens"]),
format_count(row["cache_tokens"]),
format_count(row["tokens"]),
format_cost(row["cost"]),
format_seconds(row["first_token_ms"]),