feat(logs): surface and filter the routed account label per request - #4134
Conversation
The proxy has stamped a stable non-PII account label on every request row and every attempt for a long time (main, p<hex6> for Codex pool accounts, o<hex6> for other OAuth providers), but nothing could read it back. An operator running several accounts behind one provider had to grep usage.jsonl to answer "which account served this request", which is the first diagnostic question for a quota or cache anomaly. /api/logs now accepts ?account=<label>, matching failover attempts the same way ?provider and ?model already do, so a request is findable by the account that finally served it as well as the one that first refused it. ocx logs gains the matching --account flag and prints acct=<label> in human output, so a filtered result can be told apart from an empty one. No new field is persisted and no new identifier is derived: this reads back the label already written by sealRequestAttemptIdentity. Closes #4057
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Advanced Run ID: 📒 Files selected for processing (2)
Included review availability: Your plan provides up to 10 included reviews per hour; 0 remain after this review. 📝 WalkthroughWalkthroughThe change adds account-aware request-log filtering. The CLI accepts ChangesAccount-aware request logs
Priority: ➖ Normal Estimated code review effort: 3 (Moderate) | ~20 minutes Severity of issue fixed: Medium Merge Risk: ⚪ Minimal · up to Request logs can now be filtered by account label across failover attempts, and labeled rows display the selected account identity in CLI output. The API, CLI, and documented behavior are aligned with focused coverage, with no current merge-blocking risk identified. Sequence Diagram(s)sequenceDiagram
participant Operator
participant ObserveLogs
participant LogsAPI
participant filterRequestLogs
Operator->>ObserveLogs: run ocx logs --account label
ObserveLogs->>LogsAPI: request /api/logs?account=label
LogsAPI->>filterRequestLogs: apply account filter
filterRequestLogs-->>LogsAPI: return matching rows and attempts
LogsAPI-->>ObserveLogs: return log rows
ObserveLogs-->>Operator: print acct=label for labeled rows
🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
Full details: Linked Issues checkExplanation The changes satisfy the CLI and existing-label API portions of issue [ Resolution Either implement the remaining [ Full details: Docstring CoverageExplanation Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 4 functions across 6 files. (1 skipped: 1 unsupported.)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
✅ Deterministic PR hygiene checks passed. |
…he rendered page `skills/ocx/references/01_management_surface.md` is generated from `CAPABILITIES` in `src/cli/capabilities.ts`, and `tests/ci-workflows/skill-ocx.test.ts` compares the committed file against a fresh render byte for byte. The previous commit edited the rendered page by hand, so the two disagreed. Declare the flag at its source instead: the logs capability now carries `--account` between `--conversation` and `--status`, its summary names the new filter, and a detail line documents the `acct=<label>` column next to the existing `conv=<id>` one. The rendered page is unchanged from the previous commit apart from that detail line, which is what the registry now emits.
리뷰 · 우선순위 58 / 80이 PR은 이슈 #4057의 “요청 로그에서 어느 계정이 응답했는지”를 읽기 쉽게 만드는 작업이다. 현재 이 변경은 그 구멍을 메운다. 현재 로그 필터 엔진(#2704 model 절, 이후 #3508/#3712 계열 개선이 이미 HEAD에 있음) 위에 같은 패턴으로 한 절만 더하는 형태라 충돌·회귀 위험이 낮다. 테스트도 라인 - 경로/심볼 - 경로/심볼 - GUI Account 열 / 메인테이너의 판단이 필요한 지점
너의 추천 이 댓글은 grok-bot이 작성했습니다 |
Summary
Every request row and every attempt in this proxy already carries a stable, non-PII account label —
mainandp<hex6>for Codex pool accounts,o<hex6>for other OAuth providers — written bysealRequestAttemptIdentity. Nothing could read it back. An operator running several accounts behind one provider had to grepusage.jsonlby hand to answer "which account served this request", which is the first diagnostic question for a quota anomaly or a cache miss.GET /api/logsaccepts?account=<label>. Like the existing?providerand?modelclauses, it matches failover attempts, so a request is findable by the account that finally served it as well as by the account that first refused it (src/server/request-log.ts).ocx logs --account <label>passes the filter through, and human output now printsacct=<label>next toconv=<id>for the same reasonconv=exists: without it, an empty result and a wrong-label result look identical (src/cli/observe.ts).ocxskill pages document the flag, theaccountLogLabelJSONL field, and a per-request recipe next to the existing per-account spend recipe.No new field is persisted, no new identifier is derived, and no raw key, email, or upstream account id is written anywhere.
requestLogDtoneeded no change: it spreads the entry (src/server/management/shared.ts:155-177) and the label is already set on the in-memory row (src/server/request-log.ts:1048) and preserved through hydration (:292,:324). Because that only holds by way of a spread — while the sibling projectionrequestLogEntryFromPersistedUsagerebuilds field by field and warns in its own comment that a field missing there never reachesusage.jsonl— the served contract is now pinned by a test rather than left implicit.Deliberately not in this PR
The dashboard Logs column. The issue also asks for an Account column in the GUI Logs table. Any changed path under
gui/armsmissing_ui_screenshot(.github/scripts/pr-quality.cjs:526-532), whichenforce-targetturns into a failed check and an auto-draft (.github/workflows/enforce-pr-target.yml:1251). This change was produced under an instruction not to run any local build, so no honest screenshot of the rendered change could be attached. The GUI half is a separate change: it needs an 11th column in atable-layout: fixedtable, bothcolSpan={10}spacers bumped, andlogs.col.accountadded toen.tsplus all eight other locale catalogs.Key-pool
k<hex6>labels. A stable non-secret id for a pool key already exists (_apiKeyAttempt.entryId,src/providers/api-key-selection-capture.ts:4-9), but stamping it is not a small addition:ACCOUNT_LOG_LABEL_RE(src/codex/account-label.ts:24) and the persistence predicates insrc/usage/log.tswould have to accept a fourth label family, and the stamp would need six new sites insrc/server/responses/core.ts— the initial seal at 4354-4385 plus four key-rotation arms (6254, 7230, 7299, 7711) that do not restamp identity today — and two inchat-native.ts. It also widens what is derived from a secret:entryIdhashes the configured key string itself, unlikeoauthAccountLogLabel, which hashes a provider account id. That deserves its own review rather than a tail hunk on this one.Closes #4057
Verification
Local checks were NOT RUN, per maintainer instruction for this change: no local test suite, typecheck, build, lint, or
bun installwas executed. The exact-head remote CI on this PR is the gate.Regression coverage added with the change:
tests/usage/request-log.test.ts—filterRequestLogsby account: exact row match, match through a failover attempt, a non-matching label returning[](the assertion an unfiltered implementation cannot pass), an unlabelled row never swept in, and the filter combined withprovider.tests/server/management-api-logs-metrics.test.ts— through the real/api/logshandler: the DTO servesaccountLogLabelon the row and on each attempt, and?account=selects the same rows end to end.tests/cli/cli-observe-logs.test.ts(new) —--accountreaches the query string alongside the other filters, is omitted entirely when not requested, and human output printsacct=<label>for a labelled row and nothing for an unlabelled one.src/cli/capabilities.tsdeclares the flag andskills/ocx/references/01_management_surface.mdis its rendered output;tests/ci-workflows/skill-ocx.test.ts:62byte-compares the two. The first push edited the rendered page alone and that check failed, which is exactly what it exists to catch; the flag is now declared at its source.The new test file is registered in both
scripts/test-layout/layout.jsonandtests/fixtures/test-layout-expected.json, astests/test-layout-tooling.test.tsrequires.Checklist
The filter reads back a label the proxy already persists; it derives nothing new and logs no account identifier.
--accounttakes a label, never a key, and the CLI prints only the same digest already present inusage.jsonl.Summary by CodeRabbit
New Features
--account <label>filter toocx logsfor viewing logs associated with a specific account.acct=<label>in human-readable output and asaccountLogLabelin JSONL results.Documentation
Tests