การเพิ่มการประทับเวลาลงในข้อความคอนโซลทั้งหมด


93

ฉันมีโปรเจ็กต์ Express-based ที่สมบูรณ์ใช้งานได้พร้อมคำสั่ง console.log () และ console.error () มากมายตลอด โปรเจ็กต์ทำงานโดยใช้ตลอดไปโดยกำหนดให้ stdout และ stderr เป็น 2 ไฟล์แยกกัน

ทุกอย่างทำงานได้ดี แต่ตอนนี้ฉันไม่มีการประทับเวลา - เพื่อให้ทราบว่าเกิดข้อผิดพลาดเมื่อใด

ฉันสามารถค้นหา / แทนที่บางประเภทได้ตลอดทั้งรหัสของฉันหรือใช้โมดูล npm บางอย่างที่แทนที่คอนโซลในแต่ละไฟล์ แต่ฉันไม่ต้องการสัมผัสไฟล์โมเดล / เส้นทางทุกอย่างเว้นแต่ฉันจะต้องทำอย่างนั้น

มีวิธีใดบ้างที่อาจเป็นมิดเดิลแวร์ของ Express ที่ช่วยให้ฉันสามารถเพิ่มการประทับเวลาในทุกครั้งที่โทรได้หรือฉันต้องเพิ่มด้วยตนเอง


คำตอบ:


117

ปรากฎว่าคุณสามารถแทนที่ฟังก์ชันคอนโซลที่ด้านบนของไฟล์ app.js และให้มันมีผลในทุกโมดูลอื่น ๆ ฉันได้ผลลัพธ์ที่หลากหลายเนื่องจากหนึ่งในโมดูลของฉันถูกแยกเป็นไฟล์child_process. เมื่อฉันคัดลอกบรรทัดไปที่ด้านบนของไฟล์นั้นเช่นกันทุกอย่างก็ใช้ได้

สำหรับเร็กคอร์ดฉันติดตั้ง module 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
คุณ shoud เปลี่ยนส่วนของนาทีตามสิ่งที่บอกว่า @ user603124 สำหรับนาทีสตริงคือ: MM ( github.com/starak/node-console-stamp )
sucotronic

ขอบคุณสำหรับความคิดเห็น แก้ไขแล้ว!
Travelling Tech Guy

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
ไม่ใช่ว่าเป็นแอป / กระบวนการเดียวกัน Console เป็นอ็อบเจ็กต์ส่วนกลางดังนั้นหากคุณไฮแจ็คฟังก์ชันอย่างใดอย่างหนึ่งเช่นนี้ระบบจะยังคงถูกไฮแจ็คสำหรับไฟล์ทั้งหมดที่แชร์อ็อบเจ็กต์ส่วนกลางนั้น
Andreas Hultgren

ดังนั้นสิ่งนี้ควร / สามารถวางไว้ในไฟล์ app.js?
Travelling Tech Guy

1
ใช่. <นาที 15 ตัวอักษร ... >
Andreas Hultgren

1
ขอแนะนำให้ใช้ console-stamp แทน
Jacek Pietal

1
นี่ไม่ใช่วิธีแก้ปัญหาที่ดี - อาจทำลายการแทรกตัวแปร (จึงไม่สามารถใช้แทนได้) หรือพิมพ์วันที่และบันทึกเอาต์พุตในบรรทัดอื่น
George Y.

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



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 หรือฐานข้อมูล สิ่งเหล่านี้มีการประทับเวลาตามค่าเริ่มต้นเสมอ เพียงแค่ความคิด


ฉันได้ตรวจสอบหลายสิ่งหลายอย่างแล้วตอนนี้ฉันต้องการเพิ่มบางสิ่งบางอย่างลงในโครงการที่มีอยู่และใช้งานได้โดยไม่ต้องแตะรหัสมากเกินไป
Travelling Tech Guy

1

คุณสามารถใช้ฟังก์ชั่นutil.logจากhttps://nodejs.org/api/util.html

โปรดทราบว่าเลิกใช้งานแล้วตั้งแต่เวอร์ชัน 6.0.0

สำหรับเวอร์ชันที่สูงขึ้นคุณควร"ใช้โมดูลของบุคคลที่สามแทน"


4
เลิกใช้: ใช้โมดูลของบุคคลที่สาม
Josh Unger

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

มีความสุขในการเขียนโค้ด :)

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.