/**
 * Copyright 2018, OpenCensus Authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */ import * as cls from '../../internal/cls' ; import { NoRecordSpan } from './no-record/no-record-span' ; import { CoreTracerBase } from './tracer-base' ; import * as types from './types' ; /**
 * This class represents a tracer with Continuation Local Storage (CLS).
 *
 * CLS helps keep tracking the root span over function calls automatically.
 * It is capable of storing, propagating and retrieving arbitrary
 * continuation-local data (also called "context").
 * CLS comes with some performance overhead, you can read more about it here:
 * https://github.com/othiym23/node-continuation-local-storage/issues/59
 */ export class CoreTracer extends CoreTracerBase implements types . Tracer { /** Manage context automatic propagation */ private contextManager : cls . Namespace ; /** Constructs a new TraceImpl instance. */ constructor ( ) { super ( ) ; this . contextManager = cls . getNamespace ( ) ; this . clearCurrentTrace ( ) ; } /** Gets the current root span. */ get currentRootSpan ( ) : types . Span { return this . contextManager . get ( 'rootspan' ) ; } /** Sets the current root span. */ set currentRootSpan ( root ) { this . setCurrentRootSpan ( root ) ; } /** Sets the current root span. */ setCurrentRootSpan ( root ) { if ( this . contextManager . active ) { this . contextManager . set ( 'rootspan' , root ) ; } } param options param fn startRootSpan < T > ( options , fn ) { const self = this ; return self . contextManager . runAndReturn ( ( ) => { return super . startRootSpan ( options , root => { return fn ( root ) ; } ) ; } ) ; } /** Notifies listeners of the span start. */ onStartSpan ( span ) { if ( ! this . active ) return ; if ( ! this . currentRootSpan || this . currentRootSpan . traceId !== span . traceId ) { this . logger . debug ( 'currentRootSpan != root on notifyStart. Need more investigation.' ) ; } return super . onStartSpan ( span ) ; } /** Notifies listeners of the span end. */ onEndSpan ( span ) { if ( ! this . active ) return ; if ( ! this . currentRootSpan || this . currentRootSpan . traceId !== span . traceId ) { this . logger . debug ( 'currentRootSpan != root on notifyEnd. Need more investigation.' ) ; } super . onEndSpan ( span ) ; } /** Clears the current root span. */ clearCurrentTrace ( ) { if ( this . contextManager . active ) { this . contextManager . set ( 'rootspan' , null ) ; } } param options startChildSpan ( options ? ) { if ( ! this . currentRootSpan ) { this . logger . debug ( 'no current trace found - must start a new root span first' ) ; } return super . startChildSpan ( Object . assign ( { childOf : this . currentRootSpan || new NoRecordSpan ( this ) } , options ) ) ; } param fn wrap < T > ( fn ) { if ( ! this . active ) { return fn ; } const namespace = this . contextManager ; return namespace . bind < T > ( fn ) ; } param emitter wrapEmitter ( emitter ) { if ( ! this . active ) { return ; } const namespace = this . contextManager ; namespace . bindEmitter ( emitter ) ; } }