2013-11-24 1 views
1

로거에서 winston을 사용하여 로깅 할 때 타임 스탬프와 줄 번호를 추가 할 수 있습니다. 코드는 각각 기능을 수행 할 수 있지만 결합하면 예상대로 작동하지 않습니다.로깅을 위해 node.js winston에 회선 번호 구성을 추가하면 타임 스탬프가 사라집니다.

// **help to add timestamp** 
var logger = new (winston.Logger)({ 
    transports : [new (winston.transports.Console)({ 
    json : false, 
    timestamp : true, 
    colorize: true 
    }), new winston.transports.File({ 
    filename : __dirname + '/debug.log', 
    json : true 
    })] 
    ,exitOnError : false 
}); 

// **help me to add line number** 
var logger_info_old = winston.info; 
logger.info = function(msg) { 
    var fileAndLine = traceCaller(1); 
    return logger_info_old.call(this, fileAndLine + ":" + msg); 
} 

그러나 줄 번호 구성을 추가하면 로깅을위한 타임 스탬프가 사라집니다.

예를 들어, 줄 번호 구성을 추가하기 전에. 행 번호 설정을 추가 할 때

logger.info("abc"); 
2013-11-24T09:49:15.914Z - info:339:abc 

logger.info("abc"); 
info: (H:\Dropbox\node\fablab\utils\logging.js:85:abc 

내가 원하는 최적의 결과는

logger.info("abc"); 
2013-11-24T09:49:15.914Z - info: (H:\Dropbox\node\fablab\app.js:339:abc 

나는이 문제를 해결할 수처럼?

답변

3

나는 이것을 작동 시켰고 이것이 내가 그랬던 방법이다.

var transports = [ 
    new(winston.transports.Console)({ 
    colorize: true, 
    prettyPrint: true, 
    timestamp : true, 
    level: 'debug', 
    }) 
]; 

var log = new(winston.Logger)({ 
    "transports": transports 
}); 

for (var func in winston.levels) { 
    var oldFunc = log[func]; 

    log[func] = function() { 
    var args = Array.prototype.slice.call(arguments); 
    args.unshift(traceCaller(1)); 
    oldFunc.apply(log, args); 
    } 
} 

나는 타임 스탬프와 파일을 모두 가지고 있습니다. (참고 traceCaller (1)이 stackoverflow 질문에서 : I want to display the file Name in the log statement). winston.levels를 통해 for 루프를 수행 했으므로 모든 정보가 정보가 아닌 픽업됩니다.

귀하의 logger_info_old는 로거가 아닌 winston에서 가져온 것입니다. 그래서

var logger_info_old = winston.info; 

var logger_info_old = logger.info; 
+0

벤치 마크를 수행했습니다. 스택 추적을 추가하는 것이 훨씬 더 느립니다. 10,000 로그를하는 것은 파일과 라인 번호가없는 71ms에서 4666ms로 갔다. 그것은 65 배 더 느립니다. traceCaller는 비효율적 일지 모르지만 대부분의 경우 스택 추적을 생성하는 데 실제로 사용됩니다. (새로운 오류) .stack –

+0

동의하지만 traceCaller는 비효율적이지만 디버그에 사용되므로 괜찮습니다. 고마워, jeff – user824624

+0

'oldFunc'을 포착 할 클로저가 있어야합니다. 그렇지 않으면 모든 로그 함수가 마지막 설정으로 대체됩니다 (기본 설정에서는'error()'). 또한, 왜'logger.levels' 대신'winston.levels'을 사용하고 있습니까? – leesei

3

나는 제프 - 호분의 대답 @ 업데이트 (사용 폐쇄 및 문자열 보간 수정)과 하나의 함수 만들기를하고 있어야합니다.
기존 로거를 전달하여 레벨 사이트 기능에 콜 사이트 정보를 추가합니다.
참고 logger.log()은 변경되지 않고 logger.{level}() 만 변경됩니다.

// add callsite info to winston logger instance 
function addCallSite(logger) { 
    // WARNING: traceCaller is slow 
    // http://stackoverflow.com/a/20431861/665507 
    // http://stackoverflow.com/a/13411499/665507 
    /** 
    * examines the call stack and returns a string indicating 
    * the file and line number of the n'th previous ancestor call. 
    * this works in chrome, and should work in nodejs as well. 
    * 
    * @param n : int (default: n=1) - the number of calls to trace up the 
    * stack from the current call. `n=0` gives you your current file/line. 
    * `n=1` gives the file/line that called you. 
    */ 
    function traceCaller(n) { 
    if(isNaN(n) || n<0) n=1; 
    n+=1; 
    var s = (new Error()).stack 
     , a=s.indexOf('\n',5); 
    while(n--) { 
     a=s.indexOf('\n',a+1); 
     if(a<0) { a=s.lastIndexOf('\n',s.length); break;} 
    } 
    b=s.indexOf('\n',a+1); if(b<0) b=s.length; 
    a=Math.max(s.lastIndexOf(' ',b), s.lastIndexOf('/',b)); 
    b=s.lastIndexOf(':',b); 
    s=s.substring(a+1,b); 
    return s; 
    } 

    // assign to `logger.{level}()` 
    for (var func in logger.levels) { 
    (function (oldFunc) { 
     logger[func] = function() { 
     var args = Array.prototype.slice.call(arguments); 
     if (typeof args[0] === 'string') { 
      args[0] = traceCaller(1) + ' ' + args[0]; 
     } 
     else { 
      args.unshift(traceCaller(1)); 
     } 
     oldFunc.apply(logger, args); 
     }; 
    })(logger[func]); 
    }; 
} 
관련 문제