diff --git a/src/trace/context/ContextManager.ts b/src/trace/context/ContextManager.ts index a586856..ef21803 100644 --- a/src/trace/context/ContextManager.ts +++ b/src/trace/context/ContextManager.ts @@ -23,7 +23,7 @@ import SpanContext from '../../trace/context/SpanContext'; import async_hooks from 'async_hooks'; -type AsyncState = { context: Context, spans: Span[] }; +type AsyncState = { context: Context, spans: Span[], invalid: boolean }; let store: { getStore(): AsyncState | undefined; @@ -59,9 +59,9 @@ if (async_hooks.AsyncLocalStorage) { class ContextManager { get asyncState(): AsyncState { let asyncState = store.getStore(); - - if (asyncState === undefined) { - asyncState = { context: new SpanContext(), spans: [] }; + // since `AsyncLocalStorage.getStore` may get previous state, see issue https://github.com/nodejs/node/issues/35286#issuecomment-697207158, so recreate when asyncState is invalid + if (asyncState === undefined || asyncState.invalid) { + asyncState = { context: new SpanContext(), spans: [], invalid: false }; store.enterWith(asyncState); } @@ -79,10 +79,10 @@ class ContextManager { spansDup(): Span[] { let asyncState = store.getStore(); - if (asyncState === undefined) { - asyncState = { context: new SpanContext(), spans: [] }; + if (asyncState === undefined || asyncState.invalid) { + asyncState = { context: new SpanContext(), spans: [], invalid: false }; } else { - asyncState = { context: asyncState.context, spans: [...asyncState.spans] }; + asyncState = { context: asyncState.context, spans: [...asyncState.spans], invalid: asyncState.invalid }; } store.enterWith(asyncState); @@ -91,11 +91,12 @@ class ContextManager { } clear(): void { + this.asyncState.invalid = true; store.enterWith(undefined as unknown as AsyncState); } restore(context: Context, spans: Span[]): void { - store.enterWith({ context, spans: spans || [] }); + store.enterWith({ context, spans: spans || [], invalid: this.asyncState.invalid }); } withSpan(span: Span, callback: (...args: any[]) => any, ...args: any[]): any {