Files
wehub-resource-sync 0ef5fcb1c5
Security / Dependency audit (pip-audit) (push) Has been cancelled
Security / CodeQL (javascript-typescript) (push) Has been cancelled
Security / CodeQL (python) (push) Has been cancelled
Security / Secret scan (gitleaks) (push) Has been cancelled
rust / test (ubuntu) (push) Has been cancelled
rust / simulator e2e (macos-latest) (push) Has been cancelled
rust / simulator e2e (ubuntu-latest) (push) Has been cancelled
rust / simulator e2e (windows-latest) (push) Has been cancelled
rust / wheels (aarch64-apple-darwin) (push) Has been cancelled
rust / wheels (x86_64-unknown-linux-gnu) (push) Has been cancelled
rust / wheels (x86_64-apple-darwin) (push) Has been cancelled
rust / audit (push) Has been cancelled
rust / parity (nightly, allowed to fail during Phase 0) (push) Has been cancelled
CI / commitlint (push) Has been skipped
Dev Containers / validate (.devcontainer/devcontainer.json, default) (push) Failing after 0s
Dev Containers / validate (.devcontainer/memory-stack/devcontainer.json, memory-stack) (push) Failing after 0s
Dev Containers / validate-worktree (push) Failing after 0s
CI / changes (push) Failing after 4s
Deploy Documentation / validate (push) Has been skipped
Deploy Documentation / deploy (push) Failing after 1s
Init Native E2E / init-native (ubuntu-latest, claude) (push) Failing after 1s
Init Native E2E / init-native (ubuntu-latest, codex) (push) Failing after 1s
Install Native E2E / install-native (ubuntu-latest) (push) Failing after 1s
OpenCode Plugin / typecheck + build + test (push) Failing after 1s
Init Native E2E / init-native (ubuntu-latest, copilot) (push) Failing after 1s
Release Please / release-please (push) Failing after 1s
Wrap E2E / docker-wrap-e2e (push) Failing after 1s
Wrap Native E2E / wrap-native (ubuntu-latest) (push) Failing after 1s
Init E2E / docker-init-e2e (push) Failing after 4s
Merge Conflicts / merge-conflicts (push) Failing after 4s
CI / lint (push) Has been cancelled
CI / build-wheel (push) Has been cancelled
CI / build-wheel-windows (push) Has been cancelled
CI / prefetch-model (push) Has been cancelled
CI / test-dashboard-ui (push) Has been cancelled
CI / test (1) (push) Has been cancelled
CI / test (2) (push) Has been cancelled
CI / test (3) (push) Has been cancelled
CI / test (4) (push) Has been cancelled
CI / test-extras (push) Has been cancelled
CI / test-agno (push) Has been cancelled
CI / build (push) Has been cancelled
CI / workflow-validation (push) Has been cancelled
CI / docker-native-e2e (push) Has been cancelled
CI / windows-native-wrapper (push) Has been cancelled
CI / macos-native-wrapper (push) Has been cancelled
Docker / docker-build (map[name:arm64 platform:linux/arm64 runs_on:ubuntu-24.04-arm], map[bake_target:runtime-code-nonroot name:code-nonroot]) (push) Has been cancelled
Docker / docker-build (map[name:arm64 platform:linux/arm64 runs_on:ubuntu-24.04-arm], map[bake_target:runtime-code-slim name:code-slim]) (push) Has been cancelled
Docker / docker-build (map[name:arm64 platform:linux/arm64 runs_on:ubuntu-24.04-arm], map[bake_target:runtime-code-slim-nonroot name:code-slim-nonroot]) (push) Has been cancelled
Docker / docker-build (map[name:arm64 platform:linux/arm64 runs_on:ubuntu-24.04-arm], map[bake_target:runtime-nonroot name:nonroot]) (push) Has been cancelled
Docker / docker-build (map[name:arm64 platform:linux/arm64 runs_on:ubuntu-24.04-arm], map[bake_target:runtime-slim name:slim]) (push) Has been cancelled
Docker / docker-build (map[name:arm64 platform:linux/arm64 runs_on:ubuntu-24.04-arm], map[bake_target:runtime-slim-nonroot name:slim-nonroot]) (push) Has been cancelled
Docker / docker-manifest (map[bake_target:runtime name:]) (push) Has been cancelled
Docker / docker-manifest (map[bake_target:runtime-code name:code]) (push) Has been cancelled
Docker / docker-manifest (map[bake_target:runtime-code-nonroot name:code-nonroot]) (push) Has been cancelled
Docker / docker-manifest (map[bake_target:runtime-code-slim name:code-slim]) (push) Has been cancelled
Docker / docker-manifest (map[bake_target:runtime-code-slim-nonroot name:code-slim-nonroot]) (push) Has been cancelled
Docker / docker-manifest (map[bake_target:runtime-nonroot name:nonroot]) (push) Has been cancelled
Docker / docker-manifest (map[bake_target:runtime-slim name:slim]) (push) Has been cancelled
Docker / docker-manifest (map[bake_target:runtime-slim-nonroot name:slim-nonroot]) (push) Has been cancelled
Docker / docker-build (map[name:amd64 platform:linux/amd64 runs_on:ubuntu-24.04], map[bake_target:runtime name:]) (push) Has been cancelled
Docker / docker-build (map[name:amd64 platform:linux/amd64 runs_on:ubuntu-24.04], map[bake_target:runtime-code name:code]) (push) Has been cancelled
Docker / docker-build (map[name:amd64 platform:linux/amd64 runs_on:ubuntu-24.04], map[bake_target:runtime-code-nonroot name:code-nonroot]) (push) Has been cancelled
Docker / docker-build (map[name:amd64 platform:linux/amd64 runs_on:ubuntu-24.04], map[bake_target:runtime-code-slim name:code-slim]) (push) Has been cancelled
Docker / docker-build (map[name:amd64 platform:linux/amd64 runs_on:ubuntu-24.04], map[bake_target:runtime-code-slim-nonroot name:code-slim-nonroot]) (push) Has been cancelled
Docker / docker-build (map[name:amd64 platform:linux/amd64 runs_on:ubuntu-24.04], map[bake_target:runtime-nonroot name:nonroot]) (push) Has been cancelled
Docker / docker-build (map[name:amd64 platform:linux/amd64 runs_on:ubuntu-24.04], map[bake_target:runtime-slim name:slim]) (push) Has been cancelled
Docker / docker-build (map[name:amd64 platform:linux/amd64 runs_on:ubuntu-24.04], map[bake_target:runtime-slim-nonroot name:slim-nonroot]) (push) Has been cancelled
Docker / docker-build (map[name:arm64 platform:linux/arm64 runs_on:ubuntu-24.04-arm], map[bake_target:runtime name:]) (push) Has been cancelled
Docker / docker-build (map[name:arm64 platform:linux/arm64 runs_on:ubuntu-24.04-arm], map[bake_target:runtime-code name:code]) (push) Has been cancelled
Docker / promote-latest (push) Has been cancelled
Init Native E2E / init-native (macos-latest, claude) (push) Has been cancelled
Init Native E2E / init-native (macos-latest, codex) (push) Has been cancelled
Init Native E2E / init-native (macos-latest, copilot) (push) Has been cancelled
Install Native E2E / install-native (macos-latest) (push) Has been cancelled
Wrap Native E2E / wrap-native (macos-latest) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:03:20 +08:00

