Skip to content
← Free FDE training guides

Free learning / 40-minute observability lab

Your first trace: see what happened inside a request

Connect familiar Python functions to real spans, compare a missing guide with a failed lookup, and investigate a gap in the record.

No account needed. Use your own copy for writing and keep the original as a reference.

Engineering lab library / Run locally

Make the request explainable.

Generate actual OpenTelemetry spans around a small Python program. Follow the work, compare outcomes and see what goes missing when a call is not instrumented.

Synthetic records. No provider key or model inference. Package setup needs package-registry access.

  1. Start here / Real library, SDK or framework · Scripted inputs

    First request trace

    Generate real local spans and explain their relationships, outcomes and observation gaps.

    Python 3.11+ · Pinned OpenTelemetry SDK · No collector

An assistant returns “a person should review this.” Was the guide missing, did a lookup fail, or did the application choose the wrong route? The final answer cannot tell you by itself.

In this original 40-minute exercise, you will run a small Python program and inspect real OpenTelemetry spans. Start with familiar function calls, then connect their records and investigate a missing observation.

1. Know what you are looking at

Observability means being able to investigate a system through the evidence it emits. Instrumentation is the code that produces that evidence. A trace connects operations in one execution. A span records one operation, including its start, end and relationship to other operations.

If you have used a debugger, think of the question “what called what?” A trace retains selected evidence after execution. It is not a recording of every variable, and it cannot reveal work that was never instrumented.

Our program contains ordinary Python functions:

Text example
support.request — handle a request
  |
  +-- guide.lookup — look up a synthetic guide
  |
  +-- reply.format — return the guide
      OR
      handoff.choose — choose a fallback

The enclosing operation is the root. The operations inside it are children. The request and children share a trace ID. Each operation has its own span ID; a child's parent ID points to its enclosing operation.

OpenTelemetry is an instrumentation framework with APIs, SDKs and exporters. It is not a model or a hosted dashboard. This file uses its actual Python SDK with an in-memory exporter. There is no model inference, external service, collector connection or production telemetry.

Logs describe events, metrics summarize measurements, and traces connect operations. An evaluation asks whether behavior matches an expectation. You may need several of these to explain a real issue.

2. Prepare the local exercise

Download both files into one folder:

Use Python 3.11 or later. On macOS or Linux:

Code example
python3 -m venv .venv-trace
. .venv-trace/bin/activate
python -m pip install -r fde-first-trace-requirements.txt
python fde-first-trace.py test
python fde-first-trace.py compare

On Windows, use Command Prompt:

Code example
py -3 -m venv .venv-trace
.venv-trace\Scripts\activate.bat
python -m pip install -r fde-first-trace-requirements.txt
python fde-first-trace.py test
python fde-first-trace.py compare

Installation needs internet access. The exercise commands block socket connections and DNS lookup. They do not need a provider key or account. The pinned requirements include OpenTelemetry API and SDK 1.45.1 and their dependencies. Keep the package versions with your observations.

Seven checks exercise parent/child relationships, interval boundaries, missing content, a handled exception, an omitted span, isolation and invalid inputs. If the SDK is disabled and no spans are recorded, the exercise reports an incomplete run instead of claiming that an export succeeded.

3. Connect one request

Find the success run in the JSON from compare. It contains three spans: support.request, guide.lookup and reply.format. The application result is guide. This is synthetic text from a dictionary, not a generated answer.

Try these observations before looking at a dashboard:

  1. Find the span with parent_id: null. That is the root.
  2. Compare all three trace_id values. They should match.
  3. Compare the three span_id values. Each identifies a different operation.
  4. Check that each child's parent_id matches the root's span_id.
  5. Inspect start_ms and duration_ms, measured relative to the root start.

The SDK creates new IDs and timestamps each run. Your numbers should not match the browser recording exactly. The names and relationships are what you are checking.

Each span is opened around work and closed when its with block ends. The supplied program explicitly starts a new root context and uses a private provider; it does not replace the process-wide tracer provider.

4. Read elapsed time without counting it twice

The root starts before its children and ends after them. Its duration already includes their time. If a request lasts 50 ms and a lookup inside it lasts 30 ms, the request still lasts 50 ms, not 80 ms.

