Nodejs / Express / Winston logger: как элегантно поместить req.headers.username в формат журнала?

#node.js #express #logging #winston #express-winston

#node.js #экспресс #регистрация #уинстон #экспресс-уинстон

Вопрос:

Мой сервер nodejs / Express js использует Winston регистратор.

src/utils/logger.ts :

 import winston from 'winston' import moment from 'moment'; import os from 'os'; import process from 'process'; import request from 'express';   const levels = {  error: 0,  warn: 1,  info: 2,  http: 3,  debug: 4, }  const level = () =gt; {  return 'debug' }  const colors = {  error: 'red',  warn: 'yellow',  info: 'green',  http: 'magenta',  debug: 'white', } winston.addColors(colors)  const timezonedTime = () =gt; {  return moment().local().format('YYYY-MMM-DD hh:mm:ss:ms');  };     const format_string = winston.format.combine(  winston.format.timestamp({format: timezonedTime}),  winston.format.colorize({ all: true }),  winston.format.printf(  (info) =gt; `${info.timestamp} ${os.hostname()} ${process.pid} ${info.level}: ${info.message}`,  ), )  const format_json = winston.format.combine(  winston.format.timestamp({format: timezonedTime}),  winston.format.colorize({ all: true }),  winston.format.printf(  (info) =gt; `${info.timestamp} ${os.hostname()} ${process.pid} ${info.level}: ${info.message}`,  ),  winston.format.json(), )   const options = {  conosle: {  format: format_string,  level: 'info',  handleExceptions: true,  json: false,  colorize: true,  },   error_logfile: {  filename: 'logs/error.log',  level: 'error',  format: format_string,  handleExceptions: true,  },    all_logfile: {   filename: 'logs/all.log',   format: format_string   },   all_logfile_json: {   filename: 'logs/all_json.log',  format: format_json  }  };  const transports = [  new winston.transports.Console(options.conosle),  new winston.transports.File(options.error_logfile),  new winston.transports.File(options.all_logfile),  new winston.transports.File(options.all_logfile_json), ]  const Logger = winston.createLogger({  level: level(),  levels,  transports, })  export default Logger    

Мое приложение разработано таким образом, что до тех пор, пока пользователь вошел в свою учетную запись, заголовок запроса будет содержать username поле.

Я хочу включить это username в каждое сообщение журнала, вызванное функциями в конечных точках api. Прямо сейчас я делаю:

/src/маршруты.ts:

 app.get('/api/organizations/project', organizations.getProject);   

И:

 export const getProject = catchErrors( async (req, res) =gt; {   const username = req.header('username');  if (!username) {  Logger.warn(`no req.headers.username found!`);  throw new NoUsernameError();  }    const user = await findUserWithOrganizationsByUsername(username);  const userId = user.id;   const userType = user.userType;   Logger.info(`User ${req.headers.username} has id and type ${userId}, ${userType};`);    const organizationId = req.query.organizationId;     const organization = await findEntityOrThrow(Organization, organizationId, {  relations: ['users']  });   Logger.info(`User ${req.headers.username}: got organization`);    ...   

В основном на многих этапах кода бизнес-логики мне нужно зарегистрировать сообщение req.headers.username , содержащееся в нем, точно так же, как level и timestamp во всех записях журнала.

Есть ли элегантный способ вставить это? Я не хочу этого делать

 Logger.info(`User ${req.headers.username} ....bla bla bla ... `);  

в каждой строке регистратора.