Menambahkan cap waktu ke semua pesan konsol

93

Saya memiliki proyek yang lengkap, diterapkan , berbasis Express, dengan banyak pernyataan console.log () dan console.error () di seluruh. Proyek ini berjalan menggunakan selamanya, mengarahkan stdout dan stderr ke 2 file terpisah.

Semuanya bekerja dengan cukup baik, tetapi sekarang saya kehilangan cap waktu - untuk mengetahui dengan tepat kapan kesalahan terjadi.

Saya dapat melakukan semacam pencarian / penggantian di seluruh kode saya, atau menggunakan beberapa modul npm yang menggantikan konsol di setiap file, tetapi saya tidak ingin menyentuh setiap file model / rute, kecuali saya benar-benar harus melakukannya.

Adakah cara, mungkin middleware Express, yang memungkinkan saya menambahkan stempel waktu ke setiap panggilan yang dilakukan, atau apakah saya harus menambahkannya secara manual?

Bepergian Tech Guy
sumber

Jawaban:

116

Ternyata, Anda dapat mengganti fungsi konsol di bagian atas file app.js, dan menerapkannya di setiap modul lainnya. Saya mendapatkan hasil yang beragam karena salah satu modul saya bercabang sebagai child_process. Setelah saya menyalin baris ke bagian atas file itu juga, semuanya berfungsi.

Sebagai catatan, saya menginstal modul console-stamp ( npm install console-stamp --save), dan menambahkan baris ini ke bagian atas app.js dan childProcess.js:

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

Masalah saya sekarang adalah bahwa :dateformat logger koneksi menggunakan format UTC, daripada yang saya gunakan di panggilan konsol lain. Itu mudah diperbaiki dengan mendaftarkan format waktu saya sendiri (dan sebagai efek samping, membutuhkan dateformatmodul yang console stampdisertakan, daripada menginstal yang lain):

// 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'));

Sekarang file log saya terlihat teratur (dan lebih baik lagi, dapat diurai):

[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
...
Bepergian Tech Guy
sumber
2
Saya tidak dapat menemukan dokumennya, tetapi tampaknya ": mm" mengacu pada bulan, dan ": MM" adalah format yang sebenarnya ingin Anda gunakan
Laurent Sigal
2
Anda harus mengubah bagian menit sesuai dengan yang tertulis di @ user603124. Untuk menit, stringnya adalah : MM ( github.com/starak/node-console-stamp )
sucotronic
Terima kasih atas komentarnya. Diperbaiki!
Travelling Tech Guy
2
Sepertinya Anda tidak perlu lagi membungkus HH: MM: ss.l dalam tanda kurung - ini melakukannya secara otomatis
Jeff
3
FYI loggertelah digantikan oleh morgan github.com/senchalabs/connect#middleware
vtellier
34

module: "log-timestamp" berfungsi untuk saya.

lihat https://www.npmjs.com/package/log-timestamp

npm install log-timestamp

Mudah digunakan

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

Hasil

Before log-timestamp
[2012-08-23T20:08:32.000Z] After log-timestamp
Sunding Wei
sumber
26

Buat file dengan berikut ini:

var log = console.log;

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

Membutuhkannya di aplikasi Anda sebelum Anda mencatat apa pun. Lakukan hal yang sama console.errorjika diperlukan.

Perhatikan bahwa solusi ini akan menghancurkan penyisipan variabel ( console.log("he%s", "y") // "hey") jika Anda menggunakannya. Jika Anda membutuhkannya, cukup catat stempel waktunya terlebih dahulu:

log.call(console, Date.now());
log.apply(console, arguments);
Andreas Hultgren
sumber
2
Tidak jika itu aplikasi / proses yang sama. Konsol adalah objek global jadi jika Anda membajak salah satu fungsinya seperti ini, ia akan terus dibajak untuk semua file yang berbagi objek global tersebut.
Andreas Hultgren
Jadi ini harus / dapat ditempatkan di file app.js?
Travelling Tech Guy
1
Iya. <min 15 karakter ...>
Andreas Hultgren
1
Saya merekomendasikan menggunakan stempel konsol sebagai gantinya
Jacek Pietal
1
Ini bukan solusi yang baik - ini akan menghancurkan penyisipan variabel (sehingga tidak dapat digunakan sebagai pengganti), atau mencetak tanggal dan keluaran log pada baris yang berbeda.
George Y.
16

Jika Anda menginginkan solusi tanpa ketergantungan eksternal lain tetapi Anda ingin mempertahankan fungsionalitas penuh console.log (beberapa parameter, penyisipan variabel), Anda dapat menggunakan kode berikut:

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

Anda dapat mengubah fungsi formatConsoleDate untuk memformat tanggal sesuai keinginan Anda.

Kode ini hanya perlu ditulis sekali di atas file JavaScript utama Anda.

console.log("he%s", "y") akan mencetak sesuatu seperti ini:

[12:22:55.053] hey
leszek.hanusz
sumber
4
Terima kasih, jawaban "tanpa ketergantungan" ini persis seperti yang saya butuhkan.
RdR
9

Anda juga dapat menggunakan paket log-timestamp . Ini cukup mudah, dan juga dapat disesuaikan.

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

Implementasi ini sederhana, mendukung fungsionalitas asli console.log (meneruskan satu objek, dan substitusi variabel), tidak menggunakan modul eksternal dan mencetak semuanya dalam satu panggilan ke 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 );
};
George Y.
sumber
2

Jika mau, Anda dapat membuat logger khusus untuk aplikasi Anda dengan memperluas build Node di kelas "Console". Mohon mengacu pada implementasi berikut

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

Setelah itu, Anda dapat menggunakannya dalam kode Anda sebagai:

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

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

Shivam Shekhar
sumber
1

Ini bukan jawaban langsung, tetapi apakah Anda sudah mempelajari winston.js? Ini memiliki lebih banyak opsi logging termasuk logging ke file atau database json. Ini selalu memiliki cap waktu secara default. Hanya pemikiran saja.

Zeke Alexandre Nierenberg
sumber
Saya telah melihat banyak hal, sekarang, saya ingin menambahkan sesuatu ke proyek yang sudah ada dan diterapkan - tanpa terlalu banyak menyentuh kode
Travelling Tech Guy
1

Saya mencoba menimpa consoleobjek - tampaknya berfungsi dengan baik. Untuk menggunakan, simpan kode di bawah ini dalam sebuah file, lalu impor untuk menimpa objek proxy, lalu gunakan seperti biasa.

(Perhatikan ini memerlukan transpilasi babel dan tidak akan berfungsi di lingkungan yang tidak mendukung Proxykonstruktor JavaScript seperti 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],
  }
)

Pada dasarnya saya menimpa objek konsol dengan objek proxy JavaScript. Ketika Anda memanggil .log, .warndll. Konsol yang ditimpa akan memeriksa apakah yang Anda panggil adalah sebuah fungsi, jika demikian itu akan memasukkan tanggal ke dalam pernyataan log sebagai parameter pertama, diikuti oleh semua parameter Anda.

Saya pikir consoleobjek itu sebenarnya melakukan banyak hal, dan saya tidak sepenuhnya memahaminya. Jadi saya hanya intercept console.log, console.info, console.warn, console.errorpanggilan.

Zach Smith
sumber
-1

Gunakan pendengar acara seperti ini,

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

selamat coding :)

JsWizard
sumber