nl_tokens: Print out a single result considering input options .
pl_tokens: function emitRecord ( rec , line , opts , stylize ) { var short = false ; switch ( opts . outputMode ) { case OM_SHORT : short = true ; /* jsl:fall-thru */ case OM_LONG : //    [time] LEVEL: name[/comp]/pid on hostname (src): msg* (extras...) //        msg* //        -- //        long and multi-line extras //        ... // If 'msg' is single-line, then it goes in the top line. // If 'req', show the request. // If 'res', show the response. // If 'err' and 'err.stack' then show that. if ( ! isValidRecord ( rec ) ) { return emit ( line + '\n' ) ; } delete rec . v ; // Time. var time ; if ( ! short && opts . timeFormat === TIME_UTC ) { // Fast default path: We assume the raw `rec.time` is a UTC time // in ISO 8601 format (per spec). time = '[' + rec . time + ']' ; } else if ( ! moment && opts . timeFormat === TIME_UTC ) { // Don't require momentjs install, as long as not using TIME_LOCAL. time = rec . time . substr ( 11 ) ; } else { var tzFormat ; var moTime = moment ( rec . time ) ; switch ( opts . timeFormat ) { case TIME_UTC : tzFormat = TIMEZONE_UTC_FORMATS [ short ? 'short' : 'long' ] ; moTime . utc ( ) ; break ; case TIME_LOCAL : tzFormat = TIMEZONE_LOCAL_FORMATS [ short ? 'short' : 'long' ] ; break ; default : throw new Error ( 'unexpected timeFormat: ' + opts . timeFormat ) ; } ; time = moTime . format ( tzFormat ) ; } time = stylize ( <mask> , 'none' ) ; delete rec . time ; var nameStr = rec . name ; delete rec . name ; if ( rec . component ) { nameStr += '/' + rec . component ; } delete rec . component ; if ( ! short ) nameStr += '/' + rec . pid ; delete rec . pid ; var level = ( upperPaddedNameFromLevel [ rec . level ] || 'LVL' + rec . level ) ; if ( opts . color ) { var colorFromLevel = { 10 : 'white' , // TRACE 20 : 'yellow' , // DEBUG 30 : 'cyan' , // INFO 40 : 'magenta' , // WARN 50 : 'red' , // ERROR 60 : 'inverse' , // FATAL } ; level = stylize ( level , colorFromLevel [ rec . level ] ) ; } delete rec . level ; var src = '' ; if ( rec . src && rec . src . file ) { var s = rec . src ; if ( s . func ) { src = format ( ' (%s:%d in %s)' , s . file , s . line , s . func ) ; } else { src = format ( ' (%s:%d)' , s . file , s . line ) ; } src = stylize ( src , 'green' ) ; } delete rec . src ; var hostname = rec . hostname ; delete rec . hostname ; var extras = [ ] ; var details = [ ] ; if ( rec . req_id ) { extras . push ( 'req_id=' + rec . req_id ) ; } delete rec . req_id ; var onelineMsg ; if ( rec . msg . indexOf ( '\n' ) !== - 1 ) { onelineMsg = '' ; details . push ( indent ( stylize ( rec . msg , 'cyan' ) ) ) ; } else { onelineMsg = ' ' + stylize ( rec . msg , 'cyan' ) ; } delete rec . msg ; if ( rec . req && typeof ( rec . req ) === 'object' ) { var req = rec . req ; delete rec . req ; var headers = req . headers ; if ( ! headers ) { headers = '' ; } else if ( typeof ( headers ) === 'string' ) { headers = '\n' + headers ; } else if ( typeof ( headers ) === 'object' ) { headers = '\n' + Object . keys ( headers ) . map ( function ( h ) { return h + ': ' + headers [ h ] ; } ) . join ( '\n' ) ; } var s = format ( '%s %s HTTP/%s%s' , req . method , req . url , req . httpVersion || '1.1' , headers ) ; delete req . url ; delete req . method ; delete req . httpVersion ; delete req . headers ; if ( req . body ) { s += '\n\n' + ( typeof ( req . body ) === 'object' ? JSON . stringify ( req . body , null , 2 ) : req . body ) ; delete req . body ; } if ( req . trailers && Object . keys ( req . trailers ) > 0 ) { s += '\n' + Object . keys ( req . trailers ) . map ( function ( t ) { return t + ': ' + req . trailers [ t ] ; } ) . join ( '\n' ) ; } delete req . trailers ; details . push ( indent ( s ) ) ; // E.g. for extra 'foo' field on 'req', add 'req.foo' at // top-level. This *does* have the potential to stomp on a // literal 'req.foo' key. Object . keys ( req ) . forEach ( function ( k ) { rec [ 'req.' + k ] = req [ k ] ; } ) } /*
           * `client_req` is the typical field name for an *HTTP client request
           * object* serialized by the restify-clients library. Render the
           * client request somewhat like `curl` debug output shows it.
           */ if ( rec . client_req && typeof ( rec . client_req ) === 'object' ) { var client_req = rec . client_req ; delete rec . client_req ; var headers = client_req . headers ; delete client_req . headers ; /*
               * `client_req.address`, and `client_req.port`, provide values for
               * a *likely* "Host" header that wasn't included in the serialized
               * headers. Node.js will often add this "Host" header in its
               * `http.ClientRequest`, e.g. for node v6.10.3:
               *      // JSSTYLED
               *      https://github.com/nodejs/node/blob/v6.10.3/lib/_http_client.js#L88-L105
               *
               * If `client_req.port` exists and is 80 or 443, we *assume* that
               * is the default protocol port, and elide it per the `defaultPort`
               * handling in the node.js link above.
               *
               * Note: This added Host header is a *guess*. Bunyan shouldn't be
               * doing this "favour" for users because it can be wrong and
               * misleading. Bunyan 2.x will drop adding this. See issue #504
               * for details.
               */ var hostHeaderLine = '' ; if ( ! headers || ! ( Object . hasOwnProperty . call ( headers , 'host' ) || Object . hasOwnProperty . call ( headers , 'Host' ) || Object . hasOwnProperty . call ( headers , 'HOST' ) ) ) { if ( Object . hasOwnProperty . call ( client_req , 'address' ) ) { hostHeaderLine = '\nHost: ' + client_req . address ; if ( Object . hasOwnProperty . call ( client_req , 'port' ) ) { // XXX var port = + client_req . port ; if ( port !== 80 && port !== 443 ) { hostHeaderLine += ':' + client_req . port ; } delete client_req . port ; } delete client_req . address ; } } var s = format ( '%s %s HTTP/%s%s%s' , client_req . method , client_req . url , client_req . httpVersion || '1.1' , hostHeaderLine , ( headers ? '\n' + Object . keys ( headers ) . map ( function ( h ) { return h + ': ' + headers [ h ] ; } ) . join ( '\n' ) : '' ) ) ; delete client_req . method ; delete client_req . url ; delete client_req . httpVersion ; if ( client_req . body ) { s += '\n\n' + ( typeof ( client_req . body ) === 'object' ? JSON . stringify ( client_req . body , null , 2 ) : client_req . body ) ; delete client_req . body ; } // E.g. for extra 'foo' field on 'client_req', add // 'client_req.foo' at top-level. This *does* have the potential // to stomp on a literal 'client_req.foo' key. Object . keys ( client_req ) . forEach ( function ( k ) { rec [ 'client_req.' + k ] = client_req [ k ] ; } ) details . push ( indent ( s ) ) ; } function _res ( res ) { var s = '' ; /*
               * Handle `res.header` or `res.headers` as either a string or
               * an object of header key/value pairs. Prefer `res.header` if set,
               * because that's what Bunyan's own `res` serializer specifies,
               * because that's the value in Node.js's core HTTP server response
               * implementation that has all the implicit headers.
               *
               * Note: `res.header` (string) typically includes the 'HTTP/1.1 ...'
               * status line.
               */ var headerTypes = { string : true , object : true } ; var headers ; var headersStr = '' ; var headersHaveStatusLine = false ; if ( res . header && headerTypes [ typeof ( res . header ) ] ) { headers = res . header ; delete res . header ; } else if ( res . headers && headerTypes [ typeof ( res . headers ) ] ) { headers = res . headers ; delete res . headers ; } if ( headers === undefined ) { /* pass through */ } else if ( typeof ( headers ) === 'string' ) { headersStr = headers . trimRight ( ) ; // Trim the CRLF. if ( headersStr . slice ( 0 , 5 ) === 'HTTP/' ) { headersHaveStatusLine = true ; } } else { headersStr += Object . keys ( headers ) . map ( function ( h ) { return h + ': ' + headers [ h ] ; } ) . join ( '\n' ) ; } /*
               * Add a 'HTTP/1.1 ...' status line if the headers didn't already
               * include it.
               */ if ( ! headersHaveStatusLine && res . statusCode !== undefined ) { s += format ( 'HTTP/1.1 %s %s\n' , res . statusCode , http . STATUS_CODES [ res . statusCode ] ) ; } delete res . statusCode ; s += headersStr ; if ( res . body !== undefined ) { var body = ( typeof ( res . body ) === 'object' ? JSON . stringify ( res . body , null , 2 ) : res . body ) ; if ( body . length > 0 ) { s += '\n\n' + body } ; delete res . body ; } else { s = s . trimRight ( ) ; } if ( res . trailer ) { s += '\n' + res . trailer ; } delete res . trailer ; if ( s ) { details . push ( indent ( s ) ) ; } // E.g. for extra 'foo' field on 'res', add 'res.foo' at // top-level. This *does* have the potential to stomp on a // literal 'res.foo' key. Object . keys ( res ) . forEach ( function ( k ) { rec [ 'res.' + k ] = res [ k ] ; } ) ; } if ( rec . res && typeof ( rec . res ) === 'object' ) { _res ( rec . res ) ; delete rec . res ; } if ( rec . client_res && typeof ( rec . client_res ) === 'object' ) { _res ( rec . client_res ) ; delete rec . client_res ; } if ( rec . err && rec . err . stack ) { var err = rec . err if ( typeof ( err . stack ) !== 'string' ) { details . push ( indent ( err . stack . toString ( ) ) ) ; } else { details . push ( indent ( err . stack ) ) ; } delete err . message ; delete err . name ; delete err . stack ; // E.g. for extra 'foo' field on 'err', add 'err.foo' at // top-level. This *does* have the potential to stomp on a // literal 'err.foo' key. Object . keys ( err ) . forEach ( function ( k ) { rec [ 'err.' + k ] = err [ k ] ; } ) delete rec . err ; } var leftover = Object . keys ( rec ) ; for ( var i = 0 ; i < leftover . length ; i ++ ) { var key = leftover [ i ] ; var value = rec [ key ] ; var stringified = false ; if ( typeof ( value ) !== 'string' ) { value = JSON . stringify ( value , null , 2 ) ; stringified = true ; } if ( value . indexOf ( '\n' ) !== - 1 || value . length > 50 ) { details . push ( indent ( key + ': ' + value ) ) ; } else if ( ! stringified && ( value . indexOf ( ' ' ) != - 1 || value . length === 0 ) ) { extras . push ( key + '=' + JSON . stringify ( value ) ) ; } else { extras . push ( key + '=' + value ) ; } } extras = stylize ( ( extras . length ? ' (' + extras . join ( ', ' ) + ')' : '' ) , 'none' ) ; details = stylize ( ( details . length ? details . join ( '\n    --\n' ) + '\n' : '' ) , 'none' ) ; if ( ! short ) emit ( format ( '%s %s: %s on %s%s:%s%s\n%s' , time , level , nameStr , hostname || '<no-hostname>' , src , onelineMsg , extras , details ) ) ; else emit ( format ( '%s %s %s:%s%s\n%s' , time , level , nameStr , onelineMsg , extras , details ) ) ; break ; case OM_INSPECT : emit ( util . inspect ( rec , false , Infinity , true ) + '\n' ) ; break ; case OM_BUNYAN : emit ( JSON . stringify ( rec , null , 0 ) + '\n' ) ; break ; case OM_JSON : emit ( JSON . stringify ( rec , null , opts . jsonIndent ) + '\n' ) ; break ; case OM_SIMPLE : /* JSSTYLED */ // <http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/SimpleLayout.html> if ( ! isValidRecord ( rec ) ) { return emit ( line + '\n' ) ; } emit ( format ( '%s - %s\n' , upperNameFromLevel [ rec . level ] || 'LVL' + rec . level , rec . msg ) ) ; break ; default : throw new Error ( 'unknown output mode: ' + opts . outputMode ) ; } }