releases.shpreview

Custom spans now outlive their callback

1 featureThis release1 featureNew capabilitiesAI-tallied from the release notes
From the original release noteView original ↗

The Workers runtime now provides built-in tracing.startActiveSpan() and span.end() APIs, allowing you to write custom spans for operations that last beyond a single callback — for example, instrumenting a stream pipeline where the span should stay open until the stream is fully consumed.

This augments the existing API for writing custom spans, tracing.enterSpan(), which automatically ends a span when its callback is returned. With startActiveSpan(), the span remains open after the callback returns, and you call span.end() when the work is complete:

src/index.jsjs

<span class="line"><span class="nb-shiki-1itgoe">import</span><span class="nb-shiki-140thh"> { tracing } </span><span class="nb-shiki-1itgoe">from</span><span class="nb-shiki-mdbnqw"> "cloudflare:workers"</span><span class="nb-shiki-140thh">;</span></span>
<span class="line"></span>
<span class="line"><span class="nb-shiki-1itgoe">const</span><span class="nb-shiki-dzsirb"> encoder</span><span class="nb-shiki-1itgoe"> =</span><span class="nb-shiki-1itgoe"> new</span><span class="nb-shiki-1t8gfj"> TextEncoder</span><span class="nb-shiki-140thh">();</span></span>
<span class="line"></span>
<span class="line"><span class="nb-shiki-1itgoe">export</span><span class="nb-shiki-1itgoe"> default</span><span class="nb-shiki-140thh"> {</span></span>
<span class="line"><span class="nb-shiki-1t8gfj">	fetch</span><span class="nb-shiki-140thh">() {</span></span>
<span class="line"><span class="nb-shiki-1itgoe">		return</span><span class="nb-shiki-140thh"> tracing.</span><span class="nb-shiki-1t8gfj">startActiveSpan</span><span class="nb-shiki-140thh">(</span><span class="nb-shiki-mdbnqw">"stream-response"</span><span class="nb-shiki-140thh">, (</span><span class="nb-shiki-1jdh33">span</span><span class="nb-shiki-140thh">) </span><span class="nb-shiki-1itgoe">=></span><span class="nb-shiki-140thh"> {</span></span>
<span class="line"><span class="nb-shiki-1itgoe">			let</span><span class="nb-shiki-140thh"> timer;</span></span>
<span class="line"></span>
<span class="line"><span class="nb-shiki-1itgoe">			const</span><span class="nb-shiki-dzsirb"> body</span><span class="nb-shiki-1itgoe"> =</span><span class="nb-shiki-1itgoe"> new</span><span class="nb-shiki-1t8gfj"> ReadableStream</span><span class="nb-shiki-140thh">({</span></span>
<span class="line"><span class="nb-shiki-1t8gfj">				start</span><span class="nb-shiki-140thh">(</span><span class="nb-shiki-1jdh33">controller</span><span class="nb-shiki-140thh">) {</span></span>
<span class="line"><span class="nb-shiki-140thh">					controller.</span><span class="nb-shiki-1t8gfj">enqueue</span><span class="nb-shiki-140thh">(encoder.</span><span class="nb-shiki-1t8gfj">encode</span><span class="nb-shiki-140thh">(</span><span class="nb-shiki-mdbnqw">"Starting...</span><span class="nb-shiki-dzsirb">\n</span><span class="nb-shiki-mdbnqw">"</span><span class="nb-shiki-140thh">));</span></span>
<span class="line"></span>
<span class="line"><span class="nb-shiki-140thh">					timer </span><span class="nb-shiki-1itgoe">=</span><span class="nb-shiki-1t8gfj"> setTimeout</span><span class="nb-shiki-140thh">(() </span><span class="nb-shiki-1itgoe">=></span><span class="nb-shiki-140thh"> {</span></span>
<span class="line"><span class="nb-shiki-140thh">						controller.</span><span class="nb-shiki-1t8gfj">enqueue</span><span class="nb-shiki-140thh">(encoder.</span><span class="nb-shiki-1t8gfj">encode</span><span class="nb-shiki-140thh">(</span><span class="nb-shiki-mdbnqw">"Complete.</span><span class="nb-shiki-dzsirb">\n</span><span class="nb-shiki-mdbnqw">"</span><span class="nb-shiki-140thh">));</span></span>
<span class="line"><span class="nb-shiki-140thh">						controller.</span><span class="nb-shiki-1t8gfj">close</span><span class="nb-shiki-140thh">();</span></span>
<span class="line"></span>
<span class="line"><span class="nb-shiki-140thh">						span.</span><span class="nb-shiki-1t8gfj">setAttribute</span><span class="nb-shiki-140thh">(</span><span class="nb-shiki-mdbnqw">"stream.status"</span><span class="nb-shiki-140thh">, </span><span class="nb-shiki-mdbnqw">"complete"</span><span class="nb-shiki-140thh">);</span></span>
<span class="line"><span class="nb-shiki-140thh">						span.</span><span class="nb-shiki-1t8gfj">end</span><span class="nb-shiki-140thh">();</span></span>
<span class="line"><span class="nb-shiki-140thh">					}, </span><span class="nb-shiki-dzsirb">1000</span><span class="nb-shiki-140thh">);</span></span>
<span class="line"><span class="nb-shiki-140thh">				},</span></span>
<span class="line"></span>
<span class="line"><span class="nb-shiki-1t8gfj">				cancel</span><span class="nb-shiki-140thh">() {</span></span>
<span class="line"><span class="nb-shiki-1itgoe">					if</span><span class="nb-shiki-140thh"> (timer </span><span class="nb-shiki-1itgoe">!==</span><span class="nb-shiki-dzsirb"> undefined</span><span class="nb-shiki-140thh">) </span><span class="nb-shiki-1t8gfj">clearTimeout</span><span class="nb-shiki-140thh">(timer);</span></span>
<span class="line"></span>
<span class="line"><span class="nb-shiki-140thh">					span.</span><span class="nb-shiki-1t8gfj">setAttribute</span><span class="nb-shiki-140thh">(</span><span class="nb-shiki-mdbnqw">"stream.status"</span><span class="nb-shiki-140thh">, </span><span class="nb-shiki-mdbnqw">"cancelled"</span><span class="nb-shiki-140thh">);</span></span>
<span class="line"><span class="nb-shiki-140thh">					span.</span><span class="nb-shiki-1t8gfj">end</span><span class="nb-shiki-140thh">();</span></span>
<span class="line"><span class="nb-shiki-140thh">				},</span></span>
<span class="line"><span class="nb-shiki-140thh">			});</span></span>
<span class="line"></span>
<span class="line"><span class="nb-shiki-1itgoe">			return</span><span class="nb-shiki-1itgoe"> new</span><span class="nb-shiki-1t8gfj"> Response</span><span class="nb-shiki-140thh">(body, {</span></span>
<span class="line"><span class="nb-shiki-140thh">				headers: { </span><span class="nb-shiki-mdbnqw">"content-type"</span><span class="nb-shiki-140thh">: </span><span class="nb-shiki-mdbnqw">"text/plain"</span><span class="nb-shiki-140thh"> },</span></span>
<span class="line"><span class="nb-shiki-140thh">			});</span></span>
<span class="line"><span class="nb-shiki-140thh">		});</span></span>
<span class="line"><span class="nb-shiki-140thh">	},</span></span>
<span class="line"><span class="nb-shiki-140thh">};</span></span>

