Span Protocol
This document uses key words such as "MUST", "SHOULD", and "MAY" as defined in RFC 2119 to indicate requirement levels.
The SDK must implement a new "span v2" envelope item, which is used to emit spans to Sentry.
The envelope header must contain the same properties as previously with transactions. There are no special requirements for the Span v2 envelope header.
{
"sent_at": "2025-02-07T14:16:00Z",
"dsn": "https://e12d836b15bb49d7bbf99e64295d995b@sentry.io/42",
"sdk": {
// ...
},
"trace": {
// ...
}
}
{
"sent_at": "2025-02-07T14:16:00Z",
"dsn": "https://e12d836b15bb49d7bbf99e64295d995b@sentry.io/42",
"sdk": {
// ...
},
"trace": {
// ...
}
}
Unlike transactions, envelope headers for spans require Dynamic sampling context. Also see Envelope Headers.
The envelope item header must contain the following properties:
{
"type": "span",
"item_count": 2,
"content_type": "application/vnd.sentry.items.span.v2+json"
}
{
"type": "span",
"item_count": 2,
"content_type": "application/vnd.sentry.items.span.v2+json"
}
The span v2 envelope item payload is a JSON object that MUST include an items array of span objects. The payload MAY also include top-level version and ingest_settings fields as specified in the next section.
The container is defined as follows:
{
"version": 2,
"ingest_settings": {
"infer_ip": "auto",
"infer_user_agent": "auto"
},
"items": [{..span..}, {..span..}, {..span..}]
}
{
"version": 2,
"ingest_settings": {
"infer_ip": "auto",
"infer_user_agent": "auto"
},
"items": [{..span..}, {..span..}, {..span..}]
}
The span envelope item SHOULD include version and ingest_settings properties to instruct Relay to infer IP address and user agent from the incoming request. See the Ingest Settings spec for the full definition, field reference, and behavior.
The items array MUST contain at least one and at most 1000 span objects:
{
"items": [
{
"trace_id": "6cf173d587eb48568a9b2e12dcfbea52",
"span_id": "438f40bd3b4a41ee",
"name": "GET /users",
"status": "ok",
"is_segment": true,
"start_timestamp": 1742921669.158209,
"end_timestamp": 1742921669.180536,
"attributes": {
"sentry.segment.name": {
"type": "string",
"value": "GET /users"
},
"sentry.segment.id": {
"type": "string",
"value": "438f40bd3b4a41ee"
},
"sentry.release": {
"type": "string",
"value": "1.0.0"
},
"sentry.environment": {
"type": "string",
"value": "local"
},
"sentry.op": {
"type": "string",
"value": "http.server"
},
"sentry.platform": {
"type": "string",
"value": "php"
},
"sentry.sdk.name": {
"type": "string",
"value": "sentry.php"
},
"sentry.sdk.version": {
"type": "string",
"value": "4.10.0"
},
"sentry.segment.name.source": {
"type": "string",
"value": "route"
},
"sentry.origin": {
"type": "string",
"value": "auto"
},
"server.address": {
"type": "string",
"value": "127.0.0.1"
},
"http.response.status_code": {
"type": "integer",
"value": 200
},
"session.duration": {
"type": "integer",
"value": 164,
"unit": "second"
}
},
"links": [
{
"span_id": "6c71fc6b09b8b716",
"trace_id": "627a2885119dcc8184fae7eef09438cb",
"sampled": true,
"attributes": {
"sentry.link.type": {
"type": "string",
"value": "previous_trace"
}
}
}
]
},
{
"trace_id": "6cf173d587eb48568a9b2e12dcfbea52",
"parent_span_id": "438f40bd3b4a41ee",
"span_id": "f1196292f76e45c0",
"name": "app.handle",
"status": "ok",
"is_segment": false,
"start_timestamp": 1742921669.178306,
"end_timestamp": 1742921669.180484,
"attributes": {
"sentry.segment.name": {
"type": "string",
"value": "GET /users"
},
"sentry.segment.id": {
"type": "string",
"value": "438f40bd3b4a41ee"
},
"sentry.op": {
"type": "string",
"value": "middleware"
},
"sentry.release": {
"type": "string",
"value": "1.0.0"
},
"sentry.environment": {
"type": "string",
"value": "local"
},
"sentry.sdk.name": {
"type": "string",
"value": "sentry.php"
},
"sentry.sdk.version": {
"type": "string",
"value": "4.10.0"
},
"sentry.origin": {
"type": "string",
"value": "auto"
}
}
}
]
}
{
"items": [
{
"trace_id": "6cf173d587eb48568a9b2e12dcfbea52",
"span_id": "438f40bd3b4a41ee",
"name": "GET /users",
"status": "ok",
"is_segment": true,
"start_timestamp": 1742921669.158209,
"end_timestamp": 1742921669.180536,
"attributes": {
"sentry.segment.name": {
"type": "string",
"value": "GET /users"
},
"sentry.segment.id": {
"type": "string",
"value": "438f40bd3b4a41ee"
},
"sentry.release": {
"type": "string",
"value": "1.0.0"
},
"sentry.environment": {
"type": "string",
"value": "local"
},
"sentry.op": {
"type": "string",
"value": "http.server"
},
"sentry.platform": {
"type": "string",
"value": "php"
},
"sentry.sdk.name": {
"type": "string",
"value": "sentry.php"
},
"sentry.sdk.version": {
"type": "string",
"value": "4.10.0"
},
"sentry.segment.name.source": {
"type": "string",
"value": "route"
},
"sentry.origin": {
"type": "string",
"value": "auto"
},
"server.address": {
"type": "string",
"value": "127.0.0.1"
},
"http.response.status_code": {
"type": "integer",
"value": 200
},
"session.duration": {
"type": "integer",
"value": 164,
"unit": "second"
}
},
"links": [
{
"span_id": "6c71fc6b09b8b716",
"trace_id": "627a2885119dcc8184fae7eef09438cb",
"sampled": true,
"attributes": {
"sentry.link.type": {
"type": "string",
"value": "previous_trace"
}
}
}
]
},
{
"trace_id": "6cf173d587eb48568a9b2e12dcfbea52",
"parent_span_id": "438f40bd3b4a41ee",
"span_id": "f1196292f76e45c0",
"name": "app.handle",
"status": "ok",
"is_segment": false,
"start_timestamp": 1742921669.178306,
"end_timestamp": 1742921669.180484,
"attributes": {
"sentry.segment.name": {
"type": "string",
"value": "GET /users"
},
"sentry.segment.id": {
"type": "string",
"value": "438f40bd3b4a41ee"
},
"sentry.op": {
"type": "string",
"value": "middleware"
},
"sentry.release": {
"type": "string",
"value": "1.0.0"
},
"sentry.environment": {
"type": "string",
"value": "local"
},
"sentry.sdk.name": {
"type": "string",
"value": "sentry.php"
},
"sentry.sdk.version": {
"type": "string",
"value": "4.10.0"
},
"sentry.origin": {
"type": "string",
"value": "auto"
}
}
}
]
}
| Property | Type | Required | Description |
|---|---|---|---|
type | string | Yes | Must be set to "span" to identify this as a span envelope item |
item_count | integer | Yes | Number of span items in the payload |
content_type | string | Yes | Must be set to "application/vnd.sentry.items.span.v2+json" |
| Property | Type | Required | Description |
|---|---|---|---|
trace_id | string | Yes | 32-character hexadecimal string (a valid uuid4 without dashes) |
span_id | string | Yes | 16-character hexadecimal string (a valid uuid4 without dashes) |
parent_span_id | string | No | 16-character hexadecimal string (a valid uuid4 without dashes) |
name | string | Yes | A low cardinality description of what the span represents (e.g., "GET /users", "database.query") |
status | string | Yes | Status of the span operation. Either "ok" or "error" |
is_segment | boolean | Yes | Whether the span is a segment span |
start_timestamp | number | Yes | Unix timestamp (with fractional microseconds) when the span was started |
end_timestamp | number | Yes | Unix timestamp (with fractional microseconds) when the span was ended |
attributes | object | No | Key-value pairs containing additional metadata about the span |
links | array | No | Array of links connecting this span to other spans or traces |
All attributes mentioned below MUST be attached to every span being emitted from the SDK, depending on the platform and availability of the information.
| Attribute Key | Type | Required | Description |
|---|---|---|---|
sentry.segment.name | string | Strictly Required | The segment name (e.g., "GET /users") |
sentry.segment.id | string | Strictly Required | The segment span id |
sentry.trace_lifecycle | string | Required | The trace lifecycle mode. MUST be set to "stream". |
sentry.op | string | Required, see note | The span op (e.g., "http.client", "db.query") of the span. MUST be set on spans from auto instrumentation, MAY be set by manually started spans. |
sentry.release | string | Required | The release version of the application |
sentry.environment | string | Required | The environment name (e.g., "production", "staging", "development") |
sentry.segment.name.source | string | Required on segment spans | The source of the span name. MUST exclusively be set on segment spans. See Sentry Conventions for all supported sources. See Transaction Annotations for more information. |
sentry.profiler_id | string | Required | The id of the currently running profiler (continuous profiling) |
sentry.replay_id | string | Required | The id of the currently running replay (if available) |
os.name | string | Required | The operating system name (e.g., "Linux", "Windows", "macOS") |
browser.name | string | Required | The browser name (e.g., "Chrome", "Firefox", "Safari") |
user.id | string | Required | The user ID |
user.email | string | Required | The user email |
user.ip_address | string | Required | The user IP address |
user.name | string | Required | The user username |
thread.id | string | Required | The thread ID |
thread.name | string | Required | The thread name |
sentry.sdk.name | string | Required | Name of the Sentry SDK (e.g., "sentry.php", "sentry.javascript") |
sentry.sdk.version | string | Required | Version of the Sentry SDK |
Spans missing Strictly Required attributes MAY be rejected by Relay. All other attributes in the table are required if they are available to the SDK. For example, sentry.release MUST be sent, if and only if the SDK has a release value set (or auto-detected it).
Attributes outside of the above list MUST only be attached to the span they conceptually belong on, and not propagated to children spans. For instance, attributes mirroring transaction context data should only be set on the segment span. See also the implementation guidelines.
Empty attributes MUST be omitted.
See Sentry Conventions for a full list of supported attributes.
Links connect spans to other spans or traces, enabling distributed tracing:
| Property | Type | Required | Description |
|---|---|---|---|
span_id | string | Yes | 16-character hexadecimal string (a valid uuid4 without dashes) |
trace_id | string | Yes | 32-character hexadecimal string (a valid uuid4 without dashes) |
sampled | boolean | No | Whether the linked trace was sampled |
attributes | object | No | Additional metadata about the link relationship |
| Attribute Key | Type | Description |
|---|---|---|
sentry.link.type | string | Type of link relationship (e.g., "previous_trace", "child_of", "follows_from") |
Timestamps use Unix time with fractional microseconds as a floating-point number:
1742921669.158209
1742921669.158209
- Trace ID: 32-character (128 bits) lowercase hexadecimal string (a valid uuid4 without dashes)
- Span ID: 16-character (64 bits) lowercase hexadecimal string (a valid uuid4 without dashes)
Example:
trace_id: "6cf173d587eb48568a9b2e12dcfbea52"
span_id: "438f40bd3b4a41ee"
trace_id: "6cf173d587eb48568a9b2e12dcfbea52"
span_id: "438f40bd3b4a41ee"
Span attachments are an experimental feature that is still under development.
To associate an attachment with a span, submit a trace attachment item with an additional span_id item header. The trace attachment should be submitted in the same envelope as the span itself.
span_idis the ID of the span that owns the attachment. If set, the attachment will be dropped with the span if the span is dropped by dynamic sampling, inbound filters or rate limits. That is, Relay treatsspan_idas the owner of the attachment.- The SDK may set the
span_iditem header to an explicitnullvalue.span_id: nullis treated as “owned by spans”, but not owned by a specific span. That is, the attachment can be dropped if the span quota is exceeded, but it will not be dropped with a specific span because of e.g. inbound filters.
Our documentation is open source and available on GitHub. Your contributions are welcome, whether fixing a typo (drat!) or suggesting an update ("yeah, this would be better").