Repository navigation
feat(daemon): capture the full Claude Code and Codex OTEL spec - #320
Conversation
Align the AICodeOtel receiver with the Claude Code monitoring doc and Codex codex-rs/otel so no attribute is silently dropped: - Optional scalars are pointers, so success=false and zero values reach the server (failed tool calls were always counted as 0). - Payload v2 fields: timestampMs, promptId, sequence, requestId, speed, querySource, response, responseLength, toolInput, entrypoint and an attributes catch-all for every unmapped attribute (capped). - Stable ot1: event and metric ids so exporter retries de-duplicate. - Event names: event.name, then LogRecord.EventName, then Body; generic claude_code./codex. prefix strip; raw API bodies and system_prompt are dropped. - Spec mappings: tool_use_id, tool_input/arguments, Codex output, cache_write_token_count, cost_usd_micros, effort, string mcp_servers, host.name and originator fallbacks; tool_token_count (total tokens) no longer lands in toolTokens. - Metrics: type routed per metric, tool_name accepted, fabricated codex.* names removed, cumulative temporality warning. - gRPC receive limit 32 MB; outgoing requests split at 8 MB. - cc install adds OTEL_LOG_TOOL_DETAILS, OTEL_LOG_ASSISTANT_RESPONSES, entrypoint/repository attributes and delta temporality; codex install merges into [otel] and enables log_agent_responses; doctor flags stale configs; installs print a privacy note. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EsMo3p9YUBzdsjFHxGWoCL
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
Codecov Report❌ Patch coverage is
Flags with carried forward coverage won't be shown. Click here to find out more.
... and 3 files with indirect coverage changes 🚀 New features to boost your workflow:
|
⏱️
|
| Scenario | base | head | Δ | p | |
|---|---|---|---|---|---|
Startup/floor |
487 µs ±1% | 488 µs ±2% | ~ | 0.971 | A/A |
Startup/version |
3.58 ms ±1% | 3.55 ms ±1% | ~ | 0.165 | ✅ |
Track/daemon/pre |
3.92 ms ±1% | 3.88 ms ±1% | -1.21% | 0.001 | ✅ |
Track/daemon/post |
3.88 ms ±1% | 3.85 ms ±1% | ~ | 0.075 | ✅ |
Track/direct/pre |
3.85 ms ±1% | 3.82 ms ±1% | -0.67% | 0.023 | ✅ |
Track/direct/post |
7.42 ms ±1% | 7.33 ms ±1% | -1.16% | 0.003 | ✅ |
Track/direct/post-sync |
9.04 ms ±2% | 8.99 ms ±1% | ~ | 0.052 | ✅ |
Binary size: 19.1 MiB → 19.1 MiB (+0.0%).
CPU, tail latency and memory
Per exec, base → head (Δ when significant).
| Scenario | p95 wall | user CPU | sys CPU | peak RSS |
|---|---|---|---|---|
Startup/floor |
548 µs → 544 µs | 276 µs → 278 µs | 159 µs → 161 µs | 12.2 MiB → 12.2 MiB |
Startup/version |
3.89 ms → 3.91 ms | 1.71 ms → 1.63 ms | 2.35 ms → 2.34 ms | 18.0 MiB → 18.1 MiB |
Track/daemon/pre |
4.28 ms → 4.20 ms (-2.03%) | 1.96 ms → 1.94 ms | 2.48 ms → 2.42 ms | 18.9 MiB → 19.0 MiB |
Track/daemon/post |
4.21 ms → 4.23 ms | 1.93 ms → 1.92 ms | 2.45 ms → 2.41 ms | 18.8 MiB → 18.8 MiB |
Track/direct/pre |
4.18 ms → 4.12 ms (-1.46%) | 1.84 ms → 1.89 ms | 2.47 ms → 2.41 ms | 18.7 MiB → 18.9 MiB (+0.97%) |
Track/direct/post |
8.11 ms → 7.98 ms (-1.57%) | 5.21 ms → 5.19 ms | 3.44 ms → 3.41 ms | 21.1 MiB → 21.1 MiB |
Track/direct/post-sync |
9.83 ms → 9.87 ms | 6.98 ms → 6.90 ms | 4.63 ms → 4.49 ms | 23.4 MiB → 23.4 MiB |
benchstat
goos: linux
goarch: amd64
pkg: github.com/malamtime/cli/perf
cpu: AMD EPYC 7763 64-Core Processor
│ base │ head │
│ sec/op │ sec/op vs base │
Startup/floor-4 487.2µ ± 1% 488.0µ ± 2% ~ (p=0.971 n=10)
Startup/version-4 3.577m ± 1% 3.549m ± 1% ~ (p=0.165 n=10)
Track/daemon/pre-4 3.923m ± 1% 3.875m ± 1% -1.21% (p=0.001 n=10)
Track/daemon/post-4 3.884m ± 1% 3.854m ± 1% ~ (p=0.075 n=10)
Track/direct/pre-4 3.848m ± 1% 3.822m ± 1% -0.67% (p=0.023 n=10)
Track/direct/post-4 7.415m ± 1% 7.330m ± 1% -1.16% (p=0.003 n=10)
Track/direct/post-sync-4 9.043m ± 2% 8.989m ± 1% ~ (p=0.052 n=10)
geomean 3.532m 3.506m -0.72%
│ base │ head │
│ p50-sec/op │ p50-sec/op vs base │
Startup/floor-4 478.8µ ± 1% 477.8µ ± 1% ~ (p=0.912 n=10)
Startup/version-4 3.542m ± 2% 3.507m ± 2% -1.00% (p=0.043 n=10)
Track/daemon/pre-4 3.910m ± 1% 3.860m ± 1% -1.29% (p=0.000 n=10)
Track/daemon/post-4 3.859m ± 2% 3.814m ± 1% ~ (p=0.063 n=10)
Track/direct/pre-4 3.840m ± 1% 3.825m ± 2% ~ (p=0.143 n=10)
Track/direct/post-4 7.368m ± 1% 7.287m ± 2% -1.10% (p=0.029 n=10)
Track/direct/post-sync-4 9.018m ± 1% 8.935m ± 1% -0.92% (p=0.001 n=10)
geomean 3.507m 3.477m -0.87%
│ base │ head │
│ p95-sec/op │ p95-sec/op vs base │
Startup/floor-4 548.5µ ± 3% 544.0µ ± 2% ~ (p=0.436 n=10)
Startup/version-4 3.893m ± 2% 3.911m ± 3% ~ (p=0.579 n=10)
Track/daemon/pre-4 4.282m ± 2% 4.196m ± 1% -2.03% (p=0.043 n=10)
Track/daemon/post-4 4.208m ± 2% 4.225m ± 3% ~ (p=0.971 n=10)
Track/direct/pre-4 4.184m ± 1% 4.123m ± 1% -1.46% (p=0.011 n=10)
Track/direct/post-4 8.107m ± 3% 7.980m ± 2% -1.57% (p=0.035 n=10)
Track/direct/post-sync-4 9.832m ± 2% 9.865m ± 2% ~ (p=0.579 n=10)
geomean 3.863m 3.837m -0.67%
│ base │ head │
│ peak-rss-B │ peak-rss-B vs base │
Startup/floor-4 12.23Mi ± 2% 12.22Mi ± 1% ~ (p=0.928 n=10)
Startup/version-4 17.97Mi ± 1% 18.06Mi ± 1% ~ (p=0.218 n=10)
Track/daemon/pre-4 18.94Mi ± 1% 18.99Mi ± 1% ~ (p=0.247 n=10)
Track/daemon/post-4 18.80Mi ± 1% 18.84Mi ± 1% ~ (p=0.529 n=10)
Track/direct/pre-4 18.72Mi ± 1% 18.90Mi ± 1% +0.97% (p=0.001 n=10)
Track/direct/post-4 21.11Mi ± 1% 21.13Mi ± 1% ~ (p=0.631 n=10)
Track/direct/post-sync-4 23.39Mi ± 1% 23.37Mi ± 0% ~ (p=0.529 n=10)
geomean 18.43Mi 18.48Mi +0.27%
│ base │ head │
│ sys-sec/op │ sys-sec/op vs base │
Startup/floor-4 159.1µ ± 8% 161.4µ ± 15% ~ (p=0.631 n=10)
Startup/version-4 2.354m ± 5% 2.342m ± 4% ~ (p=0.912 n=10)
Track/daemon/pre-4 2.476m ± 4% 2.416m ± 4% ~ (p=0.190 n=10)
Track/daemon/post-4 2.449m ± 5% 2.410m ± 8% ~ (p=0.739 n=10)
Track/direct/pre-4 2.469m ± 6% 2.414m ± 5% ~ (p=0.218 n=10)
Track/direct/post-4 3.443m ± 2% 3.407m ± 4% ~ (p=0.684 n=10)
Track/direct/post-sync-4 4.629m ± 5% 4.490m ± 5% ~ (p=0.247 n=10)
geomean 1.900m 1.874m -1.35%
│ base │ head │
│ user-sec/op │ user-sec/op vs base │
Startup/floor-4 275.6µ ± 6% 277.8µ ± 5% ~ (p=0.912 n=10)
Startup/version-4 1.708m ± 6% 1.633m ± 6% ~ (p=0.247 n=10)
Track/daemon/pre-4 1.962m ± 5% 1.939m ± 6% ~ (p=0.912 n=10)
Track/daemon/post-4 1.930m ± 7% 1.921m ± 7% ~ (p=0.529 n=10)
Track/direct/pre-4 1.844m ± 9% 1.895m ± 4% ~ (p=0.579 n=10)
Track/direct/post-4 5.209m ± 3% 5.186m ± 6% ~ (p=0.529 n=10)
Track/direct/post-sync-4 6.978m ± 3% 6.897m ± 5% ~ (p=0.353 n=10)
geomean 1.980m 1.968m -0.60%
Δ compares medians; ~ means no significant difference (Mann-Whitney U, p ≥ 0.05). A scenario is flagged when it is more than 10% and more than 250µs slower with p < 0.05. Startup/floor runs true, not shelltime: it is an A/A check of runner noise. Runner: linux/amd64, AMD EPYC 7763 64-Core Processor . go1.27.1, 10 rounds × 100 execs per scenario and binary.
Code reviewNo issues found. Checked for bugs and CLAUDE.md compliance. |
|
/claude review Generated by Claude Code |
|
@claude review |
|
Claude finished @AnnatarHe's task in 42s —— View job Review of #320: capture the full Claude Code and Codex OTEL specI read the diff for the processor, the request splitter, the Claude and Codex config services and the gRPC server. I did not re-run the tests. The PR reports Worth addressing
Minor
Looks good
|
Install now merges into the user's [otel] table, so Check() returning true for any [otel] table made a config with only `environment` (or an exporter pointing at another collector) look installed. Check() now requires the exporter to point at the ShellTime daemon. Also move a misplaced comment in extractResourceAttributes to the service.name case it describes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EsMo3p9YUBzdsjFHxGWoCL
|
Thanks for the review. Changes in 4ffd4b3:
Not changed, with reasons:
Generated by Claude Code |
Summary
This aligns the AICodeOtel receiver with its two sources of truth: the Claude Code monitoring doc and Codex
codex-rs/otel/src. It is part of a cross-repo change; the server, web and iOS PRs follow.Data that was lost or wrong before
success=falseand zero values never reached the server. The event struct used non-pointer fields withomitempty, so false and 0 were dropped and failed tool calls always counted as 0. Optional scalars are now pointers.timestampMsfield is sent;timestamp(seconds) is kept for older servers.ot1:hashes of the resource, scope and record, so a retry produces the same id.attributescatch-all (64 keys, 2 KB per value).promptId(prompt.id),sequence(event.sequence),requestId,speed,querySource,response/responseLength(assistant_response, Codexagent_response),toolInput(Claudetool_input, Codexarguments, raw),entrypoint(app.entrypoint/ Codexoriginator/service.name).tool_use_id→callIdoutput→toolOutputcache_write_token_count→cacheCreationTokenscost_usd_microsused as a fallback for costeffort/model_reasoning_effort→reasoningEffortmcp_serverssent as a comma-joined string is now parsedhost.nameused as the machine-name fallbacktool_token_count(which is reallytotal_tokens) no longer lands intoolTokensevent.name, thenLogRecord.EventName, then the body, with a generic prefix strip. The opt-in raw API bodies andsystem_promptare dropped.typeis routed per metric;active_timeuser/cli no longer lands intokenType.tool_nameis accepted oncode_edit_tool.decision.codex.*metric names are removed (Codex exports no such metrics).Install and config
shelltime cc installaddsOTEL_LOG_TOOL_DETAILS=1,OTEL_LOG_ASSISTANT_RESPONSES=1,OTEL_METRICS_INCLUDE_ENTRYPOINT=true,OTEL_METRICS_INCLUDE_REPOSITORY=trueandOTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE=delta.shelltime codex installmerges into[otel]instead of replacing the table. It keeps the user's other keys and addslog_agent_responses = true. Uninstall removes only the keys it manages.doctorwarns when a config is missing the new keys and offers the existing auto-fix.Compatibility
The payload changes are additive. Older servers ignore the new keys and already decode optional fields as pointers. The server PR stores the new fields.
Test plan
go vet ./...go test -timeout 3m ./...passes: commands, daemon, model, stloader.daemon/aicode_otel_processor_v2_test.go: table tests built from the spec's record shapes (15 Claude and 10 Codex cases), plus the drop list, name fallbacks, stable ids, metric routing, attribute caps and chunked sending."success":false, zero cost and duration,timestampMsandot1:ids; a 6 MB export is accepted.🤖 Generated with Claude Code
https://claude.ai/code/session_01EsMo3p9YUBzdsjFHxGWoCL
Generated by Claude Code