Skip to main content
This lesson shows how to add events to OpenTelemetry spans. Events are timestamped annotations attached to a span to record notable occurrences (for example: “request sent”, “error occurred”, or any business-relevant event). Instrumenting spans with events improves the ability to correlate traces with logs, errors, metrics, and other telemetry. What you’ll learn:
  • How to configure a tracer with an OTLP exporter
  • How to add span attributes and events
  • How to inject trace context into outgoing HTTP requests
  • How to record events on a server span (Flask example)
Avoid recording sensitive data (such as full account numbers, passwords, or PII) in span attributes or events. When needed, prefer identifiers, truncated values, or hashes.

Tracer setup (OTLP HTTP exporter)

Below is a minimal tracer configuration that exports traces to an OTLP HTTP endpoint. Adjust endpoint, headers, and resource attributes to match your environment.
Run your application and ensure the exporter endpoint is reachable. The tracer configuration above uses a BatchSpanProcessor for efficient export. Expected local console output (example when running the client application — separate from the tracer export):

Payment client: add attributes, events, and inject context

This client example demonstrates:
  • creating a span for the payment flow,
  • adding attributes to make spans searchable,
  • adding timestamped events before and after an HTTP call,
  • injecting trace context into outgoing request headers so downstream services can correlate traces.
Run the client:
When you inspect this trace in a tracing UI (for example Jaeger, Tempo, or any OTLP-compatible backend), open the span for “Starting Payment”. You should see the two timestamped events:
  • “Sending request” (includes http.method and http.url)
  • “Request sent” (includes http.status_code and http.url)
These events appear in the span timeline and help you understand the sequence of actions around the outgoing request.

Server-side (Flask) example: record an error event on the server span

On the server side you want to annotate the server span with request metadata and record events for application-level conditions such as errors, retries, or business rule violations.
Run the Flask server, then execute the client. In the server span details you will see the “User has insufficient funds” event with the available_balance attribute. This makes it easier to correlate failures with the originating trace. Expected combined console output (client + server example):

Quick reference: span attributes vs events

Use attributes to add searchable, indexed metadata to a span. Use events to attach timestamped, ordered observations within the span.
UseAPIExample
Add a single attributespan.set_attribute(key, value)span.set_attribute("http.status_code", resp.status_code)
Add multiple attributesspan.set_attributes(dict)span.set_attributes({ "user": "john", "bank": "BOA" })
Add a timestamped eventspan.add_event(name, attributes=None)span.add_event("Sending request", {"http.url": url})
Note: In the table above any curly-brace examples are shown as code to avoid parsing as JS/MDX objects.

Best practices

  • Add events for meaningful, timestamped occurrences (request sent/received, error, retry).
  • Use attributes for metadata you want to filter or search on (user ID, status code, service name).
  • Inject trace context into outgoing HTTP requests so downstream services can join traces.
  • Avoid recording sensitive or excessive data in attributes/events. Use truncated values, hashes, or identifiers where needed.
When instrumenting production systems, prefer structured keys for attributes and events (for example error.type, http.method, http.status_code) to make querying and visualization easier in your tracing backend.

Summary

  • Use span.set_attribute / span.set_attributes to store searchable metadata on spans.
  • Use span.add_event(name, attributes=None) to record timestamped events inside a span (useful for “request sent/received”, errors, retries).
  • Inject context for outgoing HTTP calls so downstream services can correlate traces.
  • Avoid storing sensitive or excessive data in span attributes and events.

Watch Video