AnthropicClaude Certified Architect – Professional2026-104.6 Monitor system performance using logging and observability tools
Specify records that explain each call
Completed by the knowledge check
Learning objective
Define production log records with trace IDs, prompt and model versions, token usage, latency, stop reasons, tool outcomes, and errors.
Core idea
A production log schema is a queryable account of what actually ran. It must let an operator connect a reported answer to its configuration, model calls, tool executions, and final business outcome. An HTTP status and a conversation transcript cannot substitute for those joins.
See 3.4.2 for trace propagation and 3.4.5 for telemetry content controls. Here you turn those design choices into a record specification that application teams can implement and operators can validate. Distinguish fields copied from Anthropic responses from fields your application owns; a prompt revision invented by the application is not an API-returned version.
How it works
Declare the record grain
Use separate records for the workflow, each model operation, and each tool execution. Give them a shared application trace_id, their own operation identifier, and an explicit parent. These are proposed application schema fields. A single overwritten row per conversation loses the intermediate call that caused the failure.
Keep Anthropic’s request-id separately. It identifies an API request and is useful to Anthropic support; it does not replace the trace joining your retrieval and business services. The Python and TypeScript SDKs expose it as _request_id on top-level responses. Error response bodies also contain request_id. A connection failure might leave no provider response: record the identifier as unavailable rather than fabricating one. On Claude Platform on AWS, also preserve x-amzn-requestid for CloudTrail lookups alongside request-id for Anthropic support.
For direct Messages API integrations, adopt a field specification such as this:
| Field group | Values to preserve | Validation question |
|---|---|---|
| Identity | Application trace, operation, parent, workflow, and attempt IDs; provider request-id when available | Can an operator join this call to its workflow? |
| Configuration | Application release, rendered prompt revision or digest, tool schema revision, retrieval index revision, requested model, response model | Does the record describe the configuration used at execution time? |
| Usage | usage.input_tokens, usage.output_tokens, usage.cache_read_input_tokens, usage.cache_creation_input_tokens | Are cache reads and writes retained separately? |
| Timing | Application start and end timestamps, elapsed duration, explicitly defined first-text timing for streams | Is the duration a model operation or the whole user wait? |
| Termination | Response stop_reason, relevant stop_details, application validation status | Is generation termination distinct from task acceptance? |
| Tool execution | Requested tool name and tool_use.id, matching tool_result.tool_use_id, execution status, duration, backend outcome reference | Did the requested action actually complete? |
| Failure | HTTP status where available, error.type, sanitized diagnostic category, stream completion status | Does the failure path remain queryable without a successful response? |
Do not reconstruct the prompt revision from the deployment running when somebody investigates. A long-running job may have started before that deployment. Attach the actual revision when the request is assembled, including experiment assignment and tool or index revisions where they affect behavior.
Preserve meanings across successful and failed calls
usage.input_tokens excludes tokens read from or written to the prompt cache. Total input therefore equals input_tokens + cache_read_input_tokens + cache_creation_input_tokens. Store the components, rather than replacing them with a total that prevents later cache diagnosis. A missing usage object after a failed call means usage is unavailable to this logger; assigning zero would assert something you did not observe.
stop_reason: "tool_use" means Claude requested tool execution. It says nothing about whether a backend accepted the operation. Correlate the tool request and result using tool_use.id and tool_result.tool_use_id; preserve is_error when supplied with the tool result. Add the backend transaction or result reference in your own tool record so an investigator can distinguish a timeout from a confirmed external effect.
Likewise, stop_reason: "end_turn" indicates natural generation completion, not a correct answer. max_tokens identifies an output limit; refusal identifies a refusal and can have additional stop_details. Store the raw stop_reason value, including pause_turn and model_context_window_exceeded when returned, without collapsing it into a generic error flag. A truncated answer, an incorrect answer, and a rejected request need different operating queries.
Describe what the logger can observe
The official SDK retries eligible transient failures twice by default. A duration measured around one SDK call may therefore include several transport attempts and backoff. Label it as SDK-operation duration unless you also instrument those attempts. A field named attempt_count must come from observed instrumentation, not from guessing that every operation exhausted its configured retries.
Disabling retries solely to expose attempts adds a retry implementation you must own. Choose that only when the transport instrumentation requirement justifies it; in Python the setting is max_retries, and in TypeScript it is maxRetries. Preserve the existing bounded retry behavior when operation-level diagnosis is sufficient.
For streams, HTTP 200 does not prove completion: an error can arrive after headers. Write an explicit terminal record for successful completion, interruption, or failure. A logger that emits only on success makes outages look like traffic disappearing. Define which fields remain available in each terminal state and test those paths with controlled failures.
Key distinctions and trade-offs
A trace ID joins application work; a provider request ID identifies a provider request. A requested model records intent; response model records the returned model identifier. Neither should be described as an immutable snapshot unless that property is established by the selected model’s documentation.
A tool proposal records intent; its execution record and backend outcome establish what happened. Keeping these separate costs storage but prevents a plausible assistant sentence from becoming the audit record of a write.
Choose bounded categorical fields for ordinary dashboards, with trace-level details in the log store. Apply the content policy from 3.4.5 to error messages and tool results as well as prompts. A structured record can still expose confidential content if a supposedly harmless diagnostic field accepts arbitrary text.
Architecture / decision scenario
A financial-services assistant prepares payment investigations within a 12-second application target. Its team proposes full call and tool records for a sampled 10% of workflows to stay within a 50 GB monthly logging budget. The support owner requires every disputed payment investigation to be reconstructable within one working day. These figures are scenario constraints.
In a staged incident, the model returns tool_use after two seconds, the payment-status tool times out after eight seconds, and the workflow returns an incomplete result at twelve seconds. Sampling the entire workflow record leaves 90% of investigations without that distinction. A storage trial projects 35 GB per month for bounded metadata on every call and tool execution, plus 10 GB for sampled diagnostic content. The architect chooses unsampled metadata and samples only diagnostic content under the controls in 3.4.5, meeting both the budget and the reconstruction requirement.
The platform owner verifies the joins using the application trace, provider request ID, prompt revision, response model, four token components, elapsed durations, stop reason, tool correlation, timeout category, and unresolved backend outcome. The record supports an actionable diagnosis without claiming the payment failed merely because its status lookup timed out.
Common exam traps
- Using
request-idas the identifier for an entire multi-call workflow. - Treating
end_turnor HTTP 200 as proof of task correctness. - Recording tool proposals as completed business operations.
- Dropping cache fields or assigning zero to unavailable usage.
- Calling an SDK-operation duration a single transport attempt.
- Writing logs only when the successful-response handler runs.
What to remember
Specify the record grain, field ownership, and missing-value meanings before building dashboards. Preserve actual configuration, usage components, termination, and tool execution separately. A usable production record explains both the normal path and the call that never returned a complete response.
Knowledge check
A claims workflow makes four Messages API calls, two retrieval queries and three tool executions per claim. Investigators must pull every record for one disputed claim and, when needed, give Anthropic support the identifier of a failing call. Which identity design should the log records use?
request-id as the key on every record of the whole claimtrace_id on every record, plus each call’s request-idrequest-id alone, joined to the claim by time rangerequest-id identifies one API request; it cannot join retrieval, tools and later calls. An application trace ID on every record joins the workflow, while each call keeps its own request-id for support. Time-range joins mix concurrent claims, and one overwritten row loses the intermediate call that failed.A claims assistant’s streaming call fails with a connection error before any response arrives, so the logger never receives a usage object. The cost dashboard currently records such calls as zero tokens. How should the call record represent usage?
count_tokens estimate for the request, recorded as billed usageA payment assistant’s model-call record shows stop_reason: "tool_use" for a release_payment request. The workflow then returned an incomplete answer after the payment service timed out. An auditor asks whether the payment was released. Which record is the best basis for investigating the actual payment outcome?
stop_reason of tool_use for the requeststop_reason: "tool_use" records that Claude requested a tool, not that a backend acted, and neither an assistant sentence nor an HTTP 200 proves the write. Use the application’s tool execution record, correlated by tool_use.id , to look for a confirmed backend outcome. A timeout may leave that outcome unresolved; the record must preserve that uncertainty rather than declare the payment failed or completed.A payments assistant has a 50 GB monthly logging budget, and every disputed investigation must be reconstructable. Full call and tool records for a sampled 10% of workflows fit the budget. Bounded metadata for every call and tool execution would take 35 GB, and diagnostic content for a 10% sample another 10 GB. Which logging design meets both requirements?
References
- Anthropic, Claude API errors
- Anthropic, Create a Message
- Anthropic, Stop reasons and fallback
- Anthropic, Prompt caching