노드 : 콘솔 대신 파일에 로그인


174

console.log콘솔에서 인쇄하는 대신 파일에 로그를 쓰도록 구성 할 수 있습니까 ?


1
긴 런타임 프로덕션 앱의 경우 특정 날짜의 로그를 찾기가 쉽지 않습니다. @racar

답변:


72

업데이트 2013- 이것은 노드 v0.2 및 v0.4를 중심으로 작성되었습니다. 로깅과 관련하여 훨씬 더 유용한 유틸리티가 있습니다. 나는 윈스턴을 강력히 추천한다

Late 2013 업데이트- 우리는 여전히 winston을 사용하지만 이제는 로거 라이브러리와 함께 사용자 지정 개체 로깅 및 서식 지정 기능을 래핑합니다. 다음은 logger.js의 샘플입니다 https://gist.github.com/rtgibbons/7354879


이만큼 간단해야합니다.

var access = fs.createWriteStream(dir + '/node.access.log', { flags: 'a' })
      , error = fs.createWriteStream(dir + '/node.error.log', { flags: 'a' });

// redirect stdout / stderr
proc.stdout.pipe(access);
proc.stderr.pipe(error);

1
Nvm, 그것은 내가 생각하는 프로세스를 의미합니다 ... 어떻게 작동합니까? console.log(whatever);여전히 파일이 아닌 콘솔로갑니다.
— trusktr

12
최근 변경으로 인해 더 이상 stderr.pipe ()를 호출 할 수 없습니다. 이제는 다음이 필요합니다.process.__defineGetter__('stderr', function() { return fs.createWriteStream(__dirname + '/error.log', {flags:'a'}) })
— damianb

15
개인적으로 저는 윈스턴을 피하고 있습니다. 우리는 1 년 넘게 사용해 왔으며, 프로덕션 환경에서 많은 문제를 일으켜서 완전히 제거하기로 결정했습니다. 이 프로젝트는 현재 유지 관리가 매우 부족한 것 같습니다. 팔만큼 문제 목록이 있습니다. 많은 문제가 다른 사용자가 풀 요청을 제출했지만 프로젝트 관리자는 이러한 요청을 병합하는 데 시간이 걸리지 않습니다. 대안으로 node-bunyan과 caterpillar를 살펴볼 가치가 있습니다.
— UpTheCreek

관리자가 반응하지 않는 것이 짜증납니다. Nodejitsu 사람들이 관리한다고 생각했습니다. 우리는 하루에 백만 페이지 이상을 조회하는 여러 사이트에서이를 사용했으며 로깅에 아무런 문제가 없었습니다. 아마도 그것은 기록되는 것과 그것의 수량과 관련이있을 것입니다.
— Ryan Gibbons

1
2015 년 4 월 현재 Winston은 최신 상태이며 많은 양의 활동을 받고 있습니다.
— Mike Grace

180

기본 console.log 함수를 오버로드 할 수도 있습니다.

var fs = require('fs');
var util = require('util');
var log_file = fs.createWriteStream(__dirname + '/debug.log', {flags : 'w'});
var log_stdout = process.stdout;

console.log = function(d) { //
  log_file.write(util.format(d) + '\n');
  log_stdout.write(util.format(d) + '\n');
};

위의 예제는 debug.log 및 stdout에 기록됩니다.

편집 : 이 페이지에서도 Clément의 멀티 파라미터 버전을 참조하십시오.


9
console.log를 덮어 쓰지 않아도됩니다. 특정 파일에 기록하는 자체 기능을 작성하십시오.
— Alexander Mills

또한 여러 매개 변수에는 작동하지 않습니다. 예 : console.log (p1, p2, p3)
— user603749

10
좋은 답변입니다! 또한 여러 console.log 인수를 캡처하려면 'd'대신 'Arguments'오브젝트를 가져 오십시오.- developer.mozilla.org
— Charlie

@AlexMills 안녕, 어쩌면 정확히 어떻게 수행되는지에 대한 예를 제공 할 수 있습니까?
— Jonathan

