欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

關(guān)于自定義Egg.js的請求級別日志詳解

 更新時間:2018年12月12日 14:22:24   作者:MaxPan  
這篇文章主要給大家介紹了關(guān)于自定義Egg.js的請求級別日志的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

Egg.js 是什么?

Egg.js 為企業(yè)級框架和應(yīng)用而生,我們希望由 Egg.js 孕育出更多上層框架,幫助開發(fā)團隊和開發(fā)人員降低開發(fā)和維護成本。

注:Egg.js 縮寫為 Egg

背景

組織為了更好的對各個業(yè)務(wù)的請求日志進行統(tǒng)一的分析,制定了統(tǒng)一的日志打印規(guī)范,比如:

[time][processId][traceId][userid] Hello World....

統(tǒng)一格式之后,業(yè)務(wù)現(xiàn)有業(yè)務(wù)的日志工具打印出來的格式是無法滿足該規(guī)范的,所以我們需要對此進行改造。

我們前端目前Node中間層使用的框架是Egg.js,所以下文講述下如何在Egg.js上自定義請求日志格式。

開始動手

Egg.js中自帶了三種logger,分別是

  • Context Logger
  • App Logger
  • Agent Logger

Context Logger主要是用來記錄請求相關(guān)的日志。每行日志都會在開頭自動的記錄當(dāng)前請求的一些信息,比如時間、ip、請求url等等。

App Logger用于記錄應(yīng)用級別的日志,比如程序啟動日志。

Agent Logger用于記錄多進程模式運行下的日志。

我們想自定義請求級別的日志,那重點就要從Context Logger去研究怎么做。最理想的方案就是,Context Logger本身支持配置化的自定義格式,通過在egg.js的config配置文件中,通過傳入formatter的參數(shù)就能自定義。

//config.default.js
exports.customLogger = {
 log: {
  file: 'appname.log',
  formatter: (message)=>{
   return `${message.time}${message.processid}` 
  }
 }
}

但不久我們發(fā)現(xiàn)這條路走不通,設(shè)置了這個formatter并不起作用。從Context Logger的源碼中,我們發(fā)現(xiàn)的端倪context_logger.js

[ 'error', 'warn', 'info', 'debug' ].forEach(level => {
 const LEVEL = level.toUpperCase();
 ContextLogger.prototype[level] = function() {
 const meta = {
  formatter: contextFormatter,
  paddingMessage: this.paddingMessage,
 };
 this._logger.log(LEVEL, arguments, meta);
 };
});

module.exports = ContextLogger;

function contextFormatter(meta) {
 return meta.date + ' ' + meta.level + ' ' + meta.pid + ' ' + meta.paddingMessage + ' ' + meta.message;
}

在源碼中我們可以看到,formatter參數(shù)已經(jīng)被內(nèi)部的一個自定義格式化函數(shù)覆蓋了,配置中寫的是不會啟作用的。
此路不通,只能嘗試自己實現(xiàn)logger去解決。自己實現(xiàn)我們需要考慮一些點,比如:

  • 日志要寫到文件中,錯誤日志單獨寫一個文件
  • 需要能按天或按小時切割日志
  • IO性能

如果這些都自己實現(xiàn)的話,那就太麻煩了。好在了解到Egg的這幾個logger都是基于egg-logger和egg-logrotator去實現(xiàn)的,所以我們可以站在巨人的肩膀上搞事情。

Context Logger是基于egg-logger的FileTransport類去進行文件落地的,同時FileTransport也默認配置了egg-logrotator的日志拆分。所以,我們只需要繼承FileTransport類,實現(xiàn)接口就可以了,代碼如下:

//CoustomTransport.js
const FileTransport = require('egg-logger').FileTransport;
const moment = require('moment');

class CoustomTransport extends FileTransport {
 constructor(options, ctx) {
  super(options);
  this.ctx = ctx;
 }

 log(level, args, meta) {
  const prefixStr = this.buildFormat(level);
  for (let i in args) {
   if (args.hasOwnProperty(i)) {
    if (parseInt(i, 10) === 0) {
     args[i] = `${prefixStr}${args[i]}`;
    }
    if (parseInt(i, 10) === args.length - 1) {
     args[i] += '\n';
    }
   }
  }

  super.log(level, args, meta);
 }

 buildFormat(level) {
  const timeStr = `[${moment().format('YYYY-MM-DD HH:mm:ss.SSS')}]`;
  const threadNameStr = `[${process.pid}]`;
  const urlStr = `[${this.ctx.request.url}]`
  return `${timeStr}${threadNameStr}${urlStr}`;
 }

