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.
Own initialization; verify the connected trace
An illustrative startup lifecycle and a separate request-level verification path.
Application startup
- Establish logging deliberately
Check handlers rather than assuming later basic configuration will apply.
- Configure one provider owner
Let integrations attach without competing to replace the global provider.
- Instrument actual dependencies
Cover the HTTP client, async driver and model library the route uses.
Synthetic request check
- HTTP request span
Use a harmless labelled request with known start and end.
- Dependency + model spans
Verify shared context, including the exception path.
- Correlated log
Find the trace from the request’s log, not from an unrelated dashboard count.
Logs arriving proves a logging path works. It does not prove request spans are emitted or connected.
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.
Sources
Technical references checked .


