How to instrument an AI application to investigate failures, latency, and usage
Imagen generada con gpt-image-2.5-sunburst para InferamaSource ↗
01

1. Start with operational questions, not fields

Observability for an AI application means being able to reconstruct its behavior from related signals: which request arrived, which stages ran, what failed, and how long each part took. For an application that already calls a model through an API, instrumentation does not mean copying every input and response into a log. It means collecting enough context to answer operational questions consistently, within a clearly defined scope and data policy.

Before choosing a library or building a dashboard, write down the questions the team needs to answer during an incident. For example: Which application and prompt versions handled this request? Was the model called once, or were there retries? Which tool ran, and how long did it take? Was the delay in the application, network, model, or a tool? What usage did the API report? These questions shape the design; fields that do not help answer them should not be added out of habit.

It is useful to distinguish observability from content evaluation. This article focuses on a request’s technical and operational path: failures, latency, retries, and reported usage. It does not propose a method for determining whether an answer is true, choosing a provider, or designing a conversational flow. Keeping that boundary clear helps keep logs small and prevents a technical signal from being presented as proof of quality.

Diagnostic questions and minimum signals

Use this table to justify each field or dashboard. If a signal does not support a specific decision or investigation, consider leaving it out.

QuestionUseful signalsPossible decision
What happened to a specific request?Request ID, final status, stages, and timestampsInvestigate a specific request
Where is latency concentrated?Total duration and duration by stageInvestigate the slow stage
Was there a retry?Attempt number, reason, and outcome for each attemptFix retry limits, retry policy, or a dependency
What did the API report about usage?Usage fields available in the response, preserved as reported dataCompare observed usage without confusing it with billing
Was sensitive information exposed?Redaction or classification result, without retaining the sensitive valueAdjust filters and access controls
02

2. Map the request lifecycle and define correlation

A request that looks like a single call from the interface may involve several operations: input validation, prompt construction, a model call, response processing, and possibly a tool call. If retries occur, each attempt should remain visible as a distinct operation. Logs should let you link these events without relying on identifiers that the external API does not guarantee.

Generate your own identifier for the request when it enters your application, then propagate it through the components you control. Add child identifiers or stage numbers to distinguish model and tool calls. If the provider returns a request identifier, store it as an additional field for later queries or support, but do not use it as the only link: it may not be available for every error or execution path.

Also define the timing boundary for each measurement. Total duration starts when the application accepts the request and ends when it delivers a response or records the final failure. A model call’s duration starts when that call begins and ends when a response or error is received. A tool call has its own start and end times. Recording milliseconds without defining these boundaries produces figures that cannot be compared reliably.

Minimum request flow

Apply this outline to a simple request and expand it only when the application actually has additional stages.

  1. 01Create a request_id at the application’s entry point and record the start time.
  2. 02Validate and prepare the request; associate a prompt version without automatically storing its contents.
  3. 03Record each model call as a stage with its attempt number, requested model, relevant configuration, and timings.
  4. 04If a tool is called, record its name, schema version if available, duration, status, and normalized result.
  5. 05Record the final response or terminal error, the closing time, and total duration.
03

3. Define a minimum schema and record what the API actually returns

A minimum schema should separate data generated by your application from fields received from the provider. Application-owned fields commonly include the request identifier, stage, attempt number, status, timestamps, and code and prompt versions. The requested model, configuration, and any identifier returned by the provider can help reconstruct an execution, but their origins should be labelled.

Usage reported by an API is not universal. It can vary by endpoint, model, modality, version, or response type; it may also be absent from errors or partial responses. The documentation available for this guide does not specify a particular provider, so it cannot establish a universal list of fields. Instead, implement an adapter for each API and consult its current primary documentation to check field names, units, and conditions. Store the result as “API-reported usage,” including which fields were present, and do not silently fill missing values with zeros.

Also keep application-measured time separate from any duration reported by the provider. The former measures the path through your system; the latter, if available, follows the provider’s definition. Make units explicit—for example, milliseconds for durations—and define whether timestamps are stored in UTC. Consistent conventions make it possible to compare requests and detect changes without mixing clocks or different intervals.

Initial per-request and per-stage schema

Provider usage fields vary. Keep only those offered in the documented API response for the configuration in use.

