ノード:コンソールの代わりにファイルにログインする


174

console.logログがコンソールに出力されるのではなく、ファイルに書き込まれるように構成できますか?


1
できるかもしれませんが、長いランタイムの本番アプリの場合、特定の日だけのログを見つけるのは難しいでしょう?@racar

回答:


72

2013年更新-これはNode v0.2およびv0.4を中心に書かれました。ロギングに関しては、現在、はるかに優れたユーティリティがあります。ウィンストンを強くお勧めします

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 2012

12
最近の変更により、stderr.pipe()を呼び出すことはできなくなりました-これは今すぐかかります:process.__defineGetter__('stderr', function() { return fs.createWriteStream(__dirname + '/error.log', {flags:'a'}) })
— damianb

15
個人的に私はウィンストンを避けます。これは1年以上使用しており、本番環境で多くの問題を引き起こしていたため、完全に削除することにしました。プロジェクトは現在非常に不十分に維持されているようです。あなたの腕さえあれば問題のリストがあります。問題の多くは他のユーザーからプルリクエストが提出されていますが、プロジェクトのメンテナーはこれらをマージするために時間をかけていません。別の方法として、node-bunyanとcaterpillarは一見の価値があります。
— UpTheCreek

メンテナが反応しないのは残念です。それはNodejitsuの人々によって維持されていると思いました。私たちはいくつかのサイトでこれを使用しており、1日に100万を超えるページビューを取得しており、ロギングに関する問題は発生していません。たぶんそれは記録されているものとその量に関係しています。
— ライアンギボンズ

1
2015年4月の時点で、Winstonは最新の状態であり、多くのアクティビティを受け取っているようです。
— Mike Grace

178

デフォルトの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にログが記録されます。

編集: このページでも、クレメンのマルチパラメータバージョンをご覧ください。


9
console.logを上書きする必要はありません。特定のファイルにログを記録する独自の関数を作成するだけです。
— Alexander Mills

さらに、これは複数のパラメーターに対しては機能しません。例:console.log(p1、p2、p3)
— user603749

10
正解です。あなたが複数にconsole.log引数をキャプチャする場合にも、単に「D」の代わりに「引数」オブジェクトをつかむ- developer.mozilla.org/en/docs/Web/JavaScript/Reference/...
— チャーリー・

@AlexMillsこんにちは、たぶんそれがどのように行われるかについての例を提供できますか?
— ジョナサン

6
しかし、これをすべてのjsファイルに含める必要があります、それをグローバルにすることは可能ですか?
— stackdave 16

60

あなたが生産で何かを探しているなら、ウィンストンはおそらく最良の選択です。

開発をすばやく行いたい場合は、ファイルに直接出力します(これは* nixシステムでのみ機能すると思います)。

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

7
を使用>してSTDOUTをリダイレクトすると、Windowsでも機能します。 nohupしません。
— ブラッド

1
これnohupは* nixを使わなくてもうまく機能しnode simple-server.js > output.logます。次に、ログをそのまま書かれたままにしたい場合tail -f output.log
— 厄介なペースト状

これは機能しませんでした。2henがプロセスに引数を渡されました
— eran otzap

本番環境でこれを行うことの欠点は何ですか?
— marcelino 2017

1
お使いのOSにもよりますが、「do-something-about-it」は単にログローテーションである可能性があります。これはimoの
— ferr

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 2017

1
おそらくあなたの設定を共有できますか?それとも私が提案したようにそれを使用しましたか?設定に問題がない場合は、インポート(winston&winston-daily-rotate-file)を1回確認します。これらはlogs、プロジェクトのルートディレクトリにあるフォルダ内に作成する必要があります。返信が遅れてすみません。
— keshavDulal 2017

@Nigilanどうやってこれを直したの?私も同じ問題に直面しています。
— user2180794 2017年

@ user2180794 Nigilanのコメントの上にある私のコメントを見てください。それでも解決しない場合はお知らせください。
— keshavDulal 2017年

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 2017年

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 2018年

Console.prototypeキーをループする代わりに、明示的に設定するthis.errorだけです。
— リッチリマー2018

これはconsole.logを壊しますか?
— G_V

壊れませんconsole.log。動作を変更しますが、を呼び出すことで古い動作を復元できますconsole.file()。
— リッチリマー

10

これがアプリケーションの場合は、おそらくロギングモジュールを使用する方がよいでしょう。柔軟性が増します。いくつかの提案。


3
log4jsリンクが壊れています。これはどう?github.com/nomiddlename/log4js-node
— Joe Hildebrand

1
ええ、私はプロジェクトが手を切り替えたと思います。ありがとう。
— Marco

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 2017

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");
})();

ノードtest.js> test.log 2>&1

POSIX標準に従って、「入力」、「出力」、および「エラー」ストリームは、正の整数ファイル記述子(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;

うん。ごめんなさい。私の悪い
— サイモン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 Webサイトの完全な例



0

私は出力ストリームをmyストリームにスワップすることを思いつきました。

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.