Додавання позначок часу до всіх повідомлень консолі


93

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

Це все працює досить добре, але зараз мені не вистачає позначок часу - щоб точно знати, коли сталися помилки.

Я можу здійснити якийсь пошук / заміну у всьому коді, або використовувати якийсь модуль npm, який замінює консоль у кожному файлі, але я не хочу торкатися кожної моделі / файлу маршруту, якщо це не потрібно.

Чи є спосіб, можливо, проміжне програмне забезпечення Express, який би дозволив мені додати позначку часу до кожного зробленого дзвінка, чи мені доведеться додавати її вручну?


Відповіді:


118

Виявляється, ви можете перевизначити функції консолі у верхній частині файлу 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 )
сукотронік

Дякую за коментар. Виправлено!
Подорожній технічний хлопець

2
Здається, вам більше не потрібно загортати HH: MM: ss.l в дужки - це робиться автоматично
Джефф

3
FYI loggerбуло замінено 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
Ні, якщо це той самий додаток / процес. Консоль - це глобальний об'єкт, тому, якщо ви захопите одну з таких функцій, як це, вона буде продовжувати викрадати всі файли, що мають спільний доступ до цього глобального об'єкта.
Andreas Hultgren

Отже, це слід / можна розмістити у файлі app.js?
Traveling Tech Guy,

1
Так. <хв 15 символів ...>
Андреас Хультгрен,

1
Я рекомендую замість цього використовувати консольний штамп
Jacek Pietal

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

9

Ви також можете використовувати пакет log-timestamp . Це досить просто, а також налаштовується.


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

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

За бажанням ви можете створити власний реєстратор для вашого додатка, розширивши збірку вузла в класі "Консоль". Будь ласка, зверніться до наступної реалізації

"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конструктор 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.