src/index.tsts

<span class="line"><span class="nb-shiki-1itgoe">import</span><span class="nb-shiki-140thh"> { tracing } </span><span class="nb-shiki-1itgoe">from</span><span class="nb-shiki-mdbnqw"> "cloudflare:workers"</span><span class="nb-shiki-140thh">;</span></span>
<span class="line"></span>
<span class="line"><span class="nb-shiki-1itgoe">const</span><span class="nb-shiki-dzsirb"> encoder</span><span class="nb-shiki-1itgoe"> =</span><span class="nb-shiki-1itgoe"> new</span><span class="nb-shiki-1t8gfj"> TextEncoder</span><span class="nb-shiki-140thh">();</span></span>
<span class="line"></span>
<span class="line"><span class="nb-shiki-1itgoe">export</span><span class="nb-shiki-1itgoe"> default</span><span class="nb-shiki-140thh"> {</span></span>
<span class="line"><span class="nb-shiki-1t8gfj">	fetch</span><span class="nb-shiki-140thh">()</span><span class="nb-shiki-1itgoe">:</span><span class="nb-shiki-1t8gfj"> Response</span><span class="nb-shiki-140thh"> {</span></span>
<span class="line"><span class="nb-shiki-1itgoe">		return</span><span class="nb-shiki-140thh"> tracing.</span><span class="nb-shiki-1t8gfj">startActiveSpan</span><span class="nb-shiki-140thh">(</span><span class="nb-shiki-mdbnqw">"stream-response"</span><span class="nb-shiki-140thh">, (</span><span class="nb-shiki-1jdh33">span</span><span class="nb-shiki-140thh">) </span><span class="nb-shiki-1itgoe">=></span><span class="nb-shiki-140thh"> {</span></span>
<span class="line"><span class="nb-shiki-1itgoe">			let</span><span class="nb-shiki-140thh"> timer</span><span class="nb-shiki-1itgoe">:</span><span class="nb-shiki-1t8gfj"> ReturnType</span><span class="nb-shiki-140thh"><</span><span class="nb-shiki-1itgoe">typeof</span><span class="nb-shiki-140thh"> setTimeout> </span><span class="nb-shiki-1itgoe">|</span><span class="nb-shiki-dzsirb"> undefined</span><span class="nb-shiki-140thh">;</span></span>
<span class="line"></span>
<span class="line"><span class="nb-shiki-1itgoe">			const</span><span class="nb-shiki-dzsirb"> body</span><span class="nb-shiki-1itgoe"> =</span><span class="nb-shiki-1itgoe"> new</span><span class="nb-shiki-1t8gfj"> ReadableStream</span><span class="nb-shiki-140thh"><</span><span class="nb-shiki-1t8gfj">Uint8Array</span><span class="nb-shiki-140thh">>({</span></span>
<span class="line"><span class="nb-shiki-1t8gfj">				start</span><span class="nb-shiki-140thh">(</span><span class="nb-shiki-1jdh33">controller</span><span class="nb-shiki-140thh">) {</span></span>
<span class="line"><span class="nb-shiki-140thh">					controller.</span><span class="nb-shiki-1t8gfj">enqueue</span><span class="nb-shiki-140thh">(encoder.</span><span class="nb-shiki-1t8gfj">encode</span><span class="nb-shiki-140thh">(</span><span class="nb-shiki-mdbnqw">"Starting...</span><span class="nb-shiki-dzsirb">\n</span><span class="nb-shiki-mdbnqw">"</span><span class="nb-shiki-140thh">));</span></span>
<span class="line"></span>
<span class="line"><span class="nb-shiki-140thh">					timer </span><span class="nb-shiki-1itgoe">=</span><span class="nb-shiki-1t8gfj"> setTimeout</span><span class="nb-shiki-140thh">(() </span><span class="nb-shiki-1itgoe">=></span><span class="nb-shiki-140thh"> {</span></span>
<span class="line"><span class="nb-shiki-140thh">						controller.</span><span class="nb-shiki-1t8gfj">enqueue</span><span class="nb-shiki-140thh">(encoder.</span><span class="nb-shiki-1t8gfj">encode</span><span class="nb-shiki-140thh">(</span><span class="nb-shiki-mdbnqw">"Complete.</span><span class="nb-shiki-dzsirb">\n</span><span class="nb-shiki-mdbnqw">"</span><span class="nb-shiki-140thh">));</span></span>
<span class="line"><span class="nb-shiki-140thh">						controller.</span><span class="nb-shiki-1t8gfj">close</span><span class="nb-shiki-140thh">();</span></span>
<span class="line"></span>
<span class="line"><span class="nb-shiki-140thh">						span.</span><span class="nb-shiki-1t8gfj">setAttribute</span><span class="nb-shiki-140thh">(</span><span class="nb-shiki-mdbnqw">"stream.status"</span><span class="nb-shiki-140thh">, </span><span class="nb-shiki-mdbnqw">"complete"</span><span class="nb-shiki-140thh">);</span></span>
<span class="line"><span class="nb-shiki-140thh">						span.</span><span class="nb-shiki-1t8gfj">end</span><span class="nb-shiki-140thh">();</span></span>
<span class="line"><span class="nb-shiki-140thh">					}, </span><span class="nb-shiki-dzsirb">1000</span><span class="nb-shiki-140thh">);</span></span>
<span class="line"><span class="nb-shiki-140thh">				},</span></span>
<span class="line"></span>
<span class="line"><span class="nb-shiki-1t8gfj">				cancel</span><span class="nb-shiki-140thh">() {</span></span>
<span class="line"><span class="nb-shiki-1itgoe">					if</span><span class="nb-shiki-140thh"> (timer </span><span class="nb-shiki-1itgoe">!==</span><span class="nb-shiki-dzsirb"> undefined</span><span class="nb-shiki-140thh">) </span><span class="nb-shiki-1t8gfj">clearTimeout</span><span class="nb-shiki-140thh">(timer);</span></span>
<span class="line"></span>
<span class="line"><span class="nb-shiki-140thh">					span.</span><span class="nb-shiki-1t8gfj">setAttribute</span><span class="nb-shiki-140thh">(</span><span class="nb-shiki-mdbnqw">"stream.status"</span><span class="nb-shiki-140thh">, </span><span class="nb-shiki-mdbnqw">"cancelled"</span><span class="nb-shiki-140thh">);</span></span>
<span class="line"><span class="nb-shiki-140thh">					span.</span><span class="nb-shiki-1t8gfj">end</span><span class="nb-shiki-140thh">();</span></span>
<span class="line"><span class="nb-shiki-140thh">				},</span></span>
<span class="line"><span class="nb-shiki-140thh">			});</span></span>
<span class="line"></span>
<span class="line"><span class="nb-shiki-1itgoe">			return</span><span class="nb-shiki-1itgoe"> new</span><span class="nb-shiki-1t8gfj"> Response</span><span class="nb-shiki-140thh">(body, {</span></span>
<span class="line"><span class="nb-shiki-140thh">				headers: { </span><span class="nb-shiki-mdbnqw">"content-type"</span><span class="nb-shiki-140thh">: </span><span class="nb-shiki-mdbnqw">"text/plain"</span><span class="nb-shiki-140thh"> },</span></span>
<span class="line"><span class="nb-shiki-140thh">			});</span></span>
<span class="line"><span class="nb-shiki-140thh">		});</span></span>
<span class="line"><span class="nb-shiki-140thh">	},</span></span>
<span class="line"><span class="nb-shiki-140thh">};</span></span>

For more details, refer to the custom spans documentation.

Fetched July 29, 2026