6
그러나 나는 모든 js 파일에 이것을 가지고 있어야하며, 전역으로 만들 수 있습니까?
— stackdave

60

프로덕션 환경에서 무언가를 찾고 있다면 윈스턴 이 최선의 선택 일 것입니다.

개발 작업을 빨리하고 싶다면 파일로 직접 출력하십시오 (* nix 시스템에서만 작동한다고 생각합니다).

nohup node simple-server.js > output.log &

7
사용하여 >Windows에서뿐만 아니라를 STDOUT 작품을 리디렉션 할 수 있습니다. nohup하지 않습니다.
— Brad

1
이것은 nohup* nix 없이도 행복하게 작동합니다 node simple-server.js > output.log. 그런 다음 로그를 그대로 작성하려면tail -f output.log
— 불쾌한 페이스트리

내가 프로세스에 인수를 전달했을 때 이것은 작동하지 않았다
— eran otzap

프로덕션 환경에서이 작업의 단점은 무엇입니까?
— marcelino 2016

1
BTW, 당신의 OS에 따라 그 "할 - 일 - 대한-은"단순히이 IMO 좋은 해결책입니다 로그 회전을, 수를 - abdussamad.com/archives/541-Log-rotation-in-CentOS-Linux.html
— 무비 철

58

나는 종종 console.log () 및 console.error ()에 많은 인수를 사용 하므로 솔루션은 다음과 같습니다.

var fs = require('fs');
var util = require('util');
var logFile = fs.createWriteStream('log.txt', { flags: 'a' });
  // Or 'w' to truncate the file every time the process starts.
var logStdout = process.stdout;

console.log = function () {
  logFile.write(util.format.apply(null, arguments) + '\n');
  logStdout.write(util.format.apply(null, arguments) + '\n');
}
console.error = console.log;

32

Winston 은 로깅에 사용되는 매우 인기있는 npm 모듈입니다.

방법은 다음과 같습니다.
다음과 같이 프로젝트에 winston을 설치하십시오.

npm install winston --save

다음은 utils에서 logger.js로 프로젝트에서 자주 사용하는 기본 구성을 사용할 준비가 된 것입니다.

 /**
 * Configurations of logger.
 */
const winston = require('winston');
const winstonRotator = require('winston-daily-rotate-file');

const consoleConfig = [
  new winston.transports.Console({
    'colorize': true
  })
];

const createLogger = new winston.Logger({
  'transports': consoleConfig
});

const successLogger = createLogger;
successLogger.add(winstonRotator, {
  'name': 'access-file',
  'level': 'info',
  'filename': './logs/access.log',
  'json': false,
  'datePattern': 'yyyy-MM-dd-',
  'prepend': true
});

const errorLogger = createLogger;
errorLogger.add(winstonRotator, {
  'name': 'error-file',
  'level': 'error',
  'filename': './logs/error.log',
  'json': false,
  'datePattern': 'yyyy-MM-dd-',
  'prepend': true
});

module.exports = {
  'successlog': successLogger,
  'errorlog': errorLogger
};

그런 다음 필요한 위치를 다음과 같이 간단히 가져 오십시오.

const errorLog = require('../util/logger').errorlog;
const successlog = require('../util/logger').successlog;

그런 다음 성공을 다음과 같이 기록 할 수 있습니다.

successlog.info(`Success Message and variables: ${variable}`);

및 오류 :

errorlog.error(`Error Message : ${error}`);

또한 여기에서 볼 수 있듯이 모든 성공 로그 및 오류 로그를 로그 디렉토리 아래의 파일에 날짜별로 기록합니다.
로그 이분법


로그는 콘솔에서 볼 수 있습니다. 파일이 즉시 생성되지 않습니다 !! 뭔가 빠졌습니까?
— Nigilan

