'use strict' ; import { BasePlugin , Span , SpanKind } from '@opencensus/core' ; import * as shimmer from 'shimmer' ; import * as semver from 'semver' ; export type IgnoreMatcher = string | RegExp ; export type IORedisPluginConfig = { /**
     * Add arguments to the span metadata for a every command
     */ detailedCommands : boolean ; } ; export type IORedisCommand = { reject : ( err : Error ) => void | undefined ; resolve : ( result : any ) => void | undefined ; promise : Promise < any > ; args : Array < string | Buffer | number > ; callback : Function | undefined ; name : string ; } ; /** Redis instrumentation plugin for Opencensus */ export class IORedisPlugin extends BasePlugin { protected options : IORedisPluginConfig ; /** Constructs a new Redis instance. */ constructor ( moduleName ) { super ( moduleName ) ; } /**
     * Patches Redis operations.
     */ protected applyPatch ( ) { this . logger . debug ( 'Patched redis' ) ; if ( ! semver . satisfies ( this . version , '>=2.0.0 <5.0.0' ) ) { this . logger . info ( 'disabling ioredis plugin because version isnt supported' ) ; return this . moduleExports ; } if ( this . moduleExports ) { this . logger . debug ( 'patching ioredis.prototype.sendCommand' ) ; shimmer . wrap ( this . moduleExports . prototype , 'sendCommand' , this . getPatchSendCommand ( ) ) ; } return this . moduleExports ; } /** Unpatches all Redis patched functions. */ applyUnpatch ( ) { if ( ! semver . satisfies ( this . version , '>=2.0.0 <5.0.0' ) ) return ; shimmer . unwrap ( this . moduleExports . prototype , 'sendCommand' ) ; } /** Patch send command internal to trace requests */ private getPatchSendCommand ( ) { const plugin = this ; const addArguments = typeof this . options === 'object' && this . options . detailedCommands === true ; return function internalSendCommandWrap ( original ) { return function internal_send_command_trace ( command ) { if ( ! plugin . tracer . currentRootSpan ) { return original . apply ( this , arguments ) ; } const span = plugin . tracer . startChildSpan ( `redis-${ command . name }` , SpanKind . CLIENT ) ; if ( span === null ) return original . apply ( this , arguments ) ; span . addAttribute ( 'command' , command . name ) ; if ( addArguments ) { span . addAttribute ( 'arguments' , JSON . stringify ( command . args ) ) ; } if ( typeof command . reject === 'function' ) { command . reject = plugin . tracer . wrap ( command . reject ) ; } if ( typeof command . resolve === 'function' ) { command . resolve = plugin . tracer . wrap ( command . resolve ) ; } if ( typeof command . callback === 'function' ) { command . callback = plugin . patchEnd ( span , command . callback ) ; } if ( typeof command . promise === 'object' ) { const patchedEnd = function ( err ? ) { if ( plugin . options . detailedCommands === true && err instanceof Error ) { span . addAttribute ( 'error' , err . message ) ; } if ( span . ended === false ) { span . end ( ) ; } } ; if ( typeof command . promise . finally === 'function' ) { command . promise . finally ( patchedEnd ) ; } else if ( typeof command . promise . then === 'function' ) { command . promise . then ( patchedEnd ) . catch ( patchedEnd ) ; } } return original . apply ( this , arguments ) ; } ; } ; } param span param resultHandler patchEnd ( span , resultHandler ) { const plugin = this ; const patchedEnd = function ( err ? ) { if ( plugin . options . detailedCommands === true && err instanceof Error ) { span . addAttribute ( 'error' , err . message ) ; } if ( span . ended === false ) { span . end ( ) ; } return resultHandler . apply ( this , arguments ) ; } ; return this . tracer . wrap ( patchedEnd ) ; } } const plugin = new IORedisPlugin ( 'ioredis' ) ; export { plugin } ;