yalpsideman
yalpsideman

Reputation: 23

How to log client IP address with express winston

I am using express-winston as a middleware for express to log all requests and their response codes. This is my code

const myFormat = printf(info => {
  console.log(info)
  return `${info.timestamp} ${info.level}: ${info.message}`
})


    app.use(expressWinston.logger({
      transports: [
        new winston.transports.Console(),
        new winston.transports.File({ filename: "access.log", level: "info" })
      ],
      format: winston.format.combine(
        winston.format.timestamp(),
        myFormat
      ),
      meta: true,
      expressFormat: true, 
    }));

app.set('trust proxy', true)
app.use(cors());

The info variable in myFormat does not contain the user IP adress.req.headers['x-forwarded-for'] and req.connection.remoteAddress are both not accessible there. How can I get the address when building the log in the myFormat function?

Upvotes: 1

Views: 5802

Answers (1)

Samuel Goldenbaum
Samuel Goldenbaum

Reputation: 18929

You can build up dynamic meta as per the example below. This will result in the properties available on info.httpRequest where you can format info.httpRequest.remoteIp as needed.

Example:

class myFormat extends Transport {
    constructor(opts) {
        super(opts);
    }

    log(info, callback) {
        setImmediate(() => {
            this.emit('logged', info);
        });
        callback();
    }
};

app.use(expressWinston.logger({
    transports: [
      new winston.transports.Console(),
      new myFormat()
    ],
    metaField: null, //this causes the metadata to be stored at the root of the log entry
    responseField: null, // this prevents the response from being included in the metadata (including body and status code)
    requestWhitelist: ['headers', 'query'],  //these are not included in the standard StackDriver httpRequest
    responseWhitelist: ['body'], // this populates the `res.body` so we can get the response size (not required)

    dynamicMeta: (req, res) => {
        const httpRequest = {}
        const meta = {}
        if (req) {
            meta.httpRequest = httpRequest
            httpRequest.requestMethod = req.method
            httpRequest.requestUrl = `${req.protocol}://${req.get('host')}${req.originalUrl}`
            httpRequest.protocol = `HTTP/${req.httpVersion}`
            // httpRequest.remoteIp = req.ip // this includes both ipv6 and ipv4 addresses separated by ':'
            httpRequest.remoteIp = req.ip.indexOf(':') >= 0 ? req.ip.substring(req.ip.lastIndexOf(':') + 1) : req.ip   // just ipv4
            httpRequest.requestSize = req.socket.bytesRead
            httpRequest.userAgent = req.get('User-Agent')
            httpRequest.referrer = req.get('Referrer')
        }
        return meta
    }
}));

More Info under meta field on the docs.

Upvotes: 2

Related Questions