1
설정을 공유 할 수 있습니까? 아니면 내가 제안한대로 사용 했습니까? 구성이 올 바르면 가져 오기 ( winston& winston-daily-rotate-file)를 한 번 확인하십시오 . 그것들은 logs프로젝트의 루트 디렉토리에 이름이 지정된 폴더 안에 생성되어야합니다 . 답변이 늦어지면 용서해주세요.
— keshavDulal

@ Nigilan 어떻게 이것을 고쳤습니까? 나는 같은 문제에 직면하고있다.
— user2180794

@ user2180794 Nigilan의 의견 위의 나의 의견을 살펴보십시오. 여전히 할 수없는 경우 알려주십시오.
— keshavDulal

1
로거 - UTIL의 상단에 다음을 추가하는 것을 잊지 마세요 const winston = require('winston'); const winstonRotator = require('winston-daily-rotate-file'); 그리고 const errorLog = require('../util/logger').errorlog; const successlog = require('../util/logger').successlog; 어디든지 당신이 뭔가를 기록하고 싶습니다.
— keshavDulal

14
const fs = require("fs");
const {keys} = Object;
const {Console} = console;

/**
 * Redirect console to a file.  Call without path or with false-y
 * value to restore original behavior.
 * @param {string} [path]
 */
function file(path) {
    const con = path ? new Console(fs.createWriteStream(path)) : null;

    keys(Console.prototype).forEach(key => {
        if (path) {
            this[key] = (...args) => con[key](...args);
        } else {
            delete this[key];
        }
    });
};

// patch global console object and export
module.exports = console.file = file;

그것을 사용하려면 다음과 같이하십시오.

require("./console-file");
console.file("/path/to.log");
console.log("write to file!");
console.error("also write to file!");
console.file();    // go back to writing to stdout

단지 침식을 저장하는 것이 가능합니까?
— stackdave

Console.prototype키 를 반복하는 대신 명시 적으로 this.error만 설정하십시오 .
— rich remer

이것은 console.log를 중단합니까?
— G_V

깨지지 않습니다 console.log. 을 호출하여 이전 동작을 복원 할 수 있지만 동작이 변경됩니다 console.file().
— rich remer


6

아직 언급되지 않은 또 다른 해결책은 후크입니다 Writable에 스트림을 process.stdout하고 process.stderr. 이 방법 으로 stdout 및 stderr로 출력되는 모든 콘솔 기능 을 대체 할 필요는 없습니다 . 이 구현은 stdout과 stderr을 모두 로그 파일로 리디렉션합니다.

var log_file = require('fs').createWriteStream(__dirname + '/log.txt', {flags : 'w'})

function hook_stream(stream, callback) {
    var old_write = stream.write

    stream.write = (function(write) {
        return function(string, encoding, fd) {
            write.apply(stream, arguments)  // comments this line if you don't want output in the console
            callback(string, encoding, fd)
        }
    })(stream.write)

    return function() {
        stream.write = old_write
    }
}

console.log('a')
console.error('b')

var unhook_stdout = hook_stream(process.stdout, function(string, encoding, fd) {
    log_file.write(string, encoding)
})

var unhook_stderr = hook_stream(process.stderr, function(string, encoding, fd) {
    log_file.write(string, encoding)
})

console.log('c')
console.error('d')

unhook_stdout()
unhook_stderr()

console.log('e')
console.error('f')

콘솔에서 인쇄해야합니다

a
b
c
d
e
f

그리고 로그 파일에서 :

c
d

자세한 내용은이 요점을 확인하십시오 .


정답.
— nikk wong

6

간단한 경우에는 표준 출력 (STDOUT) 및 표준 오류 (STDERR) 스트림을 '>' 및 '2> & 1' 을 통해 파일로 직접 리디렉션 할 수 있습니다.

예:

// test.js
(function() {
    // Below outputs are sent to Standard Out (STDOUT) stream
    console.log("Hello Log");
    console.info("Hello Info");
    // Below outputs are sent to Standard Error (STDERR) stream
    console.error("Hello Error");
    console.warn("Hello Warning");
})();

node test.js> test.log 2> & 1

