Lightstep from ServiceNow Logo






Lightstep from ServiceNow Logo

Spans in OpenTelemetry

A span is the building block of a trace and is a named, timed operation that represents a piece of the workflow in the distributed system. Multiple spans are pieced together to create a trace.


Traces are often viewed as a "tree" of spans that reflects the time that each span started and completed. It also shows you the relationship between spans. Here's a simplified view of a trace, as it relates to the request above.


A trace starts with a root span where the request starts. This root span can have one or more child spans, and each one of those child spans can have child spans.


The purpose of a span is to provide information to observability tools about the execution of a program, so it should contain details about the work.

The components of an individual span include:

  • Operation name
  • Start and finish timestamps
  • SpanContext
  • Set of Attributes
  • Ordered list of Events


In order for the trace tree to be built with these relationships intact, each span needs to propagate its SpanContext to its child. It may be sent along with a request to a remote system, or to another span generated by the same system. SpanContext tells the child span who its parent is (via the span_ID) and what trace it belongs to (trace_ID).


Attributes are key-value pairs that provide detail about a span. They apply to the whole span and don’t include timestamps (use an Event for information about events that happen at a specific time). Attributes allow you to query, group, or otherwise analyze traces and spans.

The OpenTelemetry Spec defines standard attributes that you should use, for example StatusCode and SpanKind).


Status is a special, standardized property for a span. It may be set to values like OK, Cancelled, and Permission Denied.


SpanKind is another standardized span property. The SpanKind property provides useful performance context in a trace - does this span call a remote system? Does it serve requests from remote systems? Does it do work asynchronously off of a queue? All of this information is useful in performance analysis. The supported values of SpanKind are CLIENT, SERVER, PRODUCER, CONSUMER, and INTERNAL.


You can also create your own attribute key/value pairs so that the information you know you'll need to understand your system are available to you.

Here are a few examples:

  • db.type: cassandra
  • db.url: mysql://
  • net.transport: IP.TCP
  • net.peer.ip:

By following these practices, your observability tools may be able to provide more useful information to you.


Events contain a name, a timestamp, and an optional set of Attributes, along with a timestamp. Events represent an event that occurred at a specific time within a span’s workload.

Here are some examples of events: t:3, name:log, message:“retrieved 400 records” t:5, name:image-generated, image.x:408, image.y:552, image.size:2055 KB

Span and trace examples

Here's an example of a Span

    t=0            operation name: db_query               t=10

     | · · · · · · · · · ·    Span     · · · · · · · · · · |

Status: Unavailable

- db.instance:"customers"
- db.statement:"SELECT * FROM mytable WHERE foo='bar'"
- peer.address:"mysql://"

- (t=4): message:"Can't connect to mysql server on ''(10061)"

  - trace_id:"abc123"
  - span_id:"xyz654"


- trace_id:"abc123"
- span_id:"xyz789"

Here's an example of a trace and its spans: