import { Context , trace , TextMapGetter , TextMapSetter , TextMapPropagator , } from '@opentelemetry/api' ; import { BinaryTraceContext } from './BinaryTraceContext' ; /** The metadata key under which span context is stored as a binary value. */ export const GRPC_TRACE_KEY = 'grpc-trace-bin' ; const VALID_TRACEID_REGEX = /^[0-9a-f]{32}$/i ; const VALID_SPANID_REGEX = /^[0-9a-f]{16}$/i ; const INVALID_ID_REGEX = /^0+$/i ; param traceId returns function isValidTraceId ( traceId ) { return VALID_TRACEID_REGEX . test ( traceId ) && ! INVALID_ID_REGEX . test ( traceId ) ; } param spanId returns function isValidSpanId ( spanId ) { return VALID_SPANID_REGEX . test ( spanId ) && ! INVALID_ID_REGEX . test ( spanId ) ; } /**
 * Propagator for the grpc-trace-bin header used by OpenCensus for
 * gRPC. Acts as a bridge between the TextMapPropagator interface and
 * the binary encoding/decoding that happens in the supporting
 * BinaryTraceContext class.
 */ export class GrpcCensusPropagator implements TextMapPropagator { param context param carrier param setter inject ( context , carrier , setter ) { const spanContext = trace . getSpan ( context ) ?. spanContext ( ) ; if ( ! spanContext ) return ; if ( isValidTraceId ( spanContext . traceId ) && isValidSpanId ( spanContext . spanId ) ) { if ( spanContext . traceFlags !== undefined ) { const encodedArray = BinaryTraceContext . toBytes ( spanContext ) ; const encodedContext = Buffer . from ( encodedArray . buffer ) ; if ( carrier && encodedContext ) { setter . set ( carrier , GRPC_TRACE_KEY , encodedContext as any ) ; } } } } param context param carrier param getter returns extract ( context , carrier , getter ) { if ( carrier ) { const values = getter . get ( carrier , GRPC_TRACE_KEY ) as unknown as Array < Buffer > ; const metadataValue = values . length > 0 ? values [ 0 ] : null ; if ( ! metadataValue ) { return context ; } else { const decodedContext = BinaryTraceContext . fromBytes ( metadataValue ) ; if ( decodedContext ) { const traceId = decodedContext . traceId ; const spanId = decodedContext . spanId ; if ( isValidTraceId ( traceId ) && isValidSpanId ( spanId ) ) { return trace . setSpan ( context , trace . wrapSpanContext ( { traceId , spanId , isRemote : true , traceFlags : decodedContext . traceFlags , } ) ) ; } return context ; } else { return context ; } } } return context ; } fields ( ) { return [ GRPC_TRACE_KEY ] ; } }