POSIX 표준에 따라 'input', 'output'및 'error' 스트림은 양의 정수 파일 디스크립터 (0, 1, 2) 로 식별됩니다 . 즉, stdin은 0, stdout은 1, stderr은 2입니다.

'2> & 1' 은 2 (stderr)에서 1 (stdout)로 리디렉션됩니다.

'>' 는 1 (stdout)에서 파일 (test.log)로 리디렉션됩니다.


5

console.log를 덮어 쓰는 방법입니다. 그러나 필요한 모듈에서 작동하려면 내 보내야합니다.

module.exports = console;

로그 파일 작성, 회전 및 작업 문제를 해결하기 위해 winston과 같은 간단한 로거 모듈 사용을 고려할 수 있습니다.

// Include the logger module
var winston = require('winston');
// Set up log file. (you can also define size, rotation etc.)
winston.add(winston.transports.File, { filename: 'somefile.log' });
// Overwrite some of the build-in console functions
console.error = winston.error;
console.log = winston.info;
console.info = winston.info;
console.debug = winston.debug;
console.warn = winston.warn;
module.exports = console;

네. 죄송합니다. 나의 나쁜
— Simon Rigét

global개체의 콘솔 속성을 덮어 쓸 수 있습니다 . 왜 그래 module.exports?
— r3wt

3

방법 STDOUT 및 STDERR

이 접근법은 당신을 도울 수 있고 (내 프로젝트에서 비슷한 것을 사용한다) console.log, console.warn, console.error, console.info를

이 메소드는 stdout 및 stderr로 작성된 바이트를 파일에 씁니다. 출력은이 메소드 출력과 정확히 동일하므로 console.log, console.warn, console.error, console.info 메소드를 변경하는 것보다 낫습니다.


var fs= require("fs")
var os= require("os")
var HOME= os.homedir()
var stdout_r = fs.createWriteStream(HOME + '/node.stdout.log', { flags: 'a' })
var stderr_r = fs.createWriteStream(HOME + '/node.stderr.log', { flags: 'a' })

var attachToLog= function(std, std_new){

    var originalwrite= std.write
    std.write= function(data,enc){
        try{
            var d= data
            if(!Buffer.isBuffer(d))
                d= Buffer.from(data, (typeof enc === 'string') ? enc : "utf8")
            std_new.write.apply(std_new, d)
        }catch(e){}
        return originalwrite.apply(std, arguments)
    }


}
attachToLog(process.stdout, stdout_r)
attachToLog(process.stderr, stderr_r)

// recommended catch error on stdout_r and stderr_r
// stdout_r.on("error", yourfunction)
// stderr_r.on("error", yourfunction)

내 npm 모듈에서 이것을 사용 하고이 코드를 당신에게 귀속시킵니다. 멋진가요?
— r3wt

2

콘솔 의 nodejs API 문서에서 직접

const output = fs.createWriteStream('./stdout.log');
const errorOutput = fs.createWriteStream('./stderr.log');
// custom simple logger
const logger = new Console(output, errorOutput);
// use it like console
const count = 5;
logger.log('count: %d', count);
// in stdout.log: count 5

1

이제 Caterpillar를 사용할 수 있습니다 스트림 기반 로깅 시스템 인 를 하여 로그를 기록한 다음 다른 변환 및 위치로 출력을 파이프 할 수 있습니다.

파일로 출력하는 것은 다음과 같이 쉽습니다.

var logger = new (require('./').Logger)();
logger.pipe(require('fs').createWriteStream('./debug.log'));
logger.log('your log message');

Caterpillar 웹 사이트의 전체 예제



0

출력 스트림을 내 스트림으로 바꾸는 아이디어를 얻었습니다.

const LogLater                = require ('./loglater.js');
var logfile=new LogLater( 'log'+( new Date().toISOString().replace(/[^a-zA-Z0-9]/g,'-') )+'.txt' );


var PassThrough = require('stream').PassThrough;