 setUserId(userId) {
  this.userId = userId;
 }
}

module.exports = CoustomTransport;

我們通過 logger.info('Hello World')去打印日志,格式則顯示為我們自定義的格式。

到這,自定義日志格式解決了,那我們?nèi)绾潍@取每次請求的信息呢?這里就要借助Egg.js框架對Context的擴展功能, Context是請求級別的對象,我們在Context的原型上擴展方法可以拿到該對象帶有的每次請求的信息。

//CustomLogger.js
const Logger = require('egg-logger').Logger;
const CoustomTransport = require('./CoustomTransport.js');

module.exports = function(ctx){
 const logger = new Logger();
 logger.set('file', new CoustomTransport({
  level: 'INFO',
  file: 'app.log'
 }, ctx));
 return logger;
};

// app/extend/context.js
/*
* Context對象擴展
* */
const Logger = require('egg-logger').Logger;
const CoustomTransport = require('./CoustomTransport');
const CustomLogger = require('./CustomLogger');
module.exports = {
 get swLog() {
  return CustomLogger(this);
 }
};

調(diào)用

// app/controller/home.js
module.exports = app => {
 class HomeController extends app.Controller {
  async index() {
   this.ctx.swLog.info('Hello World');
  }
 }
 return HomeController;
};

結(jié)果

[2018-11-02 19:25:09.665][22896][/] Hello World

到此,我們就能完整的自定義請求級別的日志了。

總結(jié)

以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。

相關(guān)文章

  • 全面解析JavaScript中“&&”和“||”操作符(總結(jié)篇)

    全面解析JavaScript中“&&”和“||”操作符(總結(jié)篇)

    這篇文章主要介紹了全面解析JavaScript中“&&”和“||”操作符(總結(jié)篇)的相關(guān)資料,需要的朋友可以參考下
    2016-07-07
  • JavaScript操作URL的相關(guān)內(nèi)容集錦

    JavaScript操作URL的相關(guān)內(nèi)容集錦

    這篇文章主要介紹了JavaScript操作URL的相關(guān)內(nèi)容集錦的相關(guān)資料,需要的朋友可以參考下
    2015-10-10
  • JavaScript中Array實例方法filter的實現(xiàn)原理

    JavaScript中Array實例方法filter的實現(xiàn)原理

    filter() 方法創(chuàng)建一個新數(shù)組,其中包含通過所提供函數(shù)實現(xiàn)的測試的所有元素,本文將給大家介紹JavaScript中Array實例方法filter的實現(xiàn)原理,文中通過代碼示例講解的非常詳細,需要的朋友可以參考下
    2024-03-03
  • 百度前臺js筆試題與答案

    百度前臺js筆試題與答案

    百度前臺js筆試題與答案...
    2007-09-09
  • layer 刷新某個頁面的實現(xiàn)方法

    layer 刷新某個頁面的實現(xiàn)方法

    今天小編就為大家分享一篇layer 刷新某個頁面的實現(xiàn)方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-09-09
  • js實現(xiàn)Select頭像選擇實時預(yù)覽代碼

    js實現(xiàn)Select頭像選擇實時預(yù)覽代碼

    這篇文章主要介紹了js實現(xiàn)Select頭像選擇實時預(yù)覽代碼,涉及javascript動態(tài)遍歷及設(shè)置select選項的技巧,非常簡單實用,需要的朋友可以參考下
    2015-08-08
  • js DOM模型操作

    js DOM模型操作

    文檔對象模型DOM(Document Object Module)定義了用戶操作文檔對象的接口,它使得用戶對HTML有了空前的訪問能力,并使開發(fā)者能將HTML作為XML文檔來處理。
    2009-12-12
  • JavaScript實現(xiàn)鼠標(biāo)移動事件畫筆

    JavaScript實現(xiàn)鼠標(biāo)移動事件畫筆

    這篇文章主要為大家詳細介紹了JavaScript實現(xiàn)鼠標(biāo)移動事件畫筆,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-08-08
  • webpack 自動清理 dist 文件夾的兩種實現(xiàn)方法

    webpack 自動清理 dist 文件夾的兩種實現(xiàn)方法

    這篇文章主要介紹了webpack 自動清理 dist 文件夾的兩種實現(xiàn)方法,本文給大家介紹的非常詳細,感興趣的朋友跟隨小編一起看看吧
    2024-06-06
  • js中hasOwnProperty()方法詳解

    js中hasOwnProperty()方法詳解

    本文主要介紹了js中hasOwnProperty()方法詳解,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-04-04

最新評論