GroupRecommended fieldsSource
CorrelationYour own request_id; stage_id or stage numberApplication
VersionsApplication version; prompt version; requested modelApplication and configuration
TimingStart, end, and total duration; duration by stage; unitApplication
StatusNormalized final outcome; error category; attemptApplication
ProviderRequest ID returned, if available; resolved model, if documentedAPI response
UsageUsage fields documented by the API for that operation; indicator of missing fieldsAPI response
ToolsName, relevant version, status, and durationApplication
04

4. Instrument structured events end to end

Structured logs are easier to filter and group than prose messages. Define stable names for events, statuses, and fields; avoid having every component use a different label for the same concept. You do not need a specific observability vendor to get started: you can emit JSON events from the application and send them to the platform the team already uses.

One useful pattern is to emit a start and end event for each stage, or a single end event containing start time, end time, and outcome when the stage is short and does not need real-time updates. For longer operations, the end event should retain its link to the original request. If you use distributed traces, propagate context across services and queues you control; verify that the identifier survives the transition from synchronous to asynchronous work.

The example below is schematic pseudocode, not a working integration with an API: response and error field names depend on the SDK and provider. In a real implementation, adapt usage and error extraction to current documentation, and make sure the exception handler does not automatically log bodies that may contain sensitive data.

Instrumentation sequence

Add telemetry where the application has the full context, and normalize each external response before emitting it to the logging system.

  1. 01Create the application-generated request identifier and associate the environment and application version.
  2. 02Open an event or span for each important operation; include the request ID and stage ID.
  3. 03Measure start, end, and duration using the same unit and a monotonic clock for intervals.
  4. 04Normalize statuses and error categories; keep the external code separate if it is available and permitted.
  5. 05Extract only usage fields documented for the specific operation; mark missing fields explicitly.
  6. 06Apply redaction before exporting events, then validate the result using synthetic data.
05

5. Minimize sensitive data before storing or exporting it

Observability does not require keeping full prompts, complete responses, or tool arguments for every request. This content may contain personal data, secrets, commercial information, or material that is unnecessary for operational questions. Start with metadata and derived signals: opaque identifiers, versions, lengths, error categories, statuses, and timings.

Decide for each field whether to exclude, redact, transform, or store it with restricted access and limited retention. To correlate with a business entity, a pseudonymous key or internal reference that only an authorized system can resolve may be sufficient. A hash does not guarantee anonymity if the original value is predictable or can be checked against a list; do not automatically treat it as a privacy solution.

Test redaction before enabling logging in production. Use synthetic examples covering typical cases and variations, such as an email address in an input, a token in a header, or confidential data in a tool response. Inspect both the event leaving the application and the event reaching the store: a rule applied only in the dashboard or after export leaves the data exposed in transit.

Minimization decisions by data type

Classification depends on the organization’s legal, contractual, and security context; this table is a design guide, not a legal determination.

DataInitial handlingReason
Application-generated request identifierKeep with controlled operational accessNeeded to correlate events
Prompt or application versionKeep as a stable labelEnables comparison between executions
Full input or output textExclude by default; if essential, restrict access and retentionMay contain sensitive information
Credentials and access tokensDo not log; block or redact at the boundaryExposure may enable unauthorized access
Customer identifierUse a pseudonymous reference if it is sufficient for diagnosisReduces direct exposure
Normalized error code and statusKeep without the raw response bodySupports diagnosis with lower risk

Test redaction before production

Add automated tests to the code that constructs or exports events.

  1. 01Prepare synthetic inputs and responses containing fictitious sensitive data.
  2. 02Run the instrumentation and capture the event immediately before export.
  3. 03Verify that prohibited fields are absent or redacted and do not appear in error messages.
  4. 04Repeat the test with exceptions, retries, and tool calls—not only with the final response.
  5. 05Review who can query the logs and set a retention period appropriate to the operational use.
06

6. Build dashboards and alerts for investigation, not for accumulating charts

A useful dashboard answers a question and makes clear what action might follow. Start with three views: request health, latency distribution, and reported usage. For health, show completed, failed, and unresolved requests by error category. For latency, show total duration and duration by stage, with percentiles as well as averages, because an average can conceal a long tail of slow requests. For usage, show only available fields and break them down by model, version, or request type when that helps reveal changes.

Alerts should represent a condition someone can investigate or fix. An error rate that exceeds the usual pattern over a defined interval may warrant an alert; an isolated failure can remain in the log without waking a team. Thresholds depend on volume and service expectations, so there is no need to set a universal value without data. Include the observation window, owner, and a link to the relevant query or response procedure.

