14
14
* limitations under the License.
15
15
*/
16
16
17
+ import * as uuid from 'uuid' ;
17
18
import * as logger from '../../common/console-logger' ;
18
19
import * as loggerTypes from '../../common/types' ;
19
20
import * as cls from '../../internal/cls' ;
@@ -22,12 +23,10 @@ import {TraceParams} from '../config/types';
22
23
import { Propagation } from '../propagation/types' ;
23
24
import { SamplerBuilder , TraceParamsBuilder } from '../sampler/sampler' ;
24
25
import * as samplerTypes from '../sampler/types' ;
25
-
26
26
import { NoRecordRootSpan } from './no-record/no-record-root-span' ;
27
27
import { RootSpan } from './root-span' ;
28
28
import * as types from './types' ;
29
29
30
-
31
30
/**
32
31
* This class represent a tracer.
33
32
*/
@@ -125,35 +124,39 @@ export class CoreTracer implements types.Tracer {
125
124
startRootSpan < T > (
126
125
options : types . TraceOptions , fn : ( root : types . RootSpan ) => T ) : T {
127
126
return this . contextManager . runAndReturn ( ( root ) => {
128
- if ( this . active ) {
129
- let propagatedSample = null ;
130
-
131
- // if there is a context propagation, keep the decision
132
- if ( options && options . spanContext ) {
133
- if ( options . spanContext . options ) {
134
- propagatedSample =
135
- ( ( options . spanContext . options & this . IS_SAMPLED ) !== 0 ) ;
136
- }
137
- if ( ! propagatedSample ) {
138
- options . spanContext = null ;
139
- }
140
- }
141
- const aRoot = new RootSpan ( this , options ) ;
127
+ let traceId ;
128
+ if ( options && options . spanContext && options . spanContext . traceId ) {
129
+ traceId = options . spanContext . traceId ;
130
+ } else {
131
+ // New root span.
132
+ traceId = uuid . v4 ( ) . split ( '-' ) . join ( '' ) ;
133
+ }
134
+ const name = options && options . name ? options . name : 'span' ;
135
+ const kind =
136
+ options && options . kind ? options . kind : types . SpanKind . UNSPECIFIED ;
142
137
143
- let sampleDecision : boolean = propagatedSample ;
144
- if ( ! sampleDecision ) {
145
- sampleDecision = this . sampler . shouldSample ( aRoot . traceId ) ;
146
- }
138
+ let parentSpanId = '' ;
139
+ let traceState ;
140
+ if ( options && options . spanContext ) {
141
+ // New child span.
142
+ parentSpanId = options . spanContext . spanId || '' ;
143
+ traceState = options . spanContext . traceState ;
144
+ }
147
145
146
+ if ( this . active ) {
147
+ const sampleDecision = this . makeSamplingDecision ( options , traceId ) ;
148
148
if ( sampleDecision ) {
149
- this . currentRootSpan = aRoot ;
150
- aRoot . start ( ) ;
151
- return fn ( aRoot ) ;
149
+ const rootSpan =
150
+ new RootSpan ( this , name , kind , traceId , parentSpanId , traceState ) ;
151
+ this . currentRootSpan = rootSpan ;
152
+ rootSpan . start ( ) ;
153
+ return fn ( rootSpan ) ;
152
154
}
153
155
} else {
154
156
this . logger . debug ( 'Tracer is inactive, can\'t start new RootSpan' ) ;
155
157
}
156
- const noRecordRootSpan = new NoRecordRootSpan ( this , options ) ;
158
+ const noRecordRootSpan = new NoRecordRootSpan (
159
+ this , name , kind , traceId , parentSpanId , traceState ) ;
157
160
this . currentRootSpan = noRecordRootSpan ;
158
161
return fn ( noRecordRootSpan ) ;
159
162
} ) ;
@@ -283,4 +286,28 @@ export class CoreTracer implements types.Tracer {
283
286
const namespace = this . contextManager ;
284
287
namespace . bindEmitter ( emitter ) ;
285
288
}
289
+
290
+ /** Determine whether to sample request or not. */
291
+ private makeSamplingDecision ( options : types . TraceOptions , traceId : string ) :
292
+ boolean {
293
+ // If users set a specific sampler in the TraceOptions, use it.
294
+ if ( options && options . samplingRate !== undefined &&
295
+ options . samplingRate !== null ) {
296
+ return SamplerBuilder . getSampler ( options . samplingRate )
297
+ . shouldSample ( traceId ) ;
298
+ }
299
+ let propagatedSample = null ;
300
+ // if there is a context propagation, keep the decision
301
+ if ( options && options . spanContext && options . spanContext . options ) {
302
+ propagatedSample =
303
+ ( ( options . spanContext . options & this . IS_SAMPLED ) !== 0 ) ;
304
+ }
305
+
306
+ let sampleDecision : boolean = propagatedSample ;
307
+ if ( ! sampleDecision ) {
308
+ // Use the default global sampler
309
+ sampleDecision = this . sampler . shouldSample ( traceId ) ;
310
+ }
311
+ return sampleDecision ;
312
+ }
286
313
}
0 commit comments