@@ -25,6 +25,7 @@ var os = require('os');
2525var fs = require ( 'fs' ) ;
2626var util = require ( 'util' ) ;
2727var assert = require ( 'assert' ) ;
28+ var dtrace = require ( 'dtrace-provider' ) ;
2829var EventEmitter = require ( 'events' ) . EventEmitter ;
2930
3031
@@ -156,6 +157,8 @@ var levelFromName = {
156157 'fatal' : FATAL
157158} ;
158159
160+ var dtp = undefined ;
161+ var probes = { } ;
159162
160163/**
161164 * Resolve a level number, name (upper or lowercase) to a level number value.
@@ -299,6 +302,22 @@ function Logger(options, _childOptions, _childSimple) {
299302 this . fields = { } ;
300303 }
301304
305+ if ( ! dtp ) {
306+ dtp = dtrace . createDTraceProvider ( 'bunyan' ) ;
307+
308+ for ( var level in levelFromName ) {
309+ var probe ;
310+
311+ probes [ levelFromName [ level ] ] = probe =
312+ dtp . addProbe ( 'log-' + level , 'char *' ) ;
313+
314+ // Explicitly add a reference to dtp to prevent it from being GC'd
315+ probe . dtp = dtp ;
316+ }
317+
318+ dtp . enable ( ) ;
319+ }
320+
302321 // Helpers
303322 function addStream ( s ) {
304323 s = objCopy ( s ) ;
@@ -641,8 +660,9 @@ Logger.prototype._mkRecord = function (fields, level, msgArgs) {
641660 * Emit a log record.
642661 *
643662 * @param rec {log record}
663+ * @param noemit {Boolean} Optional. Set to true to only return the string.
644664 */
645- Logger . prototype . _emit = function ( rec ) {
665+ Logger . prototype . _emit = function ( rec , noemit ) {
646666 var i ;
647667
648668 var obj = objCopy ( rec [ 0 ] ) ;
@@ -685,6 +705,9 @@ Logger.prototype._emit = function (rec) {
685705 str = JSON . stringify ( obj , safeCycles ( ) ) + '\n' ;
686706 }
687707
708+ if ( noemit )
709+ return str ;
710+
688711 for ( i = 0 ; i < this . streams . length ; i ++ ) {
689712 var s = this . streams [ i ] ;
690713 if ( s . level <= level ) {
@@ -693,6 +716,8 @@ Logger.prototype._emit = function (rec) {
693716 s . stream . write ( s . raw ? obj : str ) ;
694717 }
695718 } ;
719+
720+ return str ;
696721}
697722
698723
@@ -702,33 +727,50 @@ Logger.prototype._emit = function (rec) {
702727 */
703728function mkLogEmitter ( minLevel ) {
704729 return function ( ) {
730+ var log = this ;
731+
732+ var mkRecord = function ( args ) {
733+ if ( args [ 0 ] instanceof Error ) {
734+ // `log.<level>(err, ...)`
735+ fields = { err : errSerializer ( args [ 0 ] ) } ;
736+ if ( args . length === 1 ) {
737+ msgArgs = [ fields . err . message ] ;
738+ } else {
739+ msgArgs = Array . prototype . slice . call ( args , 1 ) ;
740+ }
741+ } else if ( typeof ( args [ 0 ] ) === 'string' ) { // `log.<level>(msg, ...)`
742+ fields = null ;
743+ msgArgs = Array . prototype . slice . call ( args ) ;
744+ } else if ( Buffer . isBuffer ( args [ 0 ] ) ) { // `log.<level>(buf, ...)`
745+ // Almost certainly an error, show `inspect(buf)`. See bunyan issue #35.
746+ fields = null ;
747+ msgArgs = Array . prototype . slice . call ( args ) ;
748+ msgArgs [ 0 ] = util . inspect ( msgArgs [ 0 ] ) ;
749+ } else { // `log.<level>(fields, msg, ...)`
750+ fields = args [ 0 ] ;
751+ msgArgs = Array . prototype . slice . call ( args , 1 ) ;
752+ }
753+ return log . _mkRecord ( fields , minLevel , msgArgs ) ;
754+ } ;
755+
705756 var fields = null , msgArgs = null ;
706757 if ( arguments . length === 0 ) { // `log.<level>()`
707758 return ( this . _level <= minLevel ) ;
708759 } else if ( this . _level > minLevel ) {
709- return ;
710- } else if ( arguments [ 0 ] instanceof Error ) {
711- // `log.<level>(err, ...)`
712- fields = { err : errSerializer ( arguments [ 0 ] ) } ;
713- if ( arguments . length === 1 ) {
714- msgArgs = [ fields . err . message ] ;
715- } else {
716- msgArgs = Array . prototype . slice . call ( arguments , 1 ) ;
717- }
718- } else if ( typeof ( arguments [ 0 ] ) === 'string' ) { // `log.<level>(msg, ...)`
719- fields = null ;
720- msgArgs = Array . prototype . slice . call ( arguments ) ;
721- } else if ( Buffer . isBuffer ( arguments [ 0 ] ) ) { // `log.<level>(buf, ...)`
722- // Almost certainly an error, show `inspect(buf)`. See bunyan issue #35.
723- fields = null ;
724- msgArgs = Array . prototype . slice . call ( arguments ) ;
725- msgArgs [ 0 ] = util . inspect ( msgArgs [ 0 ] ) ;
726- } else { // `log.<level>(fields, msg, ...)`
727- fields = arguments [ 0 ] ;
728- msgArgs = Array . prototype . slice . call ( arguments , 1 ) ;
760+ /*
761+ * Even if our level is such that we will not emit the record, we want
762+ * to fire the DTrace probe associated with the level -- but we only
763+ * assemble the string representation if the probe is in fact enabled.
764+ */
765+ msgArgs = arguments ;
766+
767+ probes [ minLevel ] . fire ( function ( ) {
768+ return [ log . _emit ( mkRecord ( msgArgs ) , true ) ] ;
769+ } ) ;
770+ } else {
771+ var str = this . _emit ( mkRecord ( arguments ) ) ;
772+ probes [ minLevel ] . fire ( function ( ) { return [ str ] ; } ) ;
729773 }
730- var rec = this . _mkRecord ( fields , minLevel , msgArgs ) ;
731- this . _emit ( rec ) ;
732774 }
733775}
734776
0 commit comments