All entries

    Logs Were Arriving. Our AI Request Traces Were Missing.

    Debug an apparently healthy AI monitoring setup by separating logs, metrics and traces, checking provider ownership and instrumenting the dependencies that actually run.

    An engineer follows a broken luminous signal path through a Japanese underground observatory
    GPT-generated Japanese-inspired pixel-art illustration. Conceptual artwork, not a screenshot, measured result or depiction of private product data.

    A dashboard can show activity while omitting the trace you need to explain a slow request. Our telemetry design record described exactly that trap: logs and metrics were arriving, but request and dependency spans were missing. The current application has a dedicated telemetry setup module, which is stronger evidence than the older plan alone. This article explains the diagnosis and the verification I would expect around it. It does not claim a new production benchmark or publish our exporter configuration. The general lesson is to test the observation pipeline as deliberately as the feature it observes.

    Logs, metrics and traces answer different questions

    A log records an event or message. A metric aggregates measurements over time. A trace connects work performed during a request through related spans. They can describe the same service while having different exporters, sampling rules and initialization paths. Seeing one does not prove that the others work.

    This distinction matters when a monitoring overview displays a request count. That count may come from a metric rather than a request-span table. A healthy-looking tile therefore cannot establish that you can follow an individual request through its dependencies. I would deliberately generate a known test request and find its span, not infer success from general dashboard activity.

    Provider ownership is an application decision

    Observability libraries often want to configure a global provider for convenience. An AI tracing SDK and a hosting-provider integration can each assume they are responsible for that setup. If one initializes during an early import and the other arrives later, the result may not match the order visible in the main application function.

    Our recorded diagnosis focused on that ownership conflict. The later source has a dedicated setup module with explicit initialization responsibilities. The transferable pattern is to decide which layer owns the SDK and let integrations attach appropriately. Adding more initialization calls until something appears is a fragile fix because the next import reordering can change the winner.

    Follow the libraries the request really uses

    An auto-instrumentation bundle has a supported-library list. An application may use a different database driver or HTTP client. In that case the request span can exist while the expensive database or model interaction remains invisible. “Automatic instrumentation enabled” is not a coverage inventory.

    I would trace one representative route through its actual driver and client choices. If the application uses async operations, check those integrations specifically. The useful verification is a connected span hierarchy for the request, the database or external tool call and the model operation. An unrelated set of spans with no shared request context is much harder to diagnose.

    Import order can affect more than tracing

    Moving telemetry earlier can solve provider ownership and accidentally interfere with ordinary logging initialization. If a handler already exists, a later basic logging configuration may not behave as expected. A fix that restores traces while hiding application logs has only moved the blind spot.

    For that reason I would review initialization as a small lifecycle: establish logging intentionally, configure the shared telemetry provider, load integrations and instrument the application instance at the appropriate time. The exact calls depend on the SDK versions. What matters is that one layer owns the sequence and tests the assumptions rather than scattering setup across feature modules.

    EXPLAINED / SYSTEM FLOW

    Own initialization; verify the connected trace

    An illustrative startup lifecycle and a separate request-level verification path.

    Application startup

    1. Establish logging deliberately

      Check handlers rather than assuming later basic configuration will apply.

    2. Configure one provider owner

      Let integrations attach without competing to replace the global provider.

    3. Instrument actual dependencies

      Cover the HTTP client, async driver and model library the route uses.

    Synthetic request check

    1. HTTP request span

      Use a harmless labelled request with known start and end.

    2. Dependency + model spans

      Verify shared context, including the exception path.

    3. Correlated log

      Find the trace from the request’s log, not from an unrelated dashboard count.

    THE KEY DISTINCTION

    Logs arriving proves a logging path works. It does not prove request spans are emitted or connected.

    Conceptual lifecycle, not SDK-specific setup instructions. Exact initialization calls depend on the installed integrations.

    A synthetic trace is enough to test the pipeline

    A controlled example can make one HTTP request, one harmless dependency call and a labelled model or fake-model operation. The check should establish that spans emit, share context and close even when an exception occurs. It does not need a real customer's account or a stored prompt.

    I would also verify that a log emitted inside the request carries useful correlation information. This lets someone move from an error message to its trace. Then inspect a deliberate failure. A monitoring setup that works only for successful requests is least useful at the moment it is needed most.

    Keep infrastructure and AI content policies separate

    A database dependency span may be useful for infrastructure diagnosis without belonging in a full prompt-analysis platform. Similarly, an AI trace can include metadata such as duration and usage without capturing every message. Multiple exporters should receive an intentional subset, not whatever a shared provider happens to emit.

    The OpenTelemetry GenAI guidance explicitly discusses optional content capture. Prompts, tool arguments and outputs may contain sensitive information. I would start from the metadata needed to answer an operational question, then justify any additional content collection. Sampling does not make unnecessary sensitive data harmless; it only reduces how much is collected.

    A slow answer needs a useful denominator

    Suppose an invented request spends a short time routing, a long time waiting for an external service and another interval producing a final answer. A single total duration cannot tell a frontend developer whether a loading animation, cancellation button or backend timeout is the appropriate response.

    A trace makes that decomposition inspectable, but a lab example is not a production latency claim. Compare similar tasks, record failed attempts and account for sampling. If the slowest requests are systematically dropped or grouped under a different operation name, an attractive percentile can describe the wrong population. The measurement contract deserves review alongside the dashboard.

    Monitor the monitor after changes

    A release can change an import path, replace an HTTP client or upgrade an SDK. Any of those can break instrumentation while the business feature keeps working. I would therefore keep a small emission test and a post-release check for representative request and dependency spans.

    The current source module demonstrates that setup was implemented; it does not establish that every deployed exporter currently receives the intended data. That requires runtime evidence. Clear separation between code inspection and live verification makes the write-up more useful than claiming that a monitoring problem has been permanently solved.

    Questions worth asking

    Should I send every span to every backend? Usually that needs a reason. Different tools serve different operational questions, and indiscriminate export increases cost, noise and exposure.

    Are more logs a substitute for tracing? They can help, but reconstructing a multi-step request from unrelated timestamps becomes difficult with concurrent work. Correlation and explicit parent-child relationships solve a different problem.

    What would convince me the fix works? A known request visible with its expected children, errors represented correctly and useful log correlation. The evidence should come from the actual runtime path, not just a green configuration screen.

    FURTHER READING

    Sources

    Technical references checked .

    END OF ENTRY / 12
    BEHIND THE JOURNAL

    Eeshan Singh

    I’m Eeshan Singh Pokharia, an AI Full Stack Developer and CoFounder of UltraFit360. I work across AI features, full-stack product development, and web and mobile experiences—from Figma and frontend interactions to the systems behind them.

    When a chat panel waits without useful feedback, I want to know whether the delay belongs to a model, a tool or the surrounding request. This connects a visible frontend problem to the team’s tracing diagnosis without exposing runtime settings or raw conversations.

    Meet the author