Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

Node.jsでログにUser IDを自動出力

背景

ECサイトなどを運用する場合、ログにユーザの識別IDが付与されていると調査時に行動を把握することが容易なため便利です。
そこで今回はNode.js(Express)で実現してみたいとおもいます。

実装

userId保持用の箱を準備

ログを出力する際、userIdを参照できるようにシングルトンなクラスを作成しておきます。

requestContext.js
class RequestContext {
  init(userId) {
    this.userId = userId
  }

  getUserId() {
    return this.userId
  }
}

export default new RequestContext()

Expressサーバ

下記の記述を、他のルーティングの上部に配置します。

express/app.js
import requestContext from 'path/to/requestContext'

app.use((req, res, next) => {
  if (!req.session.userId) {
    // sessionにuesrIdがない場合は、uuidを設定
    req.session.userId = uuid.v4()
  }
  // 事前に作成したrequestContextに、userIdを設定
  requestContext.init(req.session.userId)
  next()
})

※ session管理には、express-sessionを使っています。
next()では、下部に処理を委ねます。

winston

今回loggerにはwinstonを用います。
例ではtimestampとログレベルも出力してます。

logger.js
import path from 'path'
import { createLogger, format, transports } from 'winston'
import config from 'config'
import requestContext from './requestContext'

const { combine, timestamp, printf } = format
const logDir = path.resolve('log')

const logFormatter = printf(
  ({ level, message, timestamp }) =>
    `[${timestamp}] [${level.toUpperCase()}] [${requestContext.getUid()}] ${message}`
)

export const logger = createLogger({
  level: config.get('logger.level.default') || 'info',
  format: combine(timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }), logFormatter),
  transports: [
    new transports.Console(),
    new transports.File({
      filename: `${logDir}/application.log`
    })
  ]
})

export const apiLogger = createLogger({
  level: config.get('logger.level.api') || 'info',
  format: combine(timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }), logFormatter),
  transports: [
    new transports.Console(),
    new transports.File({
      filename: `${logDir}/api.log`
    })
  ]
})

検証

logger呼び出し例

import logger from 'path/to/logger'

logger.error('test!!')

出力例

application.log
[2019-10-30 11:08:18] [ERROR] [6ffd3f48-c967-43ac-88e3-d6886c82d3a5] test!!
berry99
主に実装メモ保存用
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away