11import type { Attributes , Context , TextMapGetter } from '@opentelemetry/api'
2- import { diag , SpanKind } from '@opentelemetry/api'
2+ import { diag , SpanKind , TraceFlags } from '@opentelemetry/api'
33import type {
44 ReadableSpan ,
55 Span ,
66 SpanProcessor ,
77} from '@opentelemetry/sdk-trace-base'
8-
9- import { TraceFlags } from '@opentelemetry/api'
8+ import { after } from 'next/server'
109
1110type AttributesFromHeaderFunc = < Carrier = unknown > (
1211 headers : Carrier ,
@@ -15,41 +14,6 @@ type AttributesFromHeaderFunc = <Carrier = unknown>(
1514
1615type AttributesFromHeaders = Record < string , string > | AttributesFromHeaderFunc
1716
18- /**
19- * Helper ────────────────────────────────────────────────────────────────────
20- * Try to obtain the callback that extends the lifetime of the request so that
21- * our exporter has time to flush.
22- *
23- * Priority:
24- * 1. `after(cb)` (Next.js 15)
25- * 2. fallback (best-effort `setTimeout`)
26- */
27- function scheduleAfterResponse ( task : ( ) => Promise < void > ) {
28- try {
29- // avoid a hard dependency so this file can be imported outside a route.
30- // `require` is evaluated lazily – if Next isn't around it will throw.
31- // eslint-disable-next-line
32- const mod = require ( 'next/server' ) as { after ?: ( cb : ( ) => void ) => void }
33-
34- if ( typeof mod . after === 'function' ) {
35- mod . after ( ( ) => {
36- // no await – Next treats sync or async the same,
37- // we just fire the promise and let it resolve.
38- void task ( )
39- } )
40- return
41- }
42- } catch {
43- /* ignored – we're probably not inside a Next context */
44- }
45-
46- // 2. Node / local fallback – try our best and hope the
47- // process stays alive long enough.
48- setTimeout ( ( ) => {
49- void task ( )
50- } , 0 )
51- }
52-
5317function isSampled ( traceFlags : number ) : boolean {
5418 // Use bitwise AND to inspect the sampled flag
5519 return ( traceFlags & TraceFlags . SAMPLED ) !== 0
@@ -113,7 +77,7 @@ export class NextCompositeSpanProcessor implements SpanProcessor {
11377 // Attach request-specific attributes only on the root span
11478 if ( isRoot && isSampled ( traceFlags ) ) {
11579 // When the *response* (or prerender) is done, flush traces.
116- scheduleAfterResponse ( async ( ) => {
80+ after ( async ( ) => {
11781 if ( this . rootSpanIds . has ( traceId ) ) {
11882 // Root hasn’t finished yet – wait via onEnd().
11983 const waiter = new Promise < void > ( ( resolve ) =>
0 commit comments