import { IRequestHeaders , LogFunction } from '@creditkarma/thrift-server-core' ; import { BatchRecorder , ConsoleRecorder , Context , ExplicitContext , JsonEncoder , jsonEncoder , Recorder , sampler , TraceId , Tracer , } from 'zipkin' ; import { ZipkinHeaders } from './constants' ; import { HttpLogger } from 'zipkin-transport-http' ; import { IZipkinTracerConfig } from './types' ; class MaybeMap < K , V > extends Map < K , V > { public getOrElse ( key , orElse ) { const value = this . get ( key ) ; if ( value === undefined ) { const newValue = orElse ( ) ; this . set ( key , newValue ) ; return newValue ; } else { return value ; } } } interface IHttpLoggerOptions { endpoint : string ; httpInterval ? : number ; httpTimeout ? : number ; headers ? : IRequestHeaders ; jsonEncoder ? : JsonEncoder ; } const TRACER_CACHE = new MaybeMap ( ) ; /**
 * `http://localhost:9411/api/v1/spans`
 */ function recorderForOptions ( options ) { if ( options . endpoint !== undefined ) { const httpOptions = { endpoint : options . endpoint , headers : options . headers , httpInterval : options . httpInterval , httpTimeout : options . httpTimeout , jsonEncoder : options . zipkinVersion === 'v2' ? jsonEncoder . JSON_V2 : jsonEncoder . JSON_V1 , } ; const logger = options . logger ; const httpLogger = new HttpLogger ( httpOptions ) ; if ( logger !== undefined ) { httpLogger . on ( 'error' , ( err ) => { logger ( [ 'error' , 'zipkin' , 'recorderForOptions' ] , `An error occurred sending trace: ${ err . message }` ) ; } ) ; httpLogger . on ( 'success' , ( ) => { logger ( [ 'debug' , 'zipkin' ] , `Zipkin trace sent successfully` ) ; } ) ; } return new BatchRecorder ( { logger : httpLogger } ) ; } else { return new ConsoleRecorder ( ) ; } } interface IHeaderMap { [ name ] : string ; } export function getHeadersForTraceId ( traceId ? ) { if ( traceId !== null && traceId !== undefined ) { const headers = { } ; headers [ ZipkinHeaders . TraceId ] = traceId . traceId ; headers [ ZipkinHeaders . SpanId ] = traceId . spanId ; headers [ ZipkinHeaders . ParentId ] = traceId . parentId || '' ; traceId . sampled . ifPresent ( ( sampled ) => { headers [ ZipkinHeaders . Sampled ] = sampled ? '1' : '0' ; } ) ; return headers ; } else { return { } ; } } export function getTracerForService ( serviceName , options = { } ) { return TRACER_CACHE . getOrElse ( serviceName , ( ) => { const ctxImpl = new ExplicitContext ( ) ; const recorder = recorderForOptions ( options ) ; return new Tracer ( { ctxImpl , recorder , sampler : new sampler . CountingSampler ( options . debug ? 100 : options . sampleRate !== undefined ? options . sampleRate : 0.1 ) , localServiceName : serviceName , } ) ; } ) ; }