Thêm dấu thời gian vào tất cả các thông báo trên bảng điều khiển


93

Tôi có một dự án hoàn chỉnh, đã triển khai , dựa trên Express, với nhiều câu lệnh console.log () và console.error () xuyên suốt. Dự án chạy bằng cách sử dụng mãi mãi, hướng stdout và stderr đến 2 tệp riêng biệt.

Tất cả đều hoạt động khá tốt, nhưng bây giờ tôi đang thiếu dấu thời gian - để biết chính xác thời điểm xảy ra lỗi.

Tôi có thể thực hiện một số loại tìm kiếm / thay thế trong toàn bộ mã của mình hoặc sử dụng một số mô-đun npm ghi đè bảng điều khiển trong mỗi tệp, nhưng tôi không muốn chạm vào mọi tệp mô hình / tuyến đường, trừ khi tôi thực sự phải làm vậy.

Có cách nào, có lẽ là phần mềm trung gian Express, cho phép tôi thêm dấu thời gian vào mỗi cuộc gọi được thực hiện hay tôi phải thêm nó theo cách thủ công?


Câu trả lời:


116

Hóa ra, bạn có thể ghi đè các chức năng của bảng điều khiển ở đầu tệp app.js và để nó có hiệu lực trong mọi mô-đun khác. Tôi nhận được nhiều kết quả khác nhau bởi vì một trong những mô-đun của tôi được chia thành một child_process. Sau khi tôi sao chép dòng vào đầu tệp đó, tất cả đều hoạt động.

Đối với bản ghi, tôi đã cài đặt module console-tem ( npm install console-stamp --save) và thêm dòng này vào đầu app.js và childProcess.js:

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

Vấn đề của tôi bây giờ là :dateđịnh dạng của trình ghi kết nối sử dụng định dạng UTC, thay vì định dạng tôi đang sử dụng trong các lệnh gọi bảng điều khiển khác. Điều đó đã được khắc phục dễ dàng bằng cách đăng ký định dạng thời gian của riêng tôi (và như một tác dụng phụ, yêu cầu dateformatmô-đun console stampđi kèm, thay vì cài đặt một mô-đun khác):

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

Bây giờ các tệp nhật ký của tôi trông có tổ chức (và tốt hơn là có thể phân tích cú pháp):

[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
Tôi không thể tìm thấy tài liệu cho nó, nhưng có vẻ như ": mm" sẽ chỉ tháng và ": MM" là định dạng mà bạn thực sự muốn sử dụng
Laurent Sigal

2
bạn nên thay đổi phần phút theo nội dung @ user603124. Đối với số phút, chuỗi là : MM ( github.com/starak/node-console-stamp )
sucotronic

Cảm ơn đã nhận xét. Đã sửa!
Traveling Tech Guy

2
Có vẻ như bạn không cần đặt HH: MM: ss.l trong ngoặc nữa - nó đang tự động làm việc đó
Jeff

3
FYI loggerđã được thay thế bằng morgan github.com/senchalabs/connect#middleware
vtellier

34

module: "log-timestamp" phù hợp với tôi.

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

npm install log-timestamp

Đơn giản để sử dụng

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

Kết quả

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

26

Tạo tệp như sau:

var log = console.log;

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

Yêu cầu nó trong ứng dụng của bạn trước khi bạn đăng nhập bất kỳ thứ gì. Làm tương tự choconsole.error nếu cần.

Lưu ý rằng giải pháp này sẽ phá hủy chèn biến ( console.log("he%s", "y") // "hey") nếu bạn đang sử dụng. Nếu bạn cần, chỉ cần ghi lại dấu thời gian trước:

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

2
Không nếu đó là cùng một ứng dụng / quy trình. Console là một đối tượng toàn cục vì vậy nếu bạn chiếm đoạt một trong các chức năng của nó như thế này, nó sẽ tiếp tục bị tấn công đối với tất cả các tệp chia sẻ đối tượng toàn cầu đó.
Andreas Hultgren

Vì vậy, điều này nên / có thể được đặt trong tệp app.js?
Traveling Tech Guy

1
Đúng. <phút 15 chars ...>
Andreas Hultgren

1
Tôi khuyên bạn nên sử dụng giao diện điều khiển-tem thay
Jacek Pietal

1
Đây không phải là giải pháp tốt - nó có thể phá hủy chèn biến (do đó không thể được sử dụng thay thế) hoặc in ngày tháng và đầu ra nhật ký trên các dòng khác nhau.
George Y.

16

Nếu bạn muốn một giải pháp không có sự phụ thuộc bên ngoài khác nhưng bạn muốn giữ đầy đủ các chức năng của console.log (nhiều tham số, chèn biến), bạn có thể sử dụng mã sau:

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

Bạn có thể sửa đổi hàm formatConsoleDate để định dạng ngày tháng theo cách bạn muốn.

Mã này chỉ cần được viết một lần trên đầu tệp JavaScript chính của bạn.

console.log("he%s", "y") sẽ in một cái gì đó như thế này:

[12:22:55.053] hey

4
Cảm ơn, câu trả lời "không phụ thuộc" này là chính xác những gì tôi cần.
RdR


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

2

Việc triển khai này rất đơn giản, hỗ trợ chức năng ban đầu của console.log (truyền một đối tượng duy nhất và thay thế biến), không sử dụng các mô-đun bên ngoài và in mọi thứ trong một lệnh gọi tới 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

Nếu muốn, bạn có thể tạo một trình ghi nhật ký tùy chỉnh cho ứng dụng của mình bằng cách mở rộng bản dựng của Node trong lớp "Console". Vui lòng tham khảo cách thực hiện sau

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

Sau đó, bạn có thể sử dụng nó trong mã của mình như:

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

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


1

Đây không phải là một câu trả lời trực tiếp, nhưng bạn đã xem xét winton.js chưa? Nó có nhiều tùy chọn ghi nhật ký hơn bao gồm đăng nhập vào tệp json hoặc cơ sở dữ liệu. Chúng luôn có dấu thời gian theo mặc định. Chỉ là một suy nghĩ.


Tôi đã nhìn vào nhiều thứ, ngay bây giờ, tôi muốn thêm một cái gì đó để một, triển khai dự án hiện có - mà không cần chạm quá nhiều mã
Du lịch Tech Guy


1

Tôi đang cố gắng ghi đè consoleđối tượng - có vẻ như đang hoạt động tốt. Để sử dụng, hãy lưu mã bên dưới vào một tệp, sau đó nhập để ghi đè đối tượng proxy, sau đó sử dụng như bình thường.

(Lưu ý rằng điều này yêu cầu chuyển đổi babel và sẽ không hoạt động trong các môi trường không hỗ trợ hàm tạo JavaScript Proxynhư 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],
  }
)

Về cơ bản, tôi ghi đè đối tượng bảng điều khiển bằng một đối tượng proxy JavaScript. Khi bạn gọi .log,.warn v.v., bảng điều khiển được ghi đè sẽ kiểm tra xem những gì bạn đang gọi có phải là một hàm hay không, nếu có, nó sẽ đưa ngày vào câu lệnh nhật ký làm tham số đầu tiên, tiếp theo là tất cả các tham số của bạn.

Tôi nghĩ rằng consoleđối tượng thực sự làm được nhiều điều, và tôi không hiểu hết về nó. Vì vậy, tôi chỉ đánh chặn console.log, console.info, console.warn, console.errorcuộc gọi.


-1

Sử dụng trình nghe sự kiện như thế này,

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

viết mã vui vẻ :)

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.