すべてのコンソールメッセージにタイムスタンプを追加する


93

完全にデプロイされたExpressベースのプロジェクトがあり、全体に多くのconsole.log()およびconsole.error()ステートメントがあります。プロジェクトはforeverを使用して実行され、stdoutとstderrを2つの別々のファイルに転送します。

それはすべて非常にうまく機能しますが、エラーがいつ発生したかを正確に知るために、タイムスタンプがありません。

コード全体で何らかの検索/置換を実行したり、各ファイルのコンソールをオーバーライドするnpmモジュールを使用したりできますが、どうしても必要な場合を除いて、すべてのモデル/ルートファイルにアクセスしたくありません。

行われたすべての呼び出しにタイムスタンプを追加できる方法、おそらくExpressミドルウェアはありますか、それとも手動で追加する必要がありますか?


回答:


116

それは結局のところ、あなたができるapp.jsファイルの先頭にコンソール機能を無効にし、それが他のすべてのモジュール内で有効になります持っています。モジュールの1つがフォークされているため、結果がまちまちです。child_processです。その行をそのファイルの先頭にもコピーすると、すべて機能します。

記録のために、モジュールconsole-stamp(npm install console-stamp --save)をインストールし、app.jsとchildProcess.jsの先頭に次の行を追加しました。

// add timestamps in front of log messages
require('console-stamp')(console, '[HH:MM:ss.l]');

私の問題:dateは、接続ロガーの形式が、他のコンソール呼び出しで使用している形式ではなく、UTC形式を使用していることでした。これは、自分の時間形式を登録することで簡単に修正できました(また、副作用として、別のdateformatモジュールをconsole stampインストールするのではなく、付属のモジュールが必要になります)。

// since logger only returns a UTC version of date, I'm defining my own date format - using an internal module from console-stamp
express.logger.format('mydate', function() {
    var df = require('console-stamp/node_modules/dateformat');
    return df(new Date(), 'HH:MM:ss.l');
});
app.use(express.logger('[:mydate] :method :url :status :res[content-length] - :remote-addr - :response-time ms'));

これで、ログファイルが整理されたように見えます(さらに良いことに、解析可能です)。

[15:09:47.746] staging server listening on port 3000
[15:09:49.322] connected to database server xxxxx successfully
[15:09:52.743] GET /product 200 - - 127.0.0.1 - 214 ms
[15:09:52.929] GET /stylesheets/bootstrap-cerulean.min.css 304 - - 127.0.0.1 - 8 ms
[15:09:52.935] GET /javascripts/vendor/require.js 304 - - 127.0.0.1 - 3 ms
[15:09:53.085] GET /javascripts/product.js 304 - - 127.0.0.1 - 2 ms
...

2
ドキュメントが見つかりませんでしたが、「:mm」は月を指し、「:MM」は実際に使用したい形式であるようです
Laurent Sigal 2014

2
@ user603124の内容に従って、分の部分を変更する必要があります。数分間、文字列は:MMgithub.com/starak/node-console-stamp
sucotronic 2014

コメントありがとうございます。修正しました!
Travelling Tech Guy

2
HH:MM:ss.lを角かっこで囲む必要がなくなったようです-自動的に実行されます
Jeff

3
FYIloggerに置き換えられていmorgan github.com/senchalabs/connect#middleware
vtellier


26

次のファイルを作成します。

var log = console.log;

console.log = function(){
  log.apply(console, [Date.now()].concat(arguments));
};

何かをログに記録する前に、アプリでそれを要求します。同じことをするconsole.error必要に応じようにします。

このソリューションをconsole.log("he%s", "y") // "hey"使用している場合、このソリューションは変数の挿入()を破棄することに注意してください。それが必要な場合は、最初にタイムスタンプをログに記録してください。

log.call(console, Date.now());
log.apply(console, arguments);

2
同じアプリ/プロセスの場合は違います。コンソールはグローバルオブジェクトであるため、このような機能の1つをハイジャックすると、そのグローバルオブジェクトを共有するすべてのファイルに対してハイジャックされ続けます。
アンドレアスハルトグレン2013

それで、これはapp.jsファイルに配置する必要がありますか?
Travelling Tech Guy

1
はい。<最小15文字...>
Andreas Hultgren 2013

1
代わりにコンソールスタンプを使用することをお勧めします
Jacek Pietal 2016

1
これは適切な解決策ではありません。変数の挿入を破棄するか(したがって、置換として使用することはできません)、日付とログ出力を別の行に出力します。
ジョージY.18年

16

別の外部依存関係のないソリューションが必要であるが、console.logのすべての機能(複数のパラメーター、変数の挿入)を維持したい場合は、次のコードを使用できます。

var log = console.log;

