chopratejas commited on
Commit
6a51c39
·
1 Parent(s): 257873b

Fixing the build AND the perf logs

Browse files
headroom/perf/analyzer.py CHANGED
@@ -39,8 +39,18 @@ _TOIN_RE = re.compile(
39
 
40
 
41
  def _parse_kv(kv_str: str) -> dict[str, str]:
42
- """Parse key=value pairs from a PERF log line."""
 
 
 
 
 
43
  result: dict[str, str] = {}
 
 
 
 
 
44
  for part in kv_str.split():
45
  if "=" in part:
46
  k, v = part.split("=", 1)
@@ -143,7 +153,21 @@ def parse_log_files(last_n_hours: float = 168.0) -> PerfReport:
143
  if m:
144
  kv = _parse_kv(m.group("kv"))
145
  transforms_str = kv.get("transforms", "none")
146
- transforms = transforms_str.split(",") if transforms_str != "none" else []
 
 
 
 
 
 
 
 
 
 
 
 
 
 
147
  report.perf_records.append(
148
  PerfRecord(
149
  timestamp=m.group("ts"),
 
39
 
40
 
41
  def _parse_kv(kv_str: str) -> dict[str, str]:
42
+ """Parse key=value pairs from a PERF log line.
43
+
44
+ The ``transforms=`` field is always last and its value may contain spaces
45
+ (e.g. ``transforms=router:excluded:tool*32 read_lifecycle:stale*17``).
46
+ Everything after ``transforms=`` is captured as a single value.
47
+ """
48
  result: dict[str, str] = {}
49
+ # Handle transforms= specially since its value contains spaces
50
+ if "transforms=" in kv_str:
51
+ before, transforms_val = kv_str.split("transforms=", 1)
52
+ result["transforms"] = transforms_val.strip()
53
+ kv_str = before
54
  for part in kv_str.split():
55
  if "=" in part:
56
  k, v = part.split("=", 1)
 
153
  if m:
154
  kv = _parse_kv(m.group("kv"))
155
  transforms_str = kv.get("transforms", "none")
156
+ # Handle both old comma-separated and new space-separated *N format
157
+ if transforms_str == "none":
158
+ transforms: list[str] = []
159
+ elif "*" in transforms_str or " " in transforms_str:
160
+ # New format: "router:excluded:tool*32 read_lifecycle:stale*17"
161
+ transforms = []
162
+ for part in transforms_str.split():
163
+ if "*" in part:
164
+ name, _ = part.rsplit("*", 1)
165
+ else:
166
+ name = part
167
+ transforms.append(name)
168
+ else:
169
+ # Old comma-separated format
170
+ transforms = transforms_str.split(",")
171
  report.perf_records.append(
172
  PerfRecord(
173
  timestamp=m.group("ts"),
headroom/proxy/server.py CHANGED
@@ -175,6 +175,22 @@ def _setup_file_logging() -> None:
175
 
176
  _setup_file_logging()
177
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
178
  # Maximum request body size (100MB - increased to support image-heavy requests)
179
  MAX_REQUEST_BODY_SIZE = 100 * 1024 * 1024
180
 
@@ -2286,7 +2302,7 @@ class HeadroomProxy:
2286
  f"tok_saved={tokens_saved} "
2287
  f"cache_read={cr} cache_write={cw} cache_hit_pct={chp} "
2288
  f"opt_ms={optimization_latency:.0f} "
2289
- f"transforms={','.join(transforms_applied) if transforms_applied else 'none'}"
2290
  )
2291
 
2292
  # Remove compression headers since httpx already decompressed the response
@@ -3909,7 +3925,7 @@ class HeadroomProxy:
3909
  f"cache_read={cache_read_tokens} cache_write={cache_write_tokens} "
3910
  f"cache_hit_pct={cache_hit_pct} "
3911
  f"opt_ms={optimization_latency:.0f} "
3912
- f"transforms={','.join(transforms_applied) if transforms_applied else 'none'}"
3913
  )
3914
 
3915
  # Normalize input tokens based on provider semantics:
@@ -4098,7 +4114,7 @@ class HeadroomProxy:
4098
  f"tok_saved={tokens_saved} "
4099
  f"cache_read=0 cache_write=0 cache_hit_pct=0 "
4100
  f"opt_ms={optimization_latency:.0f} "
4101
- f"transforms={','.join(transforms_applied) if transforms_applied else 'none'}"
4102
  )
4103
 
4104
  return StreamingResponse(
 
175
 
176
  _setup_file_logging()
177
 
178
+
179
+ def _summarize_transforms(transforms: list[str]) -> str:
180
+ """Collapse repeated transforms into counted summary.
181
+
182
+ e.g. ['router:excluded:tool', 'router:excluded:tool', 'read_lifecycle:stale']
183
+ → 'router:excluded:tool*2 read_lifecycle:stale'
184
+ """
185
+ if not transforms:
186
+ return "none"
187
+ counts: dict[str, int] = {}
188
+ for t in transforms:
189
+ counts[t] = counts.get(t, 0) + 1
190
+ parts = [f"{k}*{v}" if v > 1 else k for k, v in counts.items()]
191
+ return " ".join(parts)
192
+
193
+
194
  # Maximum request body size (100MB - increased to support image-heavy requests)
195
  MAX_REQUEST_BODY_SIZE = 100 * 1024 * 1024
196
 
 
2302
  f"tok_saved={tokens_saved} "
2303
  f"cache_read={cr} cache_write={cw} cache_hit_pct={chp} "
2304
  f"opt_ms={optimization_latency:.0f} "
2305
+ f"transforms={_summarize_transforms(transforms_applied)}"
2306
  )
2307
 
2308
  # Remove compression headers since httpx already decompressed the response
 
3925
  f"cache_read={cache_read_tokens} cache_write={cache_write_tokens} "
3926
  f"cache_hit_pct={cache_hit_pct} "
3927
  f"opt_ms={optimization_latency:.0f} "
3928
+ f"transforms={_summarize_transforms(transforms_applied)}"
3929
  )
3930
 
3931
  # Normalize input tokens based on provider semantics:
 
4114
  f"tok_saved={tokens_saved} "
4115
  f"cache_read=0 cache_write=0 cache_hit_pct=0 "
4116
  f"opt_ms={optimization_latency:.0f} "
4117
+ f"transforms={_summarize_transforms(transforms_applied)}"
4118
  )
4119
 
4120
  return StreamingResponse(