295 lines
9.8 KiB
Python

from __future__ import annotations
from dataclasses import dataclass
from datetime import datetime, timedelta
from pathlib import Path
from types import SimpleNamespace
from headroom.config import RequestMetrics
from headroom.storage import JSONLStorage, SQLiteStorage, Storage, create_storage
def _metrics(
request_id: str,
timestamp: datetime,
model: str = "gpt-4o",
mode: str = "audit",
before: int = 100,
after: int = 80,
) -> RequestMetrics:
return RequestMetrics(
request_id=request_id,
timestamp=timestamp,
model=model,
stream=False,
mode=mode,
tokens_input_before=before,
tokens_input_after=after,
tokens_output=25,
block_breakdown={"system": 10},
waste_signals={"json_bloat": 3},
stable_prefix_hash="prefix",
cache_alignment_score=75.0,
cached_tokens=12,
transforms_applied=["compress"],
tool_units_dropped=1,
turns_dropped=2,
messages_hash="messages",
error=None,
)
@dataclass
class DummyStorage(Storage):
closed: bool = False
def save(self, metrics: RequestMetrics) -> None:
return None
def get(self, request_id: str) -> RequestMetrics | None:
return None
def query(self, **kwargs) -> list[RequestMetrics]:
return []
def count(self, **kwargs) -> int:
return 0
def iter_all(self):
return iter(())
def get_summary_stats(self, **kwargs) -> dict[str, int]:
return {}
def close(self) -> None:
self.closed = True
def test_storage_base_context_manager_calls_close() -> None:
storage = DummyStorage()
with storage as managed:
assert managed is storage
assert storage.closed is False
assert storage.closed is True
assert Storage.save(storage, _metrics("x", datetime(2026, 4, 23, 12, 0, 0))) is None
assert Storage.get(storage, "x") is None
assert Storage.query(storage) is None
assert Storage.count(storage) is None
assert Storage.iter_all(storage) is None
assert Storage.get_summary_stats(storage) is None
assert Storage.close(storage) is None
def test_create_storage_builtin_entrypoint_and_fallback(monkeypatch, tmp_path: Path) -> None:
sqlite_storage = create_storage(f"sqlite://{tmp_path}\\metrics.db")
jsonl_storage = create_storage(f"jsonl://{tmp_path}\\metrics.jsonl")
assert isinstance(sqlite_storage, SQLiteStorage)
assert isinstance(jsonl_storage, JSONLStorage)
sqlite_storage.close()
jsonl_storage.close()
absolute_sqlite = create_storage("sqlite:///tmp/demo.db")
absolute_jsonl = create_storage("jsonl:///tmp/demo.jsonl")
assert isinstance(absolute_sqlite, SQLiteStorage)
assert isinstance(absolute_jsonl, JSONLStorage)
absolute_sqlite.close()
absolute_jsonl.close()
created = DummyStorage()
class FakeEntryPoint:
name = "custom"
def load(self):
return lambda store_url: created
monkeypatch.setattr(
"importlib.metadata.entry_points",
lambda group: [FakeEntryPoint()] if group == "headroom.storage_backend" else [],
)
assert create_storage("custom://memory") is created
monkeypatch.setattr(
"importlib.metadata.entry_points", lambda group: (_ for _ in ()).throw(RuntimeError("boom"))
)
created_fallback: list[str] = []
class FakeSQLiteStorage:
def __init__(self, db_path: str) -> None:
created_fallback.append(db_path)
def close(self) -> None:
return None
monkeypatch.setattr("headroom.storage.SQLiteStorage", FakeSQLiteStorage)
fallback = create_storage("custom://fallback.db")
assert isinstance(fallback, FakeSQLiteStorage)
assert created_fallback == ["custom://fallback.db"]
fallback.close()
monkeypatch.setattr(
"importlib.metadata.entry_points",
lambda group: [SimpleNamespace(name="other", load=lambda: lambda url: created)],
)
missing_ep = create_storage("custom://missing.db")
assert isinstance(missing_ep, FakeSQLiteStorage)
assert created_fallback == ["custom://fallback.db", "custom://missing.db"]
missing_ep.close()
plain = create_storage("metrics.db")
assert isinstance(plain, FakeSQLiteStorage)
assert created_fallback == ["custom://fallback.db", "custom://missing.db", "metrics.db"]
plain.close()
def test_jsonl_storage_round_trip_query_count_and_summary(tmp_path: Path) -> None:
storage = JSONLStorage(str(tmp_path / "metrics.jsonl"))
now = datetime(2026, 4, 23, 12, 0, 0)
first = _metrics("one", now - timedelta(hours=2), mode="audit", before=120, after=100)
second = _metrics(
"two", now - timedelta(hours=1), model="claude", mode="optimize", before=90, after=30
)
third = _metrics("three", now, mode="audit", before=60, after=50)
storage.save(first)
storage.save(second)
storage.save(third)
assert storage.get("two") == second
assert storage.get("missing") is None
results = storage.query(start_time=now - timedelta(hours=1, minutes=30), offset=1, limit=1)
assert [item.request_id for item in results] == ["three"]
assert storage.query(model="claude")[0].request_id == "two"
assert storage.query(mode="optimize")[0].request_id == "two"
assert storage.query(end_time=now - timedelta(hours=1, minutes=30))[0].request_id == "one"
assert storage.count(mode="audit") == 2
assert storage.count(end_time=now - timedelta(hours=1, minutes=30)) == 1
assert storage.count(start_time=now + timedelta(days=1)) == 0
summary = storage.get_summary_stats(start_time=now - timedelta(hours=3), end_time=now)
assert summary == {
"total_requests": 3,
"total_tokens_before": 270,
"total_tokens_after": 180,
"total_tokens_saved": 90,
"avg_tokens_saved": 30.0,
"avg_cache_alignment": 75.0,
"audit_count": 2,
"optimize_count": 1,
}
storage.close()
def test_jsonl_storage_handles_missing_file_malformed_lines_and_defaults(tmp_path: Path) -> None:
path = tmp_path / "events.jsonl"
storage = JSONLStorage(str(path))
path.unlink()
assert list(storage.iter_all()) == []
path.write_text(
"\n".join(
[
"",
"not-json",
'{"id":"x","timestamp":"2026-04-23T12:00:00Z","model":"gpt-4o","stream":true,"mode":"simulate","tokens_input_before":5,"tokens_input_after":3}',
]
)
)
loaded = list(storage.iter_all())
assert len(loaded) == 1
assert loaded[0].request_id == "x"
assert loaded[0].tokens_output is None
assert loaded[0].block_breakdown == {}
assert loaded[0].waste_signals == {}
assert loaded[0].stable_prefix_hash == ""
assert loaded[0].cache_alignment_score == 0.0
assert loaded[0].transforms_applied == []
assert loaded[0].tool_units_dropped == 0
assert loaded[0].turns_dropped == 0
assert loaded[0].messages_hash == ""
assert loaded[0].error is None
def test_sqlite_storage_round_trip_filters_summary_and_defaults(tmp_path: Path) -> None:
storage = SQLiteStorage(str(tmp_path / "metrics.db"))
now = datetime(2026, 4, 23, 12, 0, 0)
first = _metrics("one", now - timedelta(hours=2), mode="audit", before=100, after=70)
second = _metrics(
"two", now - timedelta(hours=1), model="claude", mode="optimize", before=90, after=20
)
third = _metrics("three", now, before=50, after=50)
third.stable_prefix_hash = ""
third.cache_alignment_score = 0.0
third.cached_tokens = None
third.transforms_applied = []
third.tool_units_dropped = 0
third.turns_dropped = 0
third.messages_hash = ""
storage.save(first)
storage.save(second)
storage.save(third)
replacement = _metrics("one", now + timedelta(minutes=1), before=111, after=11)
storage.save(replacement)
assert storage.get("one") == replacement
assert storage.get("missing") is None
results = storage.query(start_time=now - timedelta(hours=2), end_time=now, limit=2, offset=1)
assert [item.request_id for item in results] == ["two"]
assert storage.query(model="claude")[0].request_id == "two"
assert storage.query(mode="optimize")[0].request_id == "two"
assert storage.count(mode="audit") == 2
assert storage.count(start_time=now - timedelta(hours=1, minutes=30), end_time=now) == 2
assert storage.count(model="missing") == 0
assert [item.request_id for item in storage.iter_all()] == ["two", "three", "one"]
summary = storage.get_summary_stats(
start_time=now - timedelta(hours=3), end_time=now + timedelta(hours=1)
)
assert summary == {
"total_requests": 3,
"total_tokens_before": 251,
"total_tokens_after": 81,
"total_tokens_saved": 170,
"avg_tokens_saved": 56.666666666666664,
"avg_cache_alignment": 50.0,
"audit_count": 2,
"optimize_count": 1,
}
empty = storage.get_summary_stats(start_time=now + timedelta(days=1))
assert empty == {
"total_requests": 0,
"total_tokens_before": 0,
"total_tokens_after": 0,
"total_tokens_saved": 0,
"avg_tokens_saved": 0,
"avg_cache_alignment": 0,
"audit_count": 0,
"optimize_count": 0,
}
storage.close()
assert storage._conn is None
def test_sqlite_storage_get_conn_reuses_connection_and_create_storage_entrypoint(
monkeypatch, tmp_path: Path
) -> None:
storage = SQLiteStorage(str(tmp_path / "metrics.db"))
first = storage._get_conn()
second = storage._get_conn()
assert first is second
storage.close()
created = DummyStorage()
monkeypatch.setattr(
"importlib.metadata.entry_points",
lambda group: [SimpleNamespace(name="custom", load=lambda: lambda url: created)],
)
assert create_storage("custom://db") is created