import { channel , IModulePatcher , PatchFunction } from "diagnostic-channel" ; export interface IWinstonData { message : string | Error ; meta : any ; level : string ; levelKind : string ; } const winston2PatchFunction = ( originalWinston ) => { const originalLog = originalWinston . Logger . prototype . log ; let curLevels ; const loggingFilter = ( level , message , meta ) => { let levelKind ; if ( curLevels === originalWinston . config . npm . levels ) { levelKind = "npm" ; } else if ( curLevels === originalWinston . config . syslog . levels ) { levelKind = "syslog" ; } else { levelKind = "unknown" ; } channel . publish < IWinstonData > ( "winston" , { level , message , meta , levelKind } ) ; return message ; } ; originalWinston . Logger . prototype . log = function log ( ) { curLevels = this . levels ; if ( ! this . filters || this . filters . length === 0 ) { this . filters = [ loggingFilter ] ; } else if ( this . filters [ this . filters . length - 1 ] !== loggingFilter ) { this . filters = this . filters . filter ( ( f ) => f !== loggingFilter ) ; this . filters . push ( loggingFilter ) ; } return originalLog . apply ( this , arguments ) ; } ; return originalWinston ; } ; const winston3PatchFunction = ( originalWinston ) => { const mapLevelToKind = ( winston , level ) => { let levelKind ; if ( winston . config . npm . levels [ level ] != null ) { levelKind = "npm" ; } else if ( winston . config . syslog . levels [ level ] != null ) { levelKind = "syslog" ; } else { levelKind = "unknown" ; } return levelKind ; } ; class AppInsightsTransport extends originalWinston . Transport { private winston ; constructor ( winston , opts ? ) { super ( opts ) ; this . winston = winston ; } public log ( info , callback ) { let { message , level , meta , ... splat } = info ; level = typeof Symbol [ "for" ] === "function" ? info [ Symbol [ "for" ] ( "level" ) ] : level ; message = info instanceof Error ? info : message ; const levelKind = mapLevelToKind ( this . winston , level ) ; meta = meta || { } ; for ( const key in splat ) { if ( splat . hasOwnProperty ( key ) ) { meta [ key ] = splat [ key ] ; } } channel . publish < IWinstonData > ( "winston" , { message , level , levelKind , meta } ) ; callback ( ) ; } } function patchedConfigure ( ) { const levels = arguments [ 0 ] . levels || originalWinston . config . npm . levels ; let lastLevel ; for ( const level in levels ) { if ( levels . hasOwnProperty ( level ) ) { lastLevel = lastLevel === undefined || levels [ level ] > levels [ lastLevel ] ? level : lastLevel ; } } this . add ( new AppInsightsTransport ( originalWinston , { level : lastLevel } ) ) ; } const origCreate = originalWinston . createLogger ; originalWinston . createLogger = function patchedCreate ( ) { const levels = arguments [ 0 ] . levels || originalWinston . config . npm . levels ; let lastLevel ; for ( const level in levels ) { if ( levels . hasOwnProperty ( level ) ) { lastLevel = lastLevel === undefined || levels [ level ] > levels [ lastLevel ] ? level : lastLevel ; } } const result = origCreate . apply ( this , arguments ) ; result . add ( new AppInsightsTransport ( originalWinston , { level : lastLevel } ) ) ; const origConfigure = result . configure ; result . configure = function ( ) { origConfigure . apply ( this , arguments ) ; patchedConfigure . apply ( this , arguments ) ; } ; return result ; } ; const origRootConfigure = originalWinston . configure ; originalWinston . configure = function ( ) { origRootConfigure . apply ( this , arguments ) ; patchedConfigure . apply ( this , arguments ) ; } ; originalWinston . add ( new AppInsightsTransport ( originalWinston ) ) ; return originalWinston ; } ; export const winston3 = { versionSpecifier : "3.x" , patch : winston3PatchFunction , } ; export const winston2 = { versionSpecifier : "2.x" , patch : winston2PatchFunction , } ; export function enable ( ) { channel . registerMonkeyPatch ( "winston" , winston2 ) ; channel . registerMonkeyPatch ( "winston" , winston3 ) ; }