- суг команда
- Добавить Автора
- Группа связи QQ: 855833773
задний план
Чтобы лучше анализировать журналы запросов каждого бизнеса, организация сформулировала унифицированную спецификацию печати журналов, такую как:
[time][processId][traceId][userid] Hello World....
После унифицированного формата формат, распечатываемый существующим инструментом бизнес-журнала, не может соответствовать этой спецификации, поэтому нам необходимо его преобразовать.
Мы Node промежуточный уровень удаляем от текущей структуры, используя Egg.js, поэтому ниже описывается, как форматировать пользовательский журнал запросов на Egg.js.
начать
Egg.js поставляется с тремя регистраторами:
- Context Logger
- App Logger
- Agent Logger
Context Logger в основном используется для записи журналов, связанных с запросами. Каждая строка журнала будет автоматически записывать некоторую информацию о текущем запросе в начале, такую как время, ip, URL-адрес запроса и т. д.
App Logger используется для записи журналов на уровне приложений, таких как журналы запуска программ.
Agent Logger используется для записи журналов в многопроцессном режиме.
Мы хотим настроить журнал на уровне запроса, поэтому нужно начать сContext Logger
исследовать, как это сделать. Самое идеальное решение,Context Logger
Он поддерживает настраиваемые пользовательские форматы, которые можно настроить, передав параметры средства форматирования в файле конфигурации конфигурации egg.js.
//config.default.js
exports.customLogger = {
log: {
file: 'appname.log',
formatter: (message)=>{
return `${message.time}${message.processid}`
}
}
}
Но вскоре мы выяснили, что этот способ не работает, и установка этого форматера не работает. В исходном коде Context Logger мы нашли подсказки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 был перезаписан внутренней пользовательской функцией форматирования, а тот, что прописан в конфигурации, работать не будет.
Это невозможно сделать, и вы можете только попытаться реализовать логгер самостоятельно, чтобы решить эту проблему. Для реализации собственного нам необходимо учитывать некоторые моменты, такие как:
- Журнал записывается в файл, а лог ошибок записывается в отдельный файл
- Необходимо иметь возможность пилить бревна по дням или по часам
- Производительность ввода-вывода
Было бы слишком много проблем, если бы они были реализованы сами по себе. К счастью, я узнал, что эти регистраторы Egg основаны наegg-logger
а такжеegg-logrotator
Чтобы достичь, чтобы мы могли стоять на плечах гигантов, чтобы делать вещи.
Context Logger
основывается наegg-logger
изFileTransport
класс для выполнения приземления файла, и в то же времяFileTransport
Также настроен по умолчаниюegg-logrotator
разделение журнала. Итак, нам просто нужно наследоватьFileTransport
class, вы можете реализовать интерфейс, код выглядит следующим образом:
//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;
После реализации класса CoustomTransport мы можем инициализировать регистратор
//CustomLogger.js
const Logger = require('egg-logger').Logger;
const CoustomTransport = require('./CoustomTransport.js');
const logger = new Logger();
logger.set('file', new CoustomTransport({
level: 'INFO',
file: 'app.log'
}));
module.exports = logger;
мы проходимlogger.info(«Hello World»), чтобы распечатать журнал, и формат отображается в нашем пользовательском формате.
На этом этапе настраиваемый формат журнала решен, так как же нам получить информацию о каждом запросе? Здесь нам нужно использовать фреймворк Egg.js для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);
}
};
передача
// app/controller/home.js
module.exports = app => {
class HomeController extends app.Controller {
async index() {
this.ctx.swLog.info('Hello World');
}
}
return HomeController;
};
результат
[2018-11-02 19:25:09.665][22896][/] Hello World
На этом этапе мы можем полностью настроить журнал уровня запроса.