Добавление меток времени ко всем сообщениям консоли


93

У меня есть законченный развернутый проект на основе Express со множеством операторов console.log () и console.error (). Проект запускается с использованием вечности, направляя stdout и stderr в 2 отдельных файла.

Все работает неплохо, но теперь мне не хватает меток времени, чтобы точно знать, когда произошли ошибки.

Я могу выполнять какой-то поиск / замену во всем моем коде или использовать какой-либо модуль npm, который переопределяет консоль в каждом файле, но я не хочу трогать каждый файл модели / маршрута, если только в этом нет крайней необходимости.

Есть ли способ, возможно, промежуточное ПО Express, которое позволило бы мне добавлять метку времени к каждому сделанному вызову, или мне нужно добавить ее вручную?


Ответы:


116

Оказывается, вы можете переопределить функции консоли в верхней части файла app.js и заставить их действовать в любом другом модуле. Я получил неоднозначные результаты, потому что один из моих модулей разветвлен как 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

2
вы должны изменить часть минут в соответствии с тем, что говорит @ user603124. Для минут строка выглядит так : MM ( github.com/starak/node-console-stamp )
Sucotronic

Спасибо за комментарий. Исправленный!
Traveling Tech Guy

2
Похоже, вам больше не нужно заключать в скобки HH: MM: ss.l - он делает это автоматически,
Джефф,

3
FYI loggerбыл заменен на morgan github.com/senchalabs/connect#middleware
vtellier

34

module: "log-timestamp" у меня работает.

см. https://www.npmjs.com/package/log-timestamp

npm install log-timestamp

Простой в использовании

console.log('Before log-timestamp');
require('log-timestamp');
console.log('After log-timestamp');

Результат

Before log-timestamp
[2012-08-23T20:08:32.000Z] After log-timestamp

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
Нет, если это одно и то же приложение / процесс. Консоль - это глобальный объект, поэтому, если вы перехватите одну из ее функций, подобную этой, она будет продолжать перехватывать все файлы, которые используют этот глобальный объект.
Андреас Халтгрен

Значит, это нужно / можно было поместить в файл app.js?
Traveling Tech Guy

1
Да. <мин. 15 символов ...>
Андреас Халтгрен

1
Я рекомендую вместо этого использовать console-stamp
Яцек Пьеталь

1
Это не очень хорошее решение - оно либо уничтожает вставку переменных (таким образом, не может использоваться в качестве замены), либо выводит дату и вывод журнала в разные строки.
Джордж Ю.

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.

console.log("he%s", "y") напечатает что-то вроде этого:

[12:22:55.053] hey

4
Спасибо, этот ответ «без зависимостей» был именно тем, что мне было нужно.
RdR 03



2

Эта реализация проста, поддерживает исходную функциональность console.log (передача одного объекта и подстановка переменных), не использует внешние модули и печатает все за один вызов console.log:

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

Если вы хотите, вы можете создать собственный журнал для своего приложения, расширив сборку узла в классе «Console». Пожалуйста, обратитесь к следующей реализации

"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

Вы можете использовать функцию util.logиз https://nodejs.org/api/util.html .

Имейте в виду, что он устарел, начиная с версии 6.0.0.

Для более поздних версий вам следует «Использовать модуль стороннего производителя».


4
Не рекомендуется: используйте сторонний модуль.
Джош Унгер,

1

Пытаюсь перезаписать consoleобъект - вроде работает нормально. Чтобы использовать, сохраните приведенный ниже код в файле, а затем импортируйте, чтобы перезаписать прокси-объект, а затем используйте как обычно.

(Обратите внимание, что это требует транспиляции babel и не будет работать в средах, которые не поддерживают Proxyконструктор JavaScript, например IE 11).

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.log, console.info, console.warn, console.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)
});

счастливого кодирования :)

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.