Do not present a cost estimate based on reported usage as a billed amount. For an internal estimate, multiply the available units by the prices and rules that apply to the specific account and configuration, and label the result as an estimate. Actual amounts may depend on conditions that cannot be inferred from the response event alone; verify any reconciliation against the provider’s current official billing information and documentation.

Initial diagnostic dashboard

Add dimensions only when they help locate a cause without unnecessarily exposing personal information.

ViewMeasuresDiagnostic use
HealthTotal, completed, failed, and unresolved requests; error categoryDetect changes in failure rate
LatencyTotal and per-stage duration; median and percentilesLocate slow stages and long tails
RetriesAttempts per request, reason, and outcomeDetect hidden failures or excess calls
Reported usageValues present by API, model, and versionObserve changes in reported consumption
Telemetry qualityEvents without IDs, events without closure, expected fields missingDetect incomplete instrumentation
07

7. Investigate a failed request reproducibly

When a report arrives, first pin down the request ID and confirm that it matches the right environment and time period. Gather the events in order by time and stage. Before interpreting the result, verify that the trace is complete: is there a start and end event? Are tool spans missing? Does the log record a terminal error or just a failed attempt? An incomplete execution can look like a model failure when the evidence simply was not captured.

Next, reconstruct the versions and sequence: application code, prompt version, requested model and any observable resolved model, number of attempts, tools, and statuses. Compare total duration with the sum of the stages, accounting for local work, queues, and time that was not instrumented. If the sum does not match, record that as a telemetry gap, not as proof of a cause.

Finally, separate facts from hypotheses. A provider timeout may be recorded as the outcome of an attempt; on its own, it does not explain why the timeout happened. A slow tool may account for part of the measured time, but not necessarily the final behavior. Record what is known, what is missing, and what check could distinguish between hypotheses. This discipline helps prevent claims about causes that the log does not establish.

Investigation procedure

Follow the same order for each incident to maintain a verifiable account.

  1. 01Find the application-generated request_id and confirm the environment, date, and application version.
  2. 02Order events by start time and stage; check for gaps or missing end events.
  3. 03Reconstruct the prompt, model, configuration, attempts, and tools from recorded versions and identifiers.
  4. 04Compare total duration with stage durations and locate any unexplained time.
  5. 05Review statuses, error categories, and available usage fields, distinguishing a missing value from zero.
  6. 06Separate observed facts from hypotheses; perform an additional check before declaring a cause.
  7. 07Document any missing field or event and add a test to confirm that instrumentation covers that case.
08

8. Verify the instrumentation and expand in stages

Instrumentation also needs testing: an application may work while dropping IDs, omitting end events, or logging data that should have been redacted. Run controlled tests for success, error, timeout, retry, and tool calls. For each case, verify the complete sequence from the incoming event to the final outcome, along with permissions and redaction before export.

Start with a limited production path and check that queries answer real questions. Review how much volume the logs generate and whether the team can find a request without manually searching several systems. Adjust event selection and retention before expanding. The goal is not to maximize telemetry, but to maintain enough searchable evidence to operate the system.

Telemetry conventions and API usage fields can change. Version your internal schema and validate the adapters when the SDK, API, or configuration changes. If the provider changes a response, the normalization layer should be adaptable without making every dashboard and query depend on external field names. General observability practices can guide the organization of signals and traces; they do not replace primary technical documentation for a specific provider’s fields or billing.

Acceptance checklist

Do not consider instrumentation complete until you have checked events and privacy using controlled test cases.

CaseCheckExpected result
SuccessRequest and stages are correlatedThe request’s path can be reconstructed using one application-generated ID
API errorStatus, category, and closure are presentA failure is not confused with a missing event
RetryEach attempt is separate and orderedThe failed attempt remains visible after a later success
ToolName, duration, and status are recordedThe stage can be distinguished from the model call
Usage absentA field is not returned by the APIIt is marked as not reported, not as zero
Synthetic sensitive dataEvent is inspected before exportThe value does not appear in the exported log

Open questions

  • No specific provider or API is identified, so it is not possible to state which usage or error fields it returns, or when they may be missing.
  • The general guide does not establish prices, account conditions, or final charges. Any estimate requires checking current official documentation and billing information for the applicable provider and period.
  • Retention periods, access controls, and data handling must be determined in the context of each organization’s legal, contractual, and security requirements.
09

Keep exploring

09

Sources consulted

03

Corrections and transparency

If you spot incorrect or outdated information, send us a correction with the page and source we should review.

Submit a correction