@@ -26,6 +26,8 @@ import {SpanDataType} from './constants';
2626import { Trace , TraceSpan } from './trace' ;
2727import { Singleton } from './util' ;
2828
29+ const asyncHooksAvailable = semver . satisfies ( process . version , '>=8' ) ;
30+
2931export interface RealRootContext {
3032 readonly span : TraceSpan ;
3133 readonly trace : Trace ;
@@ -48,11 +50,34 @@ export interface PhantomRootContext {
4850 */
4951export type RootContext = RealRootContext | PhantomRootContext ;
5052
51- const asyncHooksAvailable = semver . satisfies ( process . version , '>=8' ) ;
53+ /**
54+ * An enumeration of the possible mechanisms for supporting context propagation
55+ * through continuation-local storage.
56+ */
57+ export enum TraceCLSMechanism {
58+ /**
59+ * Use the AsyncHooksCLS class to propagate root span context.
60+ * Only available in Node 8+.
61+ */
62+ ASYNC_HOOKS = 'async-hooks' ,
63+ /**
64+ * Use the AsyncListenerCLS class to propagate root span context.
65+ * Note that continuation-local-storage should be loaded as the first module.
66+ */
67+ ASYNC_LISTENER = 'async-listener' ,
68+ /**
69+ * Do not use any special mechanism to propagate root span context.
70+ * Only a single root span can be open at a time.
71+ */
72+ NONE = 'none'
73+ }
5274
53- export interface TraceCLSConfig { mechanism : 'async-listener' | 'async-hooks' ; }
75+ /**
76+ * Configuration options passed to the TraceCLS constructor.
77+ */
78+ export interface TraceCLSConfig { mechanism : TraceCLSMechanism ; }
5479
55- export interface CLSConstructor {
80+ interface CLSConstructor {
5681 new ( defaultContext : RootContext ) : CLS < RootContext > ;
5782}
5883
@@ -80,30 +105,29 @@ export class TraceCLS implements CLS<RootContext> {
80105 readonly rootSpanStackOffset : number ;
81106
82107 constructor ( private readonly logger : Logger , config : TraceCLSConfig ) {
83- const useAH = config . mechanism === 'async-hooks' && asyncHooksAvailable ;
84- if ( useAH ) {
85- this . CLSClass = AsyncHooksCLS ;
86- this . rootSpanStackOffset = 4 ;
87- this . logger . info (
88- 'TraceCLS#constructor: Created [async-hooks] CLS instance.' ) ;
89- } else {
90- if ( config . mechanism !== 'async-listener' ) {
91- if ( config . mechanism === 'async-hooks' ) {
92- this . logger . error (
93- 'TraceCLS#constructor: [async-hooks]-based context' ,
94- `propagation is not available in Node ${ process . version } .` ) ;
95- } else {
96- this . logger . error (
97- 'TraceCLS#constructor: The specified CLS mechanism' ,
98- `[${ config . mechanism } ] was not recognized.` ) ;
108+ switch ( config . mechanism ) {
109+ case TraceCLSMechanism . ASYNC_HOOKS :
110+ if ( ! asyncHooksAvailable ) {
111+ throw new Error ( `CLS mechanism [${
112+ config . mechanism } ] is not compatible with Node <8.`) ;
99113 }
100- throw new Error ( `CLS mechanism [${ config . mechanism } ] is invalid.` ) ;
101- }
102- this . CLSClass = AsyncListenerCLS ;
103- this . rootSpanStackOffset = 8 ;
104- this . logger . info (
105- 'TraceCLS#constructor: Created [async-listener] CLS instance.' ) ;
114+ this . CLSClass = AsyncHooksCLS ;
115+ this . rootSpanStackOffset = 4 ;
116+ break ;
117+ case TraceCLSMechanism . ASYNC_LISTENER :
118+ this . CLSClass = AsyncListenerCLS ;
119+ this . rootSpanStackOffset = 8 ;
120+ break ;
121+ case TraceCLSMechanism . NONE :
122+ this . CLSClass = UniversalCLS ;
123+ this . rootSpanStackOffset = 4 ;
124+ break ;
125+ default :
126+ throw new Error (
127+ `CLS mechanism [${ config . mechanism } ] was not recognized.` ) ;
106128 }
129+ this . logger . info (
130+ `TraceCLS#constructor: Created [${ config . mechanism } ] CLS instance.` ) ;
107131 this . currentCLS = new UniversalCLS ( TraceCLS . UNTRACED ) ;
108132 this . currentCLS . enable ( ) ;
109133 }
0 commit comments