console.log = function () {
    var first_parameter = arguments[0];
    var other_parameters = Array.prototype.slice.call(arguments, 1);

    function formatConsoleDate (date) {
        var hour = date.getHours();
        var minutes = date.getMinutes();
        var seconds = date.getSeconds();
        var milliseconds = date.getMilliseconds();

        return '[' +
               ((hour < 10) ? '0' + hour: hour) +
               ':' +
               ((minutes < 10) ? '0' + minutes: minutes) +
               ':' +
               ((seconds < 10) ? '0' + seconds: seconds) +
               '.' +
               ('00' + milliseconds).slice(-3) +
               '] ';
    }

    log.apply(console, [formatConsoleDate(new Date()) + first_parameter].concat(other_parameters));
};

formatConsoleDate関数を変更して、日付を希望どおりにフォーマットできます。

このコードは、メインのJavaScriptファイルの上に1回だけ記述する必要があります。

console.log("he%s", "y") 次のようなものを印刷します:

[12:22:55.053] hey

4
おかげで、この「依存関係なし」の答えはまさに私が必要としていたものでした。
rdR 2017


3
app.use(morgan('[:date[web]] :method :url :status :res[content-length] - :remote-addr - :response-time ms'))

2

この実装は単純で、console.logの元の機能(単一のオブジェクトの受け渡しと変数置換)をサポートし、外部モジュールを使用せず、console.logへの1回の呼び出しですべてを出力します。

var origlog = console.log;

console.log = function( obj, ...placeholders ){
    if ( typeof obj === 'string' )
        placeholders.unshift( Date.now() + " " + obj );
    else
    {
        // This handles console.log( object )
        placeholders.unshift( obj );
        placeholders.unshift( Date.now() + " %j" );
    }

    origlog.apply( this, placeholders );
};

2

必要に応じて、「コンソール」クラスでノードのビルドを拡張することにより、アプリケーションのカスタムロガーを作成できます。次の実装を参照してください

"use strict";

const moment = require('moment');
const util = require('util');
const Console = require('console').Console;

class Logger extends Console {
    constructor(stdout, stderr, ...otherArgs) {
        super(stdout, stderr, ...otherArgs);
    }

    log(...args) {
        super.log(moment().format('D MMM HH:mm:ss'), '-', util.format(...args));
    }

    error(...args) {
        super.error(moment().format('D MMM HH:mm:ss'), '-', util.format(...args));
    }
}

module.exports = (function() {
    return new Logger(process.stdout, process.stderr); 
}());

その後、コードで次のように使用できます。

const logger = require('./logger');

logger.log('hello world', 123456);
logger.error('some error occurred', err);


1

これは直接的な答えではありませんが、winston.jsを調べましたか?jsonファイルまたはデータベースへのロギングを含む、さらに多くのロギングオプションがあります。これらには、デフォルトで常にタイムスタンプがあります。ちょっとした考え。


私は多くのことを調べましたが、今、既存のデプロイされたプロジェクトに何かを追加したいと思います
-Traveling Tech Guy


1

consoleオブジェクトを上書きしようとしています-うまく機能しているようです。使用するには、以下のコードをファイルに保存し、インポートしてプロキシオブジェクトを上書きしてから、通常どおりに使用します。

(これにはbabelトランスパイルが必要でありProxy、IE 11などのJavaScriptコンストラクターをサポートしていない環境では機能しないことに注意してください)。

import console from './console-shadow.js'

console.log(...)
console.warn(...)
console.error(...)
// console-shadow.js

// Only these functions are shadowed by default
const overwrites = ['log', 'warn', 'info', 'error']

export default new Proxy(
  // Proxy (overwrite console methods here)
  {},

  // Handler
  {
    get: (obj, prop) =>
      prop in obj
        ? obj[prop]
        : overwrites.includes(prop)
        ? (...args) => console[prop].call(console, new Date(), ...args)
        : console[prop],
  }
)

基本的に、コンソールオブジェクトをJavaScriptプロキシオブジェクトで上書きします。あなたが電話するとき.log.warn、など、上書きされたコンソールは、呼び出しているものが関数であるかどうかを確認します。関数である場合は、最初のパラメーターとしてログステートメントに日付を挿入し、その後にすべてのパラメーターを挿入します。

私が思うにconsole、オブジェクトが実際に多くのことをして、私は完全にそれを理解していません。唯一の切片私はそうconsole.logconsole.infoconsole.warnconsole.error通話。


-1

このようなイベントリスナーを使用して、

process.on('error', function() { 
   console.log('Error Occurred.');

   var d = Date(Date.now()).toString();
   console.log.call(console, d); // Wed Aug 07 2019 23:40:07 GMT+0100 (GMT+01:00)
});

幸せなコーディング:)

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.