var myout= new PassThrough();
var wasout=console._stdout;
myout.on('data',(data)=>{logfile.dateline("\r\n"+data);wasout.write(data);});
console._stdout=myout;

var myerr= new PassThrough();
var waserr=console._stderr;
myerr.on('data',(data)=>{logfile.dateline("\r\n"+data);waserr.write(data);});
console._stderr=myerr;

loglater.js :

const fs = require('fs');

function LogLater(filename, noduplicates, interval) {
    this.filename = filename || "loglater.txt";
    this.arr = [];
    this.timeout = false;
    this.interval = interval || 1000;
    this.noduplicates = noduplicates || true;
    this.onsavetimeout_bind = this.onsavetimeout.bind(this);
    this.lasttext = "";
    process.on('exit',()=>{ if(this.timeout)clearTimeout(this.timeout);this.timeout=false; this.save(); })
}

LogLater.prototype = {
    _log: function _log(text) {
        this.arr.push(text);
        if (!this.timeout) this.timeout = setTimeout(this.onsavetimeout_bind, this.interval);
    },
    text: function log(text, loglastline) {
        if (this.noduplicates) {
            if (this.lasttext === text) return;
            this.lastline = text;
        }
        this._log(text);
    },
    line: function log(text, loglastline) {
        if (this.noduplicates) {
            if (this.lasttext === text) return;
            this.lastline = text;
        }
        this._log(text + '\r\n');
    },
    dateline: function dateline(text) {
        if (this.noduplicates) {
            if (this.lasttext === text) return;
            this.lastline = text;
        }
        this._log(((new Date()).toISOString()) + '\t' + text + '\r\n');
    },
    onsavetimeout: function onsavetimeout() {
        this.timeout = false;
        this.save();
    },
    save: function save() { fs.appendFile(this.filename, this.arr.splice(0, this.arr.length).join(''), function(err) { if (err) console.log(err.stack) }); }
}

module.exports = LogLater;

0

많은 수의 인수를 처리하기 위해 Andres Riofrio 개선

var fs = require('fs');
var util = require('util');

var log_file = fs.createWriteStream(__dirname + '/debug.log', {flags : 'w'});
var log_stdout = process.stdout;

console.log = function(...args) {
    var output = args.join(' ');
    log_file.write(util.format(output) + '\r\n');
    log_stdout.write(util.format(output) + '\r\n');
};


0

나는 윈스턴에서 단순히 예제를 가져 와서 log(...)방법을 추가했습니다 (윈스턴은 그것을 이름으로 지정하기 때문에)info(..) .

Console.js :

"use strict"

// Include the logger module
const winston = require('winston');

const logger = winston.createLogger({
    level: 'info',
    format: winston.format.json(),
    transports: [
        //
        // - Write to all logs with level `info` and below to `combined.log`
        // - Write all logs error (and below) to `error.log`.
        //
        new winston.transports.File({ filename: 'error.log', level: 'error' }),
        new winston.transports.File({ filename: 'combined.log' })
    ]
});

//
// If we're not in production then log to the `console` with the format:
// `${info.level}: ${info.message} JSON.stringify({ ...rest }) `
//
if (process.env.NODE_ENV !== 'production') {
    logger.add(new winston.transports.Console({
        format: winston.format.simple()
    }));
}

// Add log command
logger.log=logger.info;

module.exports = logger;

그런 다음 코드에서 간단히 사용하십시오.

const console = require('Console')

이제 파일에서 일반 로그 기능을 간단하게 사용할 수 있으며 파일을 생성하여 콘솔에 기록합니다 (디버깅 / 개발 중). 의 때문에 if (process.env.NODE_ENV !== 'production') {(경우에 당신은 생산도 원하는) ...


윈스턴은 "메시지"와 로그 레벨과 같은 많은 쓰레기를 추가하지 않습니까?
— G_V

@G_V 무슨 뜻인가요? winston은 매우 유연하므로 구성 할 수 있습니다 ... 찾고 계십니까 ... github.com/winstonjs/winston#formats ?
— TechupBusiness
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.