What Are Span Events in OpenTelemetry?
A friendly, ground-up guide to the small, timestamped notes you can pin onto a span: what they are, how they differ from attributes and child spans, how they travel, and how to use them without drowning in data.
Imagine you are watching a long road race. The whole race is one big activity, and it takes two hours. But the interesting moments are not the full two hours. They are the small things that happen inside it: the runner takes a drink at 20 minutes, stumbles at 47 minutes, changes shoes at 1 hour and 10 minutes, and crosses the finish line. A good race report notes each of these moments with the exact time they happened.
A span in OpenTelemetry is like the race: one timed piece of work, such as “process payment.” A span event is like one of those noted moments. It is a small, timestamped note that says, “At this exact moment, something happened inside this span.” In this guide, we will learn what span events are, what they contain, and how to use them wisely, using simple words and everyday examples.
1The Problem: What Happened Inside the Span?
Before learning the tool, let us feel the problem it solves.
A span tells you how long, but not what happened
Suppose your payment service has a span called “Charge card” that took six seconds. That is slow, and you can see it clearly in a trace. But why was it slow? Maybe the first attempt failed and the code waited and retried. Maybe a cache lookup missed and a slower database call was needed. Maybe an exception was caught and handled in the middle. The span’s start and end time show the total, but they hide the story inside.
You could solve this by creating many tiny child spans for every little step. But that quickly becomes heavy and noisy. Many of these small happenings are not “work that takes time.” They are simply moments: “retry started,” “cache missed,” “payment approved.” For moments like these, we need something lighter than a span.
What we really need
We need a way to say, “Pin a small note on this span at this exact time.” The note should have a name, and it may carry a few details. It should cost very little. And it should stay attached to the span, so that anyone who views the trace sees the note in the right place on the timeline. This is exactly what a span event is.
Think of a flight recorder, often called a black box, in an aeroplane. It records the flight as a whole, but it also stamps specific moments: “landing gear down,” “altitude warning,” “engine restarted.” Investigators can later look at the timeline and see exactly when each thing happened. Span events are the stamped moments on your software’s timeline.
2So, What Is a Span Event?
The short answer first, and then the pieces.
A span event is a timestamped message attached to a span. It records that something meaningful happened at one specific moment during the span’s life. Unlike a span, an event has no start and end. It has just one time. It is a dot on the timeline, not a bar.
The three parts of an event
Name
A short label that says what happened, such as “cache.miss” or “retry.started”. Keep it general so that the same name can be reused many times.
Timestamp
The exact moment it happened. By default, the SDK stamps the current time for you. You can also provide your own time if you are recording something that happened a little earlier.
Attributes
Small key and value details about this moment, such as the retry number, the cache name, or the reason for the failure.
flowchart LR
A["Span starts: Charge card"] --> B["Event: cache.miss"]
B --> C["Event: retry.started"]
C --> D["Event: exception"]
D --> E["Event: payment.approved"]
E --> F["Span ends"]
In the diagram, the span runs from left to right. Along the way, four different moments were noted. If a viewer opens this trace in a tracing tool, the events usually show up as small marks on the span’s bar, and clicking one shows its name, time and attributes.
Think of a video and a photograph. A span is like a video clip because it has a beginning, an end and a length. An event is like a photograph taken during the clip. It captures one instant. Many photographs can be taken during one video.
3A Little History: Where Events Came From
Knowing the origin explains the name and some of the habits.
Before OpenTelemetry, older tracing systems already had a way to attach time-stamped notes to a span. In Zipkin, they were called annotations. In OpenTracing, they were called logs, meaning small structured messages stored inside a span. When OpenTelemetry was formed from OpenTracing and OpenCensus, the community kept the idea but chose the name events. One reason was to avoid confusing these in-span notes with the separate, independent log records that the logging signal handles.
Some tracing tools still show span events under the old word “logs.” If you ever look at a trace viewer and see a “logs” section on a span, it may be showing span events.
The OpenTelemetry community has been discussing a gradual move toward sending events through the logging signal, tied to the active trace. This area has been changing, so before building long-term plans, check the current status in the official documentation for your language.
4Core Concepts: Event, Attribute, Child Span, Log or Metric?
The biggest beginner question is “which tool should I use for this?” Let us answer it clearly.
| Tool | Best For | Has Its Own Time? | Everyday Picture |
|---|---|---|---|
| Span attribute | A fact about the whole span, such as the HTTP method or the customer tier | No, it describes the whole span | A label on a folder |
| Span event | A notable moment inside one span | Yes, one timestamp | A sticker at one point on a timeline |
| Child span | A step that takes time and may have its own details and failures | Yes, start and end | A chapter in a book |
| Span link | A connection to another related trace or span | No | A cross-reference |
| Log record | A free-standing message that may or may not belong to a span | Yes, one timestamp | A page in a diary |
| Metric | A number summarised over many requests | Collected over time | A dashboard gauge |
flowchart TD
Q["Something worth recording"] --> A{"Does it describe the whole span?"}
A -->|Yes| ATT["Use a span attribute"]
A -->|No| B{"Does it take meaningful time?"}
B -->|Yes| CS["Use a child span"]
B -->|No| C{"Is it a notable moment inside this span?"}
C -->|Yes| EV["Use a span event"]
C -->|No| D{"Is it a count or total across many requests?"}
D -->|Yes| MET["Use a metric"]
D -->|No| LOG["Use a log record"]
How to remember it
Ask three questions. First, “Is this true for the whole span?” If yes, use an attribute. Second, “Does this take real time and deserve its own bar?” If yes, use a child span. Third, “Is this a moment worth marking?” If yes, use an event. This small habit prevents most mistakes.
Production Example: Retry Handling
A payment client retries a call up to three times. The final number of attempts is a fact about the whole span, so it is an attribute. Each time a retry begins, the code adds an event with the attempt number, so engineers see exactly when each retry happened. If each attempt makes a network call that deserves its own timing, each attempt can also be a child span.
5Internal Working: Where an Event Lives
An important idea: an event is not a separate piece of data. It lives inside its span.
When your code adds an event, the SDK does not send it away right then. Instead, it stores the event inside the span’s own memory, in a list. Only when the span ends is the whole span, including all its events, passed to the processors and exporters. Then the span and its events are sent together to the backend.
sequenceDiagram
participant App as Application Code
participant Span as Active Span in SDK
participant Proc as Span Processor
participant Exp as Exporter
participant Back as Tracing Backend
App->>Span: Add event cache.miss
Span->>Span: Store event in span memory
App->>Span: Add event retry.started
Span->>Span: Store event in span memory
App->>Span: End span
Span->>Proc: Hand over finished span with events
Proc->>Exp: Batch of spans
Exp->>Back: Send spans and events together
Four things this design means for you
Events Use Memory Until the Span Ends
A span that stays open for a long time and collects thousands of events will use more and more memory. This is why SDKs have limits.
Events Share the Span’s Fate
If the trace is not sampled, the span is not recorded, and its events are not kept either. Events do not survive on their own.
Events Cannot Be Added After the Span Ends
Once a span has ended, it is read-only. Adding an event at that point is ignored. Always add events while the span is still open.
If the Program Crashes, Events May Be Lost
Because spans are exported when they end, a span that never ends because of a crash may never be sent, along with its events.
Non-recording spans ignore events
When a span is not recording, for instance because the trace was sampled out or because no SDK is installed, calls to add events do nothing. This is a feature. It means your code can add events freely, and you pay almost no cost when the data would not be kept anyway. For very expensive event details, many APIs let you check whether the span is recording before you prepare them.
Think of a student writing notes on a worksheet during an exam. The notes are on the same paper as the answers. When the paper is handed in, the notes go with it. If the teacher never receives the paper, the notes are gone too. Events travel on the span’s paper.
Limits and what happens when you exceed them
Most SDKs protect your memory with limits. There is usually a maximum number of events per span, a maximum number of attributes per event, and sometimes a maximum length for attribute values. A common default for the number of events is 128, but defaults can differ, so check your SDK. When the limit is reached, extra events are dropped, and the span records how many were dropped. A trace viewer or an exporter may then show a “dropped events” count, which is a sign you are adding too many.
6The Most Famous Event: Recording Exceptions
When something goes wrong, the standard way to note it on a span is with an exception event.
OpenTelemetry has a special, standard event for errors. Most APIs offer a helper called something like “record exception.” When you call it, the SDK adds an event with the well-known name exception. It carries standard attributes that describe what went wrong.
| Attribute | What It Holds | Why It Helps |
|---|---|---|
exception.type | The kind of error, such as a timeout error class | Lets you group and count errors by type |
exception.message | The text message of the error | Gives a human-readable reason |
exception.stacktrace | The path through the code where the error occurred | Helps developers find the exact line |
Recording an exception is not the same as marking the span as failed
This is one of the most common beginner surprises. Adding an exception event does not automatically change the span’s status to error. They are two separate steps. The event says “an exception happened at this moment.” The status says “the overall operation failed.” A span can contain an exception that was caught and handled, such as a failed first attempt followed by a successful retry, and still end as a success.
flowchart TD
S["Span starts"] --> W["Work is done"]
W --> X{"Did an error occur?"}
X -->|No| OK["Leave status as unset or ok"]
X -->|Yes| H{"Was the error handled and the operation still succeeded?"}
H -->|Yes| EV["Record exception event only"]
H -->|No| ST["Record exception event and set status to error"]
OK --> END["End the span"]
EV --> END
ST --> END
If you record an exception but forget to set the error status, your error-rate dashboards may show no failures, even though the traces contain exceptions. Decide clearly: is this a failure of the whole span, or just a bump along the way?
Production Example: The Hidden Retry
A booking service calls an airline system. The first call times out, so the code retries and succeeds. The span ends with a normal status, so no alarms ring. But the exception event is still attached, and an engineer reviewing slow bookings sees that many spans contain a timeout event on the first attempt. This quietly reveals a weak spot in the partner’s system that no error dashboard would have shown.
A warning about duplicate recording
If every layer of your code catches an exception, records it on the span, and throws it again, the same error may appear many times on the same span or on several parent spans. Pick one clear place to record it, usually where it is finally handled, so each failure is recorded once.
7Other Good Uses for Span Events
Exceptions are only the beginning. Here are the kinds of moments that deserve an event.
Retries and Fallbacks
“Retry started” with the attempt number, or “fallback used” when a backup path is taken.
Cache Hits and Misses
A small event marks whether the answer came from fast memory or needed a slow lookup.
State Changes
Moments like “order validated” or “payment authorised”, where the work moves from one stage to the next.
Queue Milestones
“Message received” or “waiting for lock ended”, showing where the time went inside a long span.
Circuit Breaker Changes
“Circuit opened” or “rate limit hit”, important moments that explain sudden behaviour.
Feature Flag Decisions
An event noting which flag was checked and which variant was chosen, so you can explain different behaviour between requests.
Page Milestones
Web instrumentation can mark moments of a page load, such as when parts of the page become ready, as events on a single span.
First Byte and Last Byte
For long responses, an event for “first chunk sent” gives a useful picture without needing many small spans.
Think of a cooking show. The whole recipe is the span. Inside it, the host says, “The oil is now hot,” “I have added the onions,” “The sauce is boiling.” None of these takes a long time on its own, but each marks a turning point that helps you follow the story. Those are events.
8Naming Events Well
A good name makes events searchable. A bad name makes them useless.
An event’s name is a label, like a category. It should describe the kind of thing that happened, not the specific details. Details belong in attributes. If you build the name from changing values, such as an order number, every event gets a unique name, and you can no longer group or count them.
Good Names
- cache.miss
- retry.started
- order.validated
- circuit_breaker.opened
- exception (the standard name)
Poor Names
- cache miss for user 4821
- retry number 3 at 7:02 pm
- order 99120 validated by Priya
- Something went wrong!!!
- event1
Practical naming habits
- Use lowercase words joined by dots or underscores, and use the same style across your whole company.
- Group related events with a shared first word, such as “cache” or “retry”.
- Put changing values, like attempt numbers and cache names, into attributes.
- Reuse the standard names from OpenTelemetry’s conventions when one exists, such as the exception event. Tools know how to display them.
- Keep a short shared list of the events your teams use, so that everyone speaks the same language.
9Data Flow and Lifecycle of an Event
Follow one event from the moment it is created to the moment you read it.
Something Notable Happens
Your code reaches a meaningful moment, such as a cache miss.
The Code Adds an Event
It calls the span’s add-event function with a name, and optionally attributes and a custom time. By default, the current time is used.
The SDK Checks Limits
If the span is recording and the limits allow, the event is stored. If not, it is dropped and counted.
The Span Ends
The span is finished and becomes read-only, with its events locked in.
Processors and Exporters Move It
The span, with its events inside, travels through the batch processor and the exporter, using the standard OpenTelemetry protocol.
The Collector May Reshape It
If a Collector is used, its processors can filter, mask or change events and their attributes before storage.
The Backend Shows It
A tracing tool draws the event as a mark on the span’s timeline, with its details visible on click.
Timestamps and a small tip
Most of the time, you let the SDK stamp the current time. Sometimes you may want to record an event that happened a little earlier, for example when processing a log of earlier activity. You can supply your own time, but keep it inside the span’s own start and end window. Events that fall outside the span’s lifetime can confuse viewers and make timelines look broken.
10Span Events versus Logs
These two are close cousins, and many people mix them up.
| Question | Span Event | Log Record |
|---|---|---|
| Where does it live? | Inside a span | As its own independent record |
| Does it need a trace? | Yes, always attached to a span | No, but it can carry trace and span IDs |
| Is it kept if the trace is dropped? | No, it goes with the span | Yes, logs can be kept regardless of trace sampling |
| Does it have a severity level? | No | Yes, such as info, warning or error |
| Best for | Marking moments within a traced operation | Recording any message, with or without a trace |
| Where do people see it? | On the span timeline in a trace viewer | In a log search tool |
A span event is a sticky note stuck to one page of a travel diary. A log record is a separate loose page that may mention the trip but can also exist on its own. If the page of the diary is torn out, the sticky note goes with it. The loose page remains in the folder.
A useful rule of thumb: if the information only makes sense inside a traced operation and you want to see it on the timeline, an event is a good fit. If it must be kept even when traces are sampled out, or if it needs a severity level and long-term search, a log record is a better fit. Many teams use both, with logs carrying trace and span IDs so that the two can be connected.
11Advantages, Disadvantages and Trade-offs
Every tool has strengths and limits. Let us see them honestly.
Advantages
- Light: far cheaper than creating a child span for every moment
- In context: shown exactly where it happened on the span timeline
- Standard: works the same across languages and tools
- Rich: can carry attributes with details
- Safe when unused: ignored cheaply when a span is not recording
- Great for errors: the exception event is understood by most tools
Disadvantages
- Tied to the span: lost if the trace is sampled out or never ends
- Memory held: events stay in memory until the span ends
- Hard to aggregate: not designed for counting across many requests
- Limits apply: too many events get dropped
- Evolving area: the community is rethinking how events fit with logs
- Uneven display: tools show events differently, and some hide them
Key trade-offs
| Decision | Option A | Option B |
|---|---|---|
| Event or child span? | Event, which is lighter and simpler for quick moments | Child span, which gives timing and its own status for real work |
| Event or log? | Event, for moments tied to a trace and visible on the timeline | Log, for messages that must survive sampling and need severity |
| How many events? | Few, key moments only, which is cheaper and clearer | Many, which gives detail but increases memory, cost and noise |
| Exception events | Record every handled exception for full visibility | Record only final failures to keep traces clean |
12Security and Privacy Considerations
Events often carry error messages, and error messages often carry surprises.
Exception Messages Can Leak Data
An error message may include a database query with real values, a file path, an email address or even a password from a bad configuration. Check what your errors contain.
Reveal Internal Structure
Stack traces show class names, file paths and library versions. This is helpful for developers but valuable to attackers if the data is exposed.
Keep Personal Data Out
Do not attach names, emails, card numbers or tokens to events. Use internal IDs if you must identify something.
Clean in the Pipeline
Use Collector processors to remove or mask sensitive event attributes as a second line of defence.
Limit Who Can View Traces
Because events can contain detailed error information, apply role-based access to your tracing tools.
Mind Privacy Laws
Laws such as GDPR can apply to telemetry. Set retention periods and deletion processes for trace data that may include personal information.
The standard “record exception” helper copies the error’s message and stack trace automatically. This is convenient, but it means anything inside your error messages will now travel to your monitoring system. Review your error messages before turning this on widely.
13Monitoring, Logging and Metrics for Events
Events are data, so they need watching too.
- Dropped events: if spans report dropped events, you are adding too many for the limit. Find the code that adds them in loops.
- Spans with huge event counts: sort spans by event count to find the worst ones. These often reveal a loop that adds an event on each iteration.
- Exception types: group exception events by type to see which errors are most common, including handled ones that never raise an alarm.
- Handled versus failed: compare spans that have exception events and an error status with those that have exception events and a normal status. A large second group may show hidden weaknesses.
- Missing expected events: if a key event, such as “payment.authorised”, stops appearing, a code path may have changed.
- Memory and span size: large spans can slow exporters and raise costs. Track average span size and the share of oversized spans.
- Counts that matter: if you need a reliable count or rate, such as cache misses per minute, use a metric rather than counting events, since events vanish with unsampled traces.
Production Example: The Loop That Ate the Budget
A team added an event inside a loop that processed each row of an uploaded file. A file with fifty thousand rows created fifty thousand events on one span. The span grew huge, exports slowed, and the tracing bill rose sharply. A simple check on “spans with more than a hundred events” found the problem. The fix was a single event at the end with the row count as an attribute.
14Design Patterns and Anti-Patterns
Habits worth copying and traps worth avoiding.
Good design patterns
Milestone Markers
Mark the key stages of a long operation with a handful of events, so the timeline tells a clear story.
Summary at the End
Instead of one event per item, record one event or attribute with the total count and the outcome.
Central Error Handling
Record exceptions in one shared place, such as middleware, so each failure is noted exactly once.
Helper Functions
Wrap common events, like “retry started”, in a helper so that names and attributes stay consistent.
Check Before You Build
If preparing an event’s details is expensive, first check whether the span is recording.
Pair With Metrics
Use an event for the individual story and a metric for the overall rate, so you get both the detail and the trend.
Anti-patterns
The Mistake
Adding an event inside a tight loop, such as once per row, item or message.
Why It Hurts
The span fills with thousands of events, uses lots of memory, reaches the limit, and drops the very events you wanted.
Better Approach
Record one summary event or an attribute with the total. If individual items matter, sample them or use a child span for a batch.
The Mistake
Using events to record work that takes real time, such as a database call.
Why It Hurts
An event has no duration, so you lose timing, status and the ability to see how long that step took.
Better Approach
Use a child span for anything with a meaningful duration. Use events only for moments.
The Mistake
Building event names from changing values, like IDs or messages.
Why It Hurts
Every event has a unique name, so you cannot group, count or search them in a useful way.
Better Approach
Use a stable name and put changing values in attributes.
The Mistake
Recording an exception but never setting the span status, or setting the status to error for every handled exception.
Why It Hurts
In the first case, real failures are invisible to error dashboards. In the second, harmless retries create false alarms.
Better Approach
Decide clearly whether the whole operation failed. Set the error status only then, and let handled exceptions remain as events alone.
The Mistake
Relying on events as the only record of important business facts.
Why It Hurts
Events vanish when traces are sampled out, when spans never end, or when limits are hit. They are not a reliable audit record.
Better Approach
Use proper logs, a database or an audit system for facts that must never be lost. Treat events as helpful debugging clues.
15Best Practices and Common Mistakes
A practical checklist for events that stay useful.
Best practices
- Use events for moments, not durations. If it takes time, make it a span.
- Keep names stable and general. Put the details in attributes.
- Use the standard exception event. It is understood by most tools and gives consistent error views.
- Set status deliberately. Record exceptions as events, and mark the span as failed only when the whole operation failed.
- Record each failure once. Choose one clear place to record exceptions.
- Be sparing. A few well-chosen events beat hundreds of noisy ones.
- Add events while the span is open. Events added after the span ends are ignored.
- Review error messages for secrets. Clean them in code or in the Collector.
- Use metrics for counts. Do not depend on events for rates and totals.
- Document your event names. A shared list helps every team name things the same way.
Common mistakes beginners make
- Thinking an event has a duration. It has only one time.
- Assuming that recording an exception marks the span as failed.
- Expecting events to appear in the backend even when the trace was not sampled.
- Adding events to a span after it has ended.
- Confusing span events with log records. They are stored and sampled differently.
- Putting personal data or full error details into event attributes without checking.
- Forgetting that events are held in memory until the span ends.
A good test before adding an event is to ask: “Will an engineer looking at this trace at three in the morning be glad this note is here?” If the answer is yes, keep it. If it is only noise, leave it out.
16Real-World and Industry Examples
How events appear in tools and platforms you may already know.
Zipkin Annotations
Zipkin, one of the earliest open-source tracing systems, supported timestamped annotations on spans, such as when a client sent a request and when the server received it. These ideas are the ancestors of OpenTelemetry’s span events.
Jaeger
Jaeger, which began at Uber and is now a CNCF project, displays the events of a span in its trace view, historically under the word “logs.” Engineers use these to see the sequence of moments inside a slow span.
Auto-Instrumentation of Exceptions
Many automatic instrumentation libraries, such as those for web frameworks and database drivers, record exceptions as span events for you. This means that a team can get helpful error details on traces on the first day, without writing any extra code.
Browser Instrumentation
Web instrumentation for the browser can note the milestones of a page load, such as when the document becomes interactive and when it finishes loading, as events on one span. This gives a compact picture of page loading without many separate spans.
Observability Platforms
Platforms such as Honeycomb, Grafana Tempo, Datadog and New Relic accept OpenTelemetry traces with their events, and display them on span timelines. Some also let you search and group by exception type or event name, which helps spot common problems across many traces.
A typical journey for a growing team
Get Exceptions for Free
Turn on automatic instrumentation and see exception events on failing spans.
Fix the Status Rules
Agree on when a span becomes an error, so dashboards and alerts are trustworthy.
Add Milestone Events
Mark a few key moments in critical flows, such as checkout and sign-in.
Standardise Names
Publish a short list of approved event names and attributes for all teams.
Protect and Monitor
Scrub sensitive data in the Collector, and watch for dropped events and oversized spans.
17Frequently Asked Questions
Quick answers to questions beginners ask most.
18Summary and Key Takeaways
If you remember only a few things, remember these.
Key Takeaways
- An event is a dot on the span’s timeline. It is a timestamped note with a name and optional attributes, marking one moment, with no duration.
- Choose the right tool. Use attributes for facts about the whole span, child spans for work that takes time, events for notable moments, metrics for counts and logs for independent messages.
- Events live inside the span. They are held in memory until the span ends, travel with it, and disappear if the span is not recorded or exported.
- Exceptions are the best-known events. The standard exception event carries the type, message and stack trace, but you must set the span status separately.
- Name events with care. Use stable, general names, and put changing details in attributes so that events can be grouped and searched.
- Be sparing and watch the limits. Avoid adding events inside loops, and monitor dropped events and oversized spans.
- Protect your data. Error messages and stack traces can leak secrets, so review them and scrub sensitive values in code or in the Collector.