Lab 7 — Observability: see every step, token and cost
Start from: app/ at tag lab06-done, with the Lab 0 setup loaded
(see Working in app/).
Goal: turn a run into data. You capture one headless run as an event
stream, summarize it with
analyze_stream.py, and compare that with the
interactive views and the saved transcript.
1. Capture a headless run
New-Item -ItemType Directory -Force .runs | Out-Null
claude -p "Add a 'stats' CLI command that prints product count, total stock units and total inventory value in dollars. Add a test and run the tests. Do not commit." `
--permission-mode acceptEdits --output-format stream-json --verbose --include-hook-events `
> .runs\lab07.jsonl
mkdir -p .runs
claude -p "Add a 'stats' CLI command that prints product count, total stock units and total inventory value in dollars. Add a test and run the tests. Do not commit." \
--permission-mode acceptEdits --output-format stream-json --verbose --include-hook-events \
> .runs/lab07.jsonl
.runs/ is gitignored. acceptEdits auto-approves file edits; your
Lab 6 allow rule covers pytest.
2. Summarize it
python ..\lab07-observability\analyze_stream.py .runs\lab07.jsonl
Observe: tool calls by name, hook events (your Lab 2B hooks!), number
of turns, duration, input/output/cache tokens, the reported cost and any
permission denials. Then open the JSONL and find one tool_use and its
matching tool_result. The summary is just a fold over these events.
The cost is Claude Code’s list-price estimate, not your Azure bill. Use Azure Cost Management for actual Foundry spend.
3. Interactive views
Start claude -c (continue the run you just captured; headless runs are
sessions too), then try:
/cost
/context
/status
Press Ctrl+O to toggle the detailed transcript view showing tool inputs,
outputs and hook messages.
4. Transcripts on disk
Every session is a JSONL file under ~/.claude/projects/<encoded path>/:
Get-ChildItem "$HOME\.claude\projects" -Recurse -Filter *.jsonl |
Sort-Object LastWriteTime -Descending | Select-Object -First 3 FullName, Length
Treat these as sensitive: they contain your prompts, file contents and command output.
5. (Optional) OpenTelemetry
Claude Code can export metrics and events with OpenTelemetry. To see them on the console:
$env:CLAUDE_CODE_ENABLE_TELEMETRY = "1"
$env:OTEL_METRICS_EXPORTER = "console"
$env:OTEL_LOGS_EXPORTER = "console"
claude -p "How many products are in catalog.csv?"
In production, point OTEL_EXPORTER_OTLP_ENDPOINT at a collector (for
example Azure Monitor) instead. Remove the variables afterwards.
Record
Turns, tool calls by type, hook events, tokens, estimated cost and duration for the step 1 run. Keep this table; Lab 14 compares against it.
Checkpoint
Review and commit the stats command if tests pass (or git restore .):
git tag lab07-done