From fa8758c3bdb284a0dd5d0fd331e848ee74a6411f Mon Sep 17 00:00:00 2001 From: Lukas Stracke Date: Wed, 3 Dec 2025 16:42:02 +0100 Subject: [PATCH 01/12] feat(develop/span-first): Add implementation guidelines page --- .../sdk/telemetry/spans/implementation.mdx | 122 ++++++++++++++++++ 1 file changed, 122 insertions(+) create mode 100644 develop-docs/sdk/telemetry/spans/implementation.mdx diff --git a/develop-docs/sdk/telemetry/spans/implementation.mdx b/develop-docs/sdk/telemetry/spans/implementation.mdx new file mode 100644 index 0000000000000..3dbe6b11a692a --- /dev/null +++ b/develop-docs/sdk/telemetry/spans/implementation.mdx @@ -0,0 +1,122 @@ +--- +title: Implementation Guidelines +sidebar_order: 10 +--- + + + 🚧 This document is work in progress. + The steps and suggestions are merely suggestions and primarily serve as a mean to document what previous SDKs have been doing so far while implementing Span-First. + They therefore also serve a page to document (temporary) decisions, trade-offs, considerations, etc. + + + + This document uses key words such as "MUST", "SHOULD", and "MAY" as defined in [RFC 2119](https://www.ietf.org/rfc/rfc2119.txt) to indicate requirement levels. + + +This document provides guidelines for implementing Span-First in SDKs. This is NOT a specification for parts in the implementation process. For exact specifications, refer to the other pages under [Spans](./../index). + + + +## How To Approach Span-First in SDKs + +If you're implementing Span-First (as a PoC) in your SDK, take an iterative approach in which you implement the functionality incrementally. Here's a rough suggestion for iterations. + +1. Add the Span v2 Envelope (type), serialization logic and any utilities necessary to support sending a new envelope. See [Span Protocol](../span-protocol) for more details. +2. Add the top-level `traceLifeCycle` (or `trace_life_cycle`) SDK init option which controls if traces should be sent as transactions or as spans (v2). + - By default, the SDK MUST send traces as transactions. Span-First MUST be an opt-in feature. + - Continue with adding Span-First logic which MUST only be applied if `traceLifeCycle` is set to `'streamed'`. +3. As an initial PoC, leave your current transaction APIs in place and convert the transaction event to a v2 spans array to be sent in the new envelope. + - At this point, you can already start sending spans in batches (i..e in multiple envelopes) to send more than 1000 spans at once. +4. If applicable to your SDK, add new Span APIs to start spans. See [Span API](../span-api) for more details. + - Most importantly, add the simplest possible `start_span` API that leaves much control to users. + - Follow up with optional, more convenient APIs later. + - This new API MUST only be used in conjunction with the new `traceLifeCycle` option and therefore only emit new spans (no transactions). + - This new API MUST NOT expose any old transaction properties or concepts like (`op`, `description`, `tags`, etc). +5. Implmenting the `captureSpan` [single-span processing pipeline](#single-span-processing-pipeline) + - Either reuse existing heuristics (e.g. flush when segment span ends) or build a simple span buffer to flush spans (e.g. similar to the existing buffers for logs or metrics). + - Implementing the more complex [Telemetry Buffer](./../telemetry-buffer/index) can happen at a later stage. +6. Achieve data parity with the existing transaction events. + - Ensure that the data added by integrations, event processors, etc to transaction events is also added to the spans (See [Event Processors](#event-processors)). + - Most additional data MUST only be added to the segment span. See [Common Attributes](../span-protocol/#common-attribute-keys) for attributes that MUST be added to every span. + - Mental model: All data our SDKs _automatically_ add to a transaction, MUST also be added to the segment span. +7. Implement the span telemetry buffer for proper, weighted span flushing. See [Span Buffer](../span-buffer) for more details. +8. (Optional) Depending on necessity, drop support for sending traces as transactions in the next major release. From this point on, the SDK will by default send spans (v2) only and therefore will no longer be compatible with current self-hosted Sentry installations. + + +## Span APIs + +To do: This section needs a few guidelines and implementation hints, including: +- how to set a span active and remove it from the scope once it ends +- languages having to deal with async context management +- edge cases (e.g. adding a span with an explicit parent span that already ended) + +## Single-Span Processing Pipeline + +SDKs should expose a `captureSpan` API that takes a span once it ends, processes and enqueues it into the span buffer. In most cases, this API SHOULD be exposed as a method on the `Client`. SDKs (e.g. JS Browser) MAY chose a different location if necessary. + +Here's a rough overview of what `captureSpan` should do in which order: + +1. Accept any span that already ended (i.e. has an `end_timestamp`) +2. Obtain the current, isolation and global scopes and merge the scope data. +3. Apply [common span attributes](../span-protocol/#common-attribute-keys) from the client and the methed scope data to every span. +4. Apply the merged scope data (including scope attributes) to the span IFF it is a segment span. +5. Apply any span processing hooks (e.g. event processor replacements) to the span. +6. Apply the `before_send_span` callback to the span. +7. Enqueue the span into the span buffer. + +The `captureSpan` pipeline MUST NOT +- drop any span +- buffer spans before enqueing them + +### [TMP solution] Span Filtering + +For the moment, we settled on `ignore_spans` being applied prior to span start. This means that the `captureSpan` pipeline doesn't have to handle filtering spans. However, there are some drawbacks with this approach, most prominently: +- Not being able to filter on span names or data that is added/updated post span start +- Not being able to filter entire segments (e.g. `http.server` segments for bot requests resulting in 404 errors) + +We might revisit this, which could require changes to the single-span processing pipeline. + +For now, this means though: +- Whenever `ignore_spans` is applied, SDKs MUST NOT start an actual span. Instead, they SHOULD start a No-op ("non-recording") span, which has no influence on the trace hierarchy. +- SDKS MUST record client outcomes for ingored spans +- SDKs MUST apply `ignore_spans` to every span if at all possible (POTel SDKs are excepted, but encouraged to do so as well) + +### [TBD] Event Processors + +Given that spans no longer are events (as opposed to transactions), they don't go through our event processors, which are exensively used throughout the SDKs (clients, integrations) but also by users. +Instead, we need to find another way for users or integrations to enrich and mutate spans. + +For user-facing migration, we should try to solve every use case with `ingore_spans` (for filtering) and `before_send_span` (for enrichment, data scrubbing and span mutation). + +For SDK-internal processing, we're still evaluating the preferred approach but there are two main options: + +1. Expose new APIs for integrations (and secondarily users) to process a span. + For example via SDK lifecycle hooks (implemented in the JS SDK). + Every intergration would have to listen to this hook and apply its logic to spans. + SDKs need to add a subscriber to the hook everywhere where they currently add an event processor. + - Pro: Clear separation and semantics + - Pro: Easy to implement and maintain + - Con: Leads to a lot of duplication whenever event processors apply to more than transaction events (these we can eventually drop once span-first becomes the default) + - Con: Users have to rewrite their event processors or perhaps their integrations. Not many users write their own processors but they definitely exist. Also 3rd party published integrations would be affected. +2. Construct a pseudo-event from the span and invoke event processors during `captureSpan`. + Once the processors were applied, back-merge the modified pseudo event into the span. + - Pro: Less duplication of code + - Pro: No/less need to rewrite existing instrumentations/integrations to support span-first + - Con: Because of the single-span processing approach, we cannot add child spans to the pseudo event. Even if we somehow made this possible, we have no guarantee that the entire span tree would be present. Similarly to the [span filtering implications](#tmp-solution-span-filtering). + - Con: back-merging is complex and might not be able to cover every aspect + - Con: Very obscure behaviour (to us and users) and contradicts our commitment to move away from events in the future. + +SDK authors working on Span-First are encouraged to evaluate both options, try them out and provide perspective as well as better solutions. + +## Span Buffer + +This section is short intentionally because all buffering specification is added to the [Telemetry Buffer](../../telemetry-buffer)page. + +Some rough pointers: +- Given that SDKs SHOULD materialize and freeze the DSC as late as possible, the span buffer SHOULD enqueue span instances and at _flush time_ serialize them to JSON. + Before serialization, the span buffer SHOULD materialize and freeze the DSC on the segment span if not already done so. + This ensures that the `trace` envelope header has the most up to date data from the DSC (e.g. relevant for `transaction` names in the DSC). +- SDKs SHOULD follow one of the backend, mobile or browser telemetry buffer specifications. +- It is expected and fine to implement the proper, weighted buffering logic as a final step in the Span-First project. + Intermediate buffers MAY be simpler, for example disregard the priority logic and just buffer until a certain span length, size or time interval is reached. + \ No newline at end of file From a416952d50f29ddc46b58311b77df1011df1a38d Mon Sep 17 00:00:00 2001 From: Lukas Stracke Date: Wed, 3 Dec 2025 16:43:37 +0100 Subject: [PATCH 02/12] reword --- develop-docs/sdk/telemetry/spans/implementation.mdx | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/develop-docs/sdk/telemetry/spans/implementation.mdx b/develop-docs/sdk/telemetry/spans/implementation.mdx index 3dbe6b11a692a..753d5b162fb3a 100644 --- a/develop-docs/sdk/telemetry/spans/implementation.mdx +++ b/develop-docs/sdk/telemetry/spans/implementation.mdx @@ -5,7 +5,7 @@ sidebar_order: 10 🚧 This document is work in progress. - The steps and suggestions are merely suggestions and primarily serve as a mean to document what previous SDKs have been doing so far while implementing Span-First. + The steps and suggestions in this document primarily serve as a means to document what SDKs so far have been doing when implementing Span-First. They therefore also serve a page to document (temporary) decisions, trade-offs, considerations, etc. @@ -13,9 +13,7 @@ sidebar_order: 10 This document uses key words such as "MUST", "SHOULD", and "MAY" as defined in [RFC 2119](https://www.ietf.org/rfc/rfc2119.txt) to indicate requirement levels. -This document provides guidelines for implementing Span-First in SDKs. This is NOT a specification for parts in the implementation process. For exact specifications, refer to the other pages under [Spans](./../index). - - +This document provides guidelines for implementing Span-First in SDKs. This is purposefully NOT a full specification. For exact specifications, refer to the other pages under [Spans](./../index). ## How To Approach Span-First in SDKs From 9face3c03b5b3436e05a3138ae18f103a3667352 Mon Sep 17 00:00:00 2001 From: Lukas Stracke Date: Wed, 3 Dec 2025 16:50:22 +0100 Subject: [PATCH 03/12] reword --- develop-docs/sdk/telemetry/spans/implementation.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/develop-docs/sdk/telemetry/spans/implementation.mdx b/develop-docs/sdk/telemetry/spans/implementation.mdx index 753d5b162fb3a..d158fb2bc6284 100644 --- a/develop-docs/sdk/telemetry/spans/implementation.mdx +++ b/develop-docs/sdk/telemetry/spans/implementation.mdx @@ -6,7 +6,7 @@ sidebar_order: 10 🚧 This document is work in progress. The steps and suggestions in this document primarily serve as a means to document what SDKs so far have been doing when implementing Span-First. - They therefore also serve a page to document (temporary) decisions, trade-offs, considerations, etc. + This page also serves as a place to document (temporary) decisions, trade-offs, considerations, etc. From f5ee5d10d905d3a233c4e44a5e92b565fa09f9c1 Mon Sep 17 00:00:00 2001 From: Lukas Stracke Date: Wed, 3 Dec 2025 17:28:24 +0100 Subject: [PATCH 04/12] add startSpan TBD --- develop-docs/sdk/telemetry/spans/implementation.mdx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/develop-docs/sdk/telemetry/spans/implementation.mdx b/develop-docs/sdk/telemetry/spans/implementation.mdx index d158fb2bc6284..67caef24fab9d 100644 --- a/develop-docs/sdk/telemetry/spans/implementation.mdx +++ b/develop-docs/sdk/telemetry/spans/implementation.mdx @@ -30,7 +30,8 @@ If you're implementing Span-First (as a PoC) in your SDK, take an iterative appr - Follow up with optional, more convenient APIs later. - This new API MUST only be used in conjunction with the new `traceLifeCycle` option and therefore only emit new spans (no transactions). - This new API MUST NOT expose any old transaction properties or concepts like (`op`, `description`, `tags`, etc). -5. Implmenting the `captureSpan` [single-span processing pipeline](#single-span-processing-pipeline) + - TBD: Some SDKs already have `startSpan` or similar APIs. The migration path is still TBD but a decision can be made at a later stage. +5. Implment the `captureSpan` [single-span processing pipeline](#single-span-processing-pipeline) - Either reuse existing heuristics (e.g. flush when segment span ends) or build a simple span buffer to flush spans (e.g. similar to the existing buffers for logs or metrics). - Implementing the more complex [Telemetry Buffer](./../telemetry-buffer/index) can happen at a later stage. 6. Achieve data parity with the existing transaction events. @@ -108,7 +109,7 @@ SDK authors working on Span-First are encouraged to evaluate both options, try t ## Span Buffer -This section is short intentionally because all buffering specification is added to the [Telemetry Buffer](../../telemetry-buffer)page. +This section is intentionally short because all buffering specification is being added to the [Telemetry Buffer](../../telemetry-buffer)page. Some rough pointers: - Given that SDKs SHOULD materialize and freeze the DSC as late as possible, the span buffer SHOULD enqueue span instances and at _flush time_ serialize them to JSON. From 8e0553c361a2a313b79ecbe2e6cd84f125b8d8b3 Mon Sep 17 00:00:00 2001 From: Lukas Stracke Date: Wed, 3 Dec 2025 17:29:04 +0100 Subject: [PATCH 05/12] fix broken link --- develop-docs/sdk/telemetry/spans/implementation.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/develop-docs/sdk/telemetry/spans/implementation.mdx b/develop-docs/sdk/telemetry/spans/implementation.mdx index 67caef24fab9d..e6d9625dcacc7 100644 --- a/develop-docs/sdk/telemetry/spans/implementation.mdx +++ b/develop-docs/sdk/telemetry/spans/implementation.mdx @@ -38,7 +38,7 @@ If you're implementing Span-First (as a PoC) in your SDK, take an iterative appr - Ensure that the data added by integrations, event processors, etc to transaction events is also added to the spans (See [Event Processors](#event-processors)). - Most additional data MUST only be added to the segment span. See [Common Attributes](../span-protocol/#common-attribute-keys) for attributes that MUST be added to every span. - Mental model: All data our SDKs _automatically_ add to a transaction, MUST also be added to the segment span. -7. Implement the span telemetry buffer for proper, weighted span flushing. See [Span Buffer](../span-buffer) for more details. +7. Implement the span telemetry buffer for proper, weighted span flushing. See [Span Buffer](#span-buffer) for more details. 8. (Optional) Depending on necessity, drop support for sending traces as transactions in the next major release. From this point on, the SDK will by default send spans (v2) only and therefore will no longer be compatible with current self-hosted Sentry installations. From 982025c1beaf3349692f9ae1386d1cd964ee0c1d Mon Sep 17 00:00:00 2001 From: Lukas Stracke Date: Wed, 3 Dec 2025 17:32:55 +0100 Subject: [PATCH 06/12] typos --- develop-docs/sdk/telemetry/spans/implementation.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/develop-docs/sdk/telemetry/spans/implementation.mdx b/develop-docs/sdk/telemetry/spans/implementation.mdx index e6d9625dcacc7..e4ffb034b35bb 100644 --- a/develop-docs/sdk/telemetry/spans/implementation.mdx +++ b/develop-docs/sdk/telemetry/spans/implementation.mdx @@ -51,7 +51,7 @@ To do: This section needs a few guidelines and implementation hints, including: ## Single-Span Processing Pipeline -SDKs should expose a `captureSpan` API that takes a span once it ends, processes and enqueues it into the span buffer. In most cases, this API SHOULD be exposed as a method on the `Client`. SDKs (e.g. JS Browser) MAY chose a different location if necessary. +SDKs MUST expose a `captureSpan` API that takes a single span once it ends, and then processes and enqueues it into the span buffer. In most cases, this API SHOULD be exposed as a method on the `Client`. SDKs (e.g. JS Browser) MAY chose a different location if necessary. Here's a rough overview of what `captureSpan` should do in which order: @@ -59,7 +59,7 @@ Here's a rough overview of what `captureSpan` should do in which order: 2. Obtain the current, isolation and global scopes and merge the scope data. 3. Apply [common span attributes](../span-protocol/#common-attribute-keys) from the client and the methed scope data to every span. 4. Apply the merged scope data (including scope attributes) to the span IFF it is a segment span. -5. Apply any span processing hooks (e.g. event processor replacements) to the span. +5. Apply any span processing hooks (i.e. event processor replacements) to the span. 6. Apply the `before_send_span` callback to the span. 7. Enqueue the span into the span buffer. From 24a43654627398c54f4896135c1b6fb9322d8b02 Mon Sep 17 00:00:00 2001 From: Lukas Stracke Date: Wed, 3 Dec 2025 17:36:01 +0100 Subject: [PATCH 07/12] more tyops --- develop-docs/sdk/telemetry/spans/implementation.mdx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/develop-docs/sdk/telemetry/spans/implementation.mdx b/develop-docs/sdk/telemetry/spans/implementation.mdx index e4ffb034b35bb..523ce1e9e0e8f 100644 --- a/develop-docs/sdk/telemetry/spans/implementation.mdx +++ b/develop-docs/sdk/telemetry/spans/implementation.mdx @@ -31,7 +31,7 @@ If you're implementing Span-First (as a PoC) in your SDK, take an iterative appr - This new API MUST only be used in conjunction with the new `traceLifeCycle` option and therefore only emit new spans (no transactions). - This new API MUST NOT expose any old transaction properties or concepts like (`op`, `description`, `tags`, etc). - TBD: Some SDKs already have `startSpan` or similar APIs. The migration path is still TBD but a decision can be made at a later stage. -5. Implment the `captureSpan` [single-span processing pipeline](#single-span-processing-pipeline) +5. Implement the `captureSpan` [single-span processing pipeline](#single-span-processing-pipeline) - Either reuse existing heuristics (e.g. flush when segment span ends) or build a simple span buffer to flush spans (e.g. similar to the existing buffers for logs or metrics). - Implementing the more complex [Telemetry Buffer](./../telemetry-buffer/index) can happen at a later stage. 6. Achieve data parity with the existing transaction events. @@ -57,7 +57,7 @@ Here's a rough overview of what `captureSpan` should do in which order: 1. Accept any span that already ended (i.e. has an `end_timestamp`) 2. Obtain the current, isolation and global scopes and merge the scope data. -3. Apply [common span attributes](../span-protocol/#common-attribute-keys) from the client and the methed scope data to every span. +3. Apply [common span attributes](../span-protocol/#common-attribute-keys) from the client and the merged scope data to every span. 4. Apply the merged scope data (including scope attributes) to the span IFF it is a segment span. 5. Apply any span processing hooks (i.e. event processor replacements) to the span. 6. Apply the `before_send_span` callback to the span. @@ -65,7 +65,7 @@ Here's a rough overview of what `captureSpan` should do in which order: The `captureSpan` pipeline MUST NOT - drop any span -- buffer spans before enqueing them +- buffer spans before enqueuing them ### [TMP solution] Span Filtering @@ -77,7 +77,7 @@ We might revisit this, which could require changes to the single-span processing For now, this means though: - Whenever `ignore_spans` is applied, SDKs MUST NOT start an actual span. Instead, they SHOULD start a No-op ("non-recording") span, which has no influence on the trace hierarchy. -- SDKS MUST record client outcomes for ingored spans +- SDKS MUST record client outcomes for ignored spans - SDKs MUST apply `ignore_spans` to every span if at all possible (POTel SDKs are excepted, but encouraged to do so as well) ### [TBD] Event Processors @@ -85,13 +85,13 @@ For now, this means though: Given that spans no longer are events (as opposed to transactions), they don't go through our event processors, which are exensively used throughout the SDKs (clients, integrations) but also by users. Instead, we need to find another way for users or integrations to enrich and mutate spans. -For user-facing migration, we should try to solve every use case with `ingore_spans` (for filtering) and `before_send_span` (for enrichment, data scrubbing and span mutation). +For user-facing migration, we should try to solve every use case with `ignore_spans` (for filtering) and `before_send_span` (for enrichment, data scrubbing and span mutation). For SDK-internal processing, we're still evaluating the preferred approach but there are two main options: 1. Expose new APIs for integrations (and secondarily users) to process a span. For example via SDK lifecycle hooks (implemented in the JS SDK). - Every intergration would have to listen to this hook and apply its logic to spans. + Every integration would have to listen to this hook and apply its logic to spans. SDKs need to add a subscriber to the hook everywhere where they currently add an event processor. - Pro: Clear separation and semantics - Pro: Easy to implement and maintain From ba7af5b09dd59f0a7ef0e9a3a6a785fb03b558ea Mon Sep 17 00:00:00 2001 From: Lukas Stracke Date: Wed, 3 Dec 2025 17:50:23 +0100 Subject: [PATCH 08/12] fix more broken links --- develop-docs/sdk/telemetry/spans/implementation.mdx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/develop-docs/sdk/telemetry/spans/implementation.mdx b/develop-docs/sdk/telemetry/spans/implementation.mdx index 523ce1e9e0e8f..02541d46b672a 100644 --- a/develop-docs/sdk/telemetry/spans/implementation.mdx +++ b/develop-docs/sdk/telemetry/spans/implementation.mdx @@ -13,7 +13,7 @@ sidebar_order: 10 This document uses key words such as "MUST", "SHOULD", and "MAY" as defined in [RFC 2119](https://www.ietf.org/rfc/rfc2119.txt) to indicate requirement levels. -This document provides guidelines for implementing Span-First in SDKs. This is purposefully NOT a full specification. For exact specifications, refer to the other pages under [Spans](./../index). +This document provides guidelines for implementing Span-First in SDKs. This is purposefully NOT a full specification. For exact specifications, refer to the other pages under [Spans](..). ## How To Approach Span-First in SDKs @@ -33,9 +33,9 @@ If you're implementing Span-First (as a PoC) in your SDK, take an iterative appr - TBD: Some SDKs already have `startSpan` or similar APIs. The migration path is still TBD but a decision can be made at a later stage. 5. Implement the `captureSpan` [single-span processing pipeline](#single-span-processing-pipeline) - Either reuse existing heuristics (e.g. flush when segment span ends) or build a simple span buffer to flush spans (e.g. similar to the existing buffers for logs or metrics). - - Implementing the more complex [Telemetry Buffer](./../telemetry-buffer/index) can happen at a later stage. + - Implementing the more complex [Telemetry Buffer](./../../telemetry-buffer) can happen at a later stage. 6. Achieve data parity with the existing transaction events. - - Ensure that the data added by integrations, event processors, etc to transaction events is also added to the spans (See [Event Processors](#event-processors)). + - Ensure that the data added by integrations, event processors, etc to transaction events is also added to the spans (See [Event Processors](#tbd-event-processors)). - Most additional data MUST only be added to the segment span. See [Common Attributes](../span-protocol/#common-attribute-keys) for attributes that MUST be added to every span. - Mental model: All data our SDKs _automatically_ add to a transaction, MUST also be added to the segment span. 7. Implement the span telemetry buffer for proper, weighted span flushing. See [Span Buffer](#span-buffer) for more details. @@ -109,7 +109,7 @@ SDK authors working on Span-First are encouraged to evaluate both options, try t ## Span Buffer -This section is intentionally short because all buffering specification is being added to the [Telemetry Buffer](../../telemetry-buffer)page. +This section is intentionally short because all buffering specification is being added to the [Telemetry Buffer](../../telemetry-buffer) page. Some rough pointers: - Given that SDKs SHOULD materialize and freeze the DSC as late as possible, the span buffer SHOULD enqueue span instances and at _flush time_ serialize them to JSON. From a82cf16bead686e842ec1e677d6ca702cfa8970a Mon Sep 17 00:00:00 2001 From: Lukas Stracke Date: Sun, 7 Dec 2025 18:30:36 +0100 Subject: [PATCH 09/12] Apply suggestions from code review Co-authored-by: Ivana Kellyer Co-authored-by: Giancarlo Buenaflor --- .../sdk/telemetry/spans/implementation.mdx | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/develop-docs/sdk/telemetry/spans/implementation.mdx b/develop-docs/sdk/telemetry/spans/implementation.mdx index 02541d46b672a..711bc9fdf8aa1 100644 --- a/develop-docs/sdk/telemetry/spans/implementation.mdx +++ b/develop-docs/sdk/telemetry/spans/implementation.mdx @@ -21,10 +21,11 @@ If you're implementing Span-First (as a PoC) in your SDK, take an iterative appr 1. Add the Span v2 Envelope (type), serialization logic and any utilities necessary to support sending a new envelope. See [Span Protocol](../span-protocol) for more details. 2. Add the top-level `traceLifeCycle` (or `trace_life_cycle`) SDK init option which controls if traces should be sent as transactions or as spans (v2). - - By default, the SDK MUST send traces as transactions. Span-First MUST be an opt-in feature. + - The allowed values for this option MUST be `'static'` and `'streamed'`. + - By default, the SDK MUST send traces as transactions (`'static'`). Span-First MUST be an opt-in feature. - Continue with adding Span-First logic which MUST only be applied if `traceLifeCycle` is set to `'streamed'`. 3. As an initial PoC, leave your current transaction APIs in place and convert the transaction event to a v2 spans array to be sent in the new envelope. - - At this point, you can already start sending spans in batches (i..e in multiple envelopes) to send more than 1000 spans at once. + - At this point, you can already start sending spans in batches (i.e. in multiple envelopes) to send more than 1000 spans at once. The maximum number of spans per envelope MUST be limited to 1000 and an envelope MUST only contain spans from one trace (as the trace envelope header is shared). 4. If applicable to your SDK, add new Span APIs to start spans. See [Span API](../span-api) for more details. - Most importantly, add the simplest possible `start_span` API that leaves much control to users. - Follow up with optional, more convenient APIs later. @@ -35,7 +36,7 @@ If you're implementing Span-First (as a PoC) in your SDK, take an iterative appr - Either reuse existing heuristics (e.g. flush when segment span ends) or build a simple span buffer to flush spans (e.g. similar to the existing buffers for logs or metrics). - Implementing the more complex [Telemetry Buffer](./../../telemetry-buffer) can happen at a later stage. 6. Achieve data parity with the existing transaction events. - - Ensure that the data added by integrations, event processors, etc to transaction events is also added to the spans (See [Event Processors](#tbd-event-processors)). + - Ensure that the data added by SDK integrations, event processors, etc. to transaction events is also added to the spans (see [Event Processors](#tbd-event-processors)). - Most additional data MUST only be added to the segment span. See [Common Attributes](../span-protocol/#common-attribute-keys) for attributes that MUST be added to every span. - Mental model: All data our SDKs _automatically_ add to a transaction, MUST also be added to the segment span. 7. Implement the span telemetry buffer for proper, weighted span flushing. See [Span Buffer](#span-buffer) for more details. @@ -118,4 +119,12 @@ Some rough pointers: - SDKs SHOULD follow one of the backend, mobile or browser telemetry buffer specifications. - It is expected and fine to implement the proper, weighted buffering logic as a final step in the Span-First project. Intermediate buffers MAY be simpler, for example disregard the priority logic and just buffer until a certain span length, size or time interval is reached. - \ No newline at end of file +## Release + +The initial PoC implementation of Span-First **SHOULD** be released in a **minor version** of the SDK. + +- This feature is entirely opt-in via `traceLifeCycle = 'streamed'` and therefore does **not** introduce breaking changes to existing users. +- The default tracing behavior (transaction-based) MUST remain unchanged until Span-First becomes the default in a future major release. +- Release notes and user facing documentation SHOULD clearly describe: + - the availability of Span-First behind the opt-in flag + - any known limitations \ No newline at end of file From 53e523c8c39c5779c6cd4ef0bbbb6976e252a593 Mon Sep 17 00:00:00 2001 From: Lukas Stracke Date: Sun, 7 Dec 2025 18:31:44 +0100 Subject: [PATCH 10/12] Apply suggestions from code review --- develop-docs/sdk/telemetry/spans/implementation.mdx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/develop-docs/sdk/telemetry/spans/implementation.mdx b/develop-docs/sdk/telemetry/spans/implementation.mdx index 711bc9fdf8aa1..b5591eda4e8cc 100644 --- a/develop-docs/sdk/telemetry/spans/implementation.mdx +++ b/develop-docs/sdk/telemetry/spans/implementation.mdx @@ -21,9 +21,9 @@ If you're implementing Span-First (as a PoC) in your SDK, take an iterative appr 1. Add the Span v2 Envelope (type), serialization logic and any utilities necessary to support sending a new envelope. See [Span Protocol](../span-protocol) for more details. 2. Add the top-level `traceLifeCycle` (or `trace_life_cycle`) SDK init option which controls if traces should be sent as transactions or as spans (v2). - - The allowed values for this option MUST be `'static'` and `'streamed'`. + - The allowed values for this option MUST be `'static'` and `'strea'`. - By default, the SDK MUST send traces as transactions (`'static'`). Span-First MUST be an opt-in feature. - - Continue with adding Span-First logic which MUST only be applied if `traceLifeCycle` is set to `'streamed'`. + - Continue with adding Span-First logic which MUST only be applied if `traceLifeCycle` is set to `'stream'`. 3. As an initial PoC, leave your current transaction APIs in place and convert the transaction event to a v2 spans array to be sent in the new envelope. - At this point, you can already start sending spans in batches (i.e. in multiple envelopes) to send more than 1000 spans at once. The maximum number of spans per envelope MUST be limited to 1000 and an envelope MUST only contain spans from one trace (as the trace envelope header is shared). 4. If applicable to your SDK, add new Span APIs to start spans. See [Span API](../span-api) for more details. @@ -123,7 +123,7 @@ Some rough pointers: The initial PoC implementation of Span-First **SHOULD** be released in a **minor version** of the SDK. -- This feature is entirely opt-in via `traceLifeCycle = 'streamed'` and therefore does **not** introduce breaking changes to existing users. +- This feature is entirely opt-in via `traceLifeCycle = 'stream'` and therefore does **not** introduce breaking changes to existing users. - The default tracing behavior (transaction-based) MUST remain unchanged until Span-First becomes the default in a future major release. - Release notes and user facing documentation SHOULD clearly describe: - the availability of Span-First behind the opt-in flag From 482820adde5a431b729bef3d7a79607ed8b8da7e Mon Sep 17 00:00:00 2001 From: Lukas Stracke Date: Sun, 7 Dec 2025 18:33:52 +0100 Subject: [PATCH 11/12] Apply suggestions from code review --- develop-docs/sdk/telemetry/spans/implementation.mdx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/develop-docs/sdk/telemetry/spans/implementation.mdx b/develop-docs/sdk/telemetry/spans/implementation.mdx index b5591eda4e8cc..5d275c9e8b232 100644 --- a/develop-docs/sdk/telemetry/spans/implementation.mdx +++ b/develop-docs/sdk/telemetry/spans/implementation.mdx @@ -20,16 +20,16 @@ This document provides guidelines for implementing Span-First in SDKs. This is p If you're implementing Span-First (as a PoC) in your SDK, take an iterative approach in which you implement the functionality incrementally. Here's a rough suggestion for iterations. 1. Add the Span v2 Envelope (type), serialization logic and any utilities necessary to support sending a new envelope. See [Span Protocol](../span-protocol) for more details. -2. Add the top-level `traceLifeCycle` (or `trace_life_cycle`) SDK init option which controls if traces should be sent as transactions or as spans (v2). +2. Add the top-level `traceLifecycle` (or `trace_lifecycle`) SDK init option which controls if traces should be sent as transactions or as spans (v2). - The allowed values for this option MUST be `'static'` and `'strea'`. - By default, the SDK MUST send traces as transactions (`'static'`). Span-First MUST be an opt-in feature. - - Continue with adding Span-First logic which MUST only be applied if `traceLifeCycle` is set to `'stream'`. + - Continue with adding Span-First logic which MUST only be applied if `traceLifecycle` is set to `'stream'`. 3. As an initial PoC, leave your current transaction APIs in place and convert the transaction event to a v2 spans array to be sent in the new envelope. - At this point, you can already start sending spans in batches (i.e. in multiple envelopes) to send more than 1000 spans at once. The maximum number of spans per envelope MUST be limited to 1000 and an envelope MUST only contain spans from one trace (as the trace envelope header is shared). 4. If applicable to your SDK, add new Span APIs to start spans. See [Span API](../span-api) for more details. - Most importantly, add the simplest possible `start_span` API that leaves much control to users. - Follow up with optional, more convenient APIs later. - - This new API MUST only be used in conjunction with the new `traceLifeCycle` option and therefore only emit new spans (no transactions). + - This new API MUST only be used in conjunction with the new `traceLifecycle` option and therefore only emit new spans (no transactions). - This new API MUST NOT expose any old transaction properties or concepts like (`op`, `description`, `tags`, etc). - TBD: Some SDKs already have `startSpan` or similar APIs. The migration path is still TBD but a decision can be made at a later stage. 5. Implement the `captureSpan` [single-span processing pipeline](#single-span-processing-pipeline) @@ -123,7 +123,7 @@ Some rough pointers: The initial PoC implementation of Span-First **SHOULD** be released in a **minor version** of the SDK. -- This feature is entirely opt-in via `traceLifeCycle = 'stream'` and therefore does **not** introduce breaking changes to existing users. +- This feature is entirely opt-in via `traceLifecycle = 'stream'` and therefore does **not** introduce breaking changes to existing users. - The default tracing behavior (transaction-based) MUST remain unchanged until Span-First becomes the default in a future major release. - Release notes and user facing documentation SHOULD clearly describe: - the availability of Span-First behind the opt-in flag From da22b11b08fd107b5dc61982ac4638601ead8e7b Mon Sep 17 00:00:00 2001 From: Lukas Stracke Date: Sun, 7 Dec 2025 18:34:20 +0100 Subject: [PATCH 12/12] Update develop-docs/sdk/telemetry/spans/implementation.mdx --- develop-docs/sdk/telemetry/spans/implementation.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/develop-docs/sdk/telemetry/spans/implementation.mdx b/develop-docs/sdk/telemetry/spans/implementation.mdx index 5d275c9e8b232..9a5b85e631299 100644 --- a/develop-docs/sdk/telemetry/spans/implementation.mdx +++ b/develop-docs/sdk/telemetry/spans/implementation.mdx @@ -21,7 +21,7 @@ If you're implementing Span-First (as a PoC) in your SDK, take an iterative appr 1. Add the Span v2 Envelope (type), serialization logic and any utilities necessary to support sending a new envelope. See [Span Protocol](../span-protocol) for more details. 2. Add the top-level `traceLifecycle` (or `trace_lifecycle`) SDK init option which controls if traces should be sent as transactions or as spans (v2). - - The allowed values for this option MUST be `'static'` and `'strea'`. + - The allowed values for this option MUST be `'static'` and `'stream'`. - By default, the SDK MUST send traces as transactions (`'static'`). Span-First MUST be an opt-in feature. - Continue with adding Span-First logic which MUST only be applied if `traceLifecycle` is set to `'stream'`. 3. As an initial PoC, leave your current transaction APIs in place and convert the transaction event to a v2 spans array to be sent in the new envelope.