Glossary · S

Span

A single named, timed operation within a distributed trace, such as an HTTP request, a database query or a message publish.

By Obseria Editorial TeamUpdated

Definition

A span is the basic unit of a distributed trace: one named, timed operation such as an incoming HTTP request, a database query or publishing a message. Each span carries trace and span IDs, a parent ID, timestamps, a kind, attributes, events, links and a status, showing where time was spent and errors occurred.

What is a span?

A span represents a single unit of work inside a request: a service handling GET /orders/{id}, an outgoing call to a payment API, a SQL query, a message consumed from Kafka. Spans that share a trace ID form a trace, and parent-child relationships between spans turn that trace into a tree showing how a request travelled through the system and how long each step took. This is the foundation of distributed tracing.

The first span of a trace, with no parent, is the root span. Spans are created by instrumentation, either automatically by libraries and agents or manually in application code, and are linked across process boundaries through context propagation.

Span fields in the OpenTelemetry specification

FieldMeaning
NameLow-cardinality description of the operation, e.g. GET /orders/{id} or SELECT orders
Span contextTrace ID (16 bytes, 32 hex characters), span ID (8 bytes, 16 hex characters), trace flags (including the sampled bit) and trace state
Parent span IDSpan ID of the parent; empty for a root span
Span kindSERVER, CLIENT, PRODUCER, CONSUMER or INTERNAL
Start and end timeTimestamps from which the duration is derived
AttributesKey-value pairs such as http.request.method, http.response.status_code, db.system
EventsTimestamped annotations within the span, e.g. an exception with type, message and stack trace
LinksReferences to spans in other traces, e.g. for batch processing or fan-in from a queue
StatusUnset, Ok or Error, with an optional description for errors

Each span is also associated with a resource (the entity that produced it, identified by attributes like service.name and k8s.pod.name) and an instrumentation scope (the library that created it).

Span kinds and how they connect

Span kind tells the backend how a span relates to others. A CLIENT span in the checkout service and the matching SERVER span in the payment service describe the same call from both sides; the gap between them is network and queueing time. PRODUCER and CONSUMER describe asynchronous messaging, where the consumer may run long after the producer finished. INTERNAL covers work that stays inside one process. Correct span kinds are what allow tools to draw service maps and compute per-service latency accurately.

Reading span durations

A span's duration includes the time of all its children. To find the real bottleneck, look at self time: the part of a span's duration not covered by any child span. A 900 ms server span with an 850 ms database child points at the query; a 900 ms span whose children add up to 50 ms points at work inside the service itself, such as CPU-bound code, lock contention or garbage collection, where continuous profiling takes over. Children running in parallel can also overlap, so their durations do not simply add up to the parent.

Example: a simplified span

{
  "name": "POST /orders",
  "kind": "SERVER",
  "traceId": "4bf92f3577b34da6a3ce929d0e0e4736",
  "spanId": "00f067aa0ba902b7",
  "parentSpanId": "",
  "startTime": "2026-10-15T09:12:03.120Z",
  "endTime":   "2026-10-15T09:12:03.512Z",
  "attributes": {
    "http.request.method": "POST",
    "http.route": "/orders",
    "http.response.status_code": 500
  },
  "events": [{"name": "exception",
              "attributes": {"exception.type": "TimeoutError"}}],
  "status": {"code": "ERROR"}
}

This illustrative root span lasted 392 ms and failed. Its child spans, such as a database query and a call to an inventory service, would show which step consumed the time.

Best practices

  • Keep span names low-cardinality. Use route templates; put IDs in attributes, not in the name.
  • Follow semantic conventions for attribute names so queries work across languages and libraries.
  • Set status deliberately. By convention a server span for an HTTP 5xx is an error, while a 4xx is usually the caller's problem and leaves the server span unset. Instrumentation libraries leave successful spans Unset; Ok is reserved for explicit confirmation by application code.
  • Record exceptions as events so stack traces stay attached to the operation that failed.
  • Add business context sparingly: attributes such as tenant tier or feature flag make traces far more useful, but avoid personal data.

Common mistakes

  • Creating a span for every function call, which adds overhead and noise without insight.
  • Forgetting to end spans, which leaks memory and produces misleading durations.
  • Broken context between services, resulting in many disconnected root spans instead of one trace.
  • Using links where a parent relationship is correct, or the other way round.

How Obseria helps

Obseria ingests spans via OTLP from any OpenTelemetry SDK or Collector and stores them in Obseria Lake without pre-indexing, so you can filter and aggregate on any attribute. Spans are linked to logs, metrics and profiles of the same service and time window, and Obseria TopoGraph builds service maps from span kinds and parent relationships. Learn more about OpenTelemetry and how spans feed application performance monitoring.

Frequently asked questions

A span is a single timed operation. A trace is the complete set of spans that share one trace ID and describe one request or transaction end to end, organized as a tree through parent span IDs.

Span attributes are key-value pairs that describe the operation, such as the HTTP method, route, response status code or database system. OpenTelemetry semantic conventions define standard attribute names for common technologies.

The root span is the first span of a trace and has no parent. It usually represents the entry point of a request, such as the incoming HTTP request at the edge service, and its duration approximates the end-to-end latency.

Span events are timestamped annotations inside one span, such as a recorded exception. Span links connect a span to spans in other traces, for example when a batch job processes messages that originated from many different requests.

Put these concepts into practice

Try Obseria free for 14 days, with OpenTelemetry and no proprietary agents.