The exercise inserts deliberate sleeps: 30 ms in lookup, 15 ms in formatting, and 5 ms in fallback. The recorded durations come from actual SDK timing. Scheduling and instrumentation add overhead, so the values are not exact sleep requests. They are teaching measurements, not a database or model benchmark.

In a disposable copy, change only the lookup sleep from 0.030 to 0.060. Predict what should change, then run again:

Code example
python fde-first-trace.py run --case success

The lookup interval should grow, and the enclosing request should include the extra time. Small differences in other intervals can be local scheduling noise. Do not turn a single run into a performance claim.

These spans measure elapsed wall time, not CPU use. If operations run concurrently, their intervals can overlap; summing child durations may then exceed the enclosing request's duration.

5. Separate a missing guide from a failed lookup

Run the two cases:

Code example
python fde-first-trace.py run --case missing
python fde-first-trace.py run --case failure

Both return the application result handoff. The distinction is in the trace:

CaseLookup evidenceNext operation
Guide missingtraining.found: false; status UNSEThandoff.choose
Lookup failedstatus ERROR; event lookup.failed with fixed lookup_unavailable categoryhandoff.choose

The missing guide is an expected branch. The failed lookup raises an exception that the application catches. The parent remains UNSET because this example handles the failure and returns a fallback. Child error status does not automatically set parent status.

UNSET is the SDK default. It is not a score for answer quality, completeness of instrumentation or deployment readiness. Read the instrumentation and application contract together.

The result is only a handoff decision. No message is sent and no human acceptance is recorded. A receiving engineer should not infer those effects from an operation name.

6. Remove an observation without removing the work

Code example
python fde-first-trace.py run --case success --omit-lookup-span

The result is still guide, but only two spans appear: the root and formatting. Read the code: lookup_guide still executes. Only its surrounding span is omitted. One of the checks verifies that call directly.

The root still includes the time spent in the lookup. From the reduced trace alone, however, you cannot assign the unobserved interval to a specific function. An absent span is not proof that work did not run or took zero time.

In a real deployment, missing instrumentation, sampling and export loss can all leave gaps. This exercise isolates missing instrumentation. It does not simulate a remote collector failure or prove cross-process propagation.

7. Keep useful evidence without copying the conversation

Inspect the recorded attributes and events. An attribute describes an operation; an event marks a moment inside it. The exercise emits fixed names and a small set of bounded values. It excludes guide text, prompt content and raw exception messages. Automatic exception capture is explicitly disabled.

This is a scoped example, not a general-purpose redactor. When adding a field, state the diagnostic question it answers and how its value is bounded. Do not serialize a whole request or exception just because it is easy.

The local exporter retains spans in memory. No collector, remote storage, access policy or retention system is tested here. Across services, trace context must be propagated deliberately, while identity and permission checks remain separate. A trace ID never grants access.

8. Keep a small investigation note

Record:

  • The program and package versions, and which case you ran.
  • One trace ID with its root and child span IDs.
  • The enclosing duration, without adding child time again.
  • The field or event distinguishing a missing guide from a failed lookup.
  • What disappeared when instrumentation was removed, and what still ran.
  • The next bounded observation you would add to a real application.

Explain it to another engineer without starting with the raw JSON: “One request looked up a guide. That lookup failed, so the application chose a fallback. Here is the recorded error, and here is what we still do not know.”

Continue in the authenticated observability lesson. Then use the advanced agent-engineering lesson for event projection, evaluation and recovery boundaries.

Sources and scope

Original LockedIn Labs instruction and synthetic exercise. Primary references checked 20 October 2026:

Local SDK observations do not establish real model behavior, service latency, collector delivery, production readiness or a learner credential.

Before you move on

Keep the evidence of your work.

  • One trace with connected parent and child spans.
  • An explanation of timing, handled failure and missing instrumentation.
  • A bounded next observation without exporting private content.

Keep these in your own working copy. Reading this page does not save work or record completion.

Suggested next free session

Plan an NVIDIA AI deployment

Connect observed work to a hardware and serving decision. This is a suggested sequence; choose the practice that addresses your current gap.

Open the next free guide
Have Academy access?

Continue with worked explanations, practice and review in the related lesson.

Open the related Academy lesson →
Back to top ↑