From 76e2cb1928ac2a2116f5aa6062c3f2baf8890b70 Mon Sep 17 00:00:00 2001 From: Tejas Chopra Date: Sat, 7 Mar 2026 15:28:02 -0800 Subject: [PATCH] Fixing the build AND the perf logs --- headroom/perf/analyzer.py | 28 ++++++++++++++++++++++++++-- headroom/proxy/server.py | 22 +++++++++++++++++++--- 2 files changed, 45 insertions(+), 5 deletions(-) diff --git a/headroom/perf/analyzer.py b/headroom/perf/analyzer.py index cd65c53c8..862acff27 100644 --- a/headroom/perf/analyzer.py +++ b/headroom/perf/analyzer.py @@ -39,8 +39,18 @@ _TOIN_RE = re.compile( def _parse_kv(kv_str: str) -> dict[str, str]: - """Parse key=value pairs from a PERF log line.""" + """Parse key=value pairs from a PERF log line. + + The ``transforms=`` field is always last and its value may contain spaces + (e.g. ``transforms=router:excluded:tool*32 read_lifecycle:stale*17``). + Everything after ``transforms=`` is captured as a single value. + """ result: dict[str, str] = {} + # Handle transforms= specially since its value contains spaces + if "transforms=" in kv_str: + before, transforms_val = kv_str.split("transforms=", 1) + result["transforms"] = transforms_val.strip() + kv_str = before for part in kv_str.split(): if "=" in part: k, v = part.split("=", 1) @@ -143,7 +153,21 @@ def parse_log_files(last_n_hours: float = 168.0) -> PerfReport: if m: kv = _parse_kv(m.group("kv")) transforms_str = kv.get("transforms", "none") - transforms = transforms_str.split(",") if transforms_str != "none" else [] + # Handle both old comma-separated and new space-separated *N format + if transforms_str == "none": + transforms: list[str] = [] + elif "*" in transforms_str or " " in transforms_str: + # New format: "router:excluded:tool*32 read_lifecycle:stale*17" + transforms = [] + for part in transforms_str.split(): + if "*" in part: + name, _ = part.rsplit("*", 1) + else: + name = part + transforms.append(name) + else: + # Old comma-separated format + transforms = transforms_str.split(",") report.perf_records.append( PerfRecord( timestamp=m.group("ts"), diff --git a/headroom/proxy/server.py b/headroom/proxy/server.py index 241ca2b36..13415e543 100644 --- a/headroom/proxy/server.py +++ b/headroom/proxy/server.py @@ -175,6 +175,22 @@ def _setup_file_logging() -> None: _setup_file_logging() + +def _summarize_transforms(transforms: list[str]) -> str: + """Collapse repeated transforms into counted summary. + + e.g. ['router:excluded:tool', 'router:excluded:tool', 'read_lifecycle:stale'] + → 'router:excluded:tool*2 read_lifecycle:stale' + """ + if not transforms: + return "none" + counts: dict[str, int] = {} + for t in transforms: + counts[t] = counts.get(t, 0) + 1 + parts = [f"{k}*{v}" if v > 1 else k for k, v in counts.items()] + return " ".join(parts) + + # Maximum request body size (100MB - increased to support image-heavy requests) MAX_REQUEST_BODY_SIZE = 100 * 1024 * 1024 @@ -2286,7 +2302,7 @@ class HeadroomProxy: f"tok_saved={tokens_saved} " f"cache_read={cr} cache_write={cw} cache_hit_pct={chp} " f"opt_ms={optimization_latency:.0f} " - f"transforms={','.join(transforms_applied) if transforms_applied else 'none'}" + f"transforms={_summarize_transforms(transforms_applied)}" ) # Remove compression headers since httpx already decompressed the response @@ -3909,7 +3925,7 @@ class HeadroomProxy: f"cache_read={cache_read_tokens} cache_write={cache_write_tokens} " f"cache_hit_pct={cache_hit_pct} " f"opt_ms={optimization_latency:.0f} " - f"transforms={','.join(transforms_applied) if transforms_applied else 'none'}" + f"transforms={_summarize_transforms(transforms_applied)}" ) # Normalize input tokens based on provider semantics: @@ -4098,7 +4114,7 @@ class HeadroomProxy: f"tok_saved={tokens_saved} " f"cache_read=0 cache_write=0 cache_hit_pct=0 " f"opt_ms={optimization_latency:.0f} " - f"transforms={','.join(transforms_applied) if transforms_applied else 'none'}" + f"transforms={_summarize_transforms(transforms_applied)}" ) return StreamingResponse(