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


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.