10

I'm using node.js and express to handle HTTP requests and responses. By using the http.ServerRequest event, I can add a hook in and log HTTP requests. There doesn't seem to be a similiar event for http.ServerResponse and I am wondering how to log all the HTTP responses with one piece of code that my server sends?

2
  • There is no way to do this. "request" is emitted by HttpServer which express extends. The easiest way would be to overwrite .send or .end with a thin logging proxy. Commented Jan 4, 2012 at 0:19
  • Thanks, I ended up monkey-patching the http.ServerResponse methods - it worked great. Commented Jan 4, 2012 at 20:42

4 Answers 4

10

I created a package that does such a thing, out of a similar need. Check out express-request-logger

The heart of the program is like this, it contains some extra code so you can have your own key-value map of data that gets logged per request:

// Save the real end that we will wrap
var rEnd = res.end;

// To track response time
req._rlStartTime = new Date();

// Proxy the real end function
res.end = function(chunk, encoding) {
  // Do the work expected
  res.end = rEnd;
  res.end(chunk, encoding);

  // And do the work we want now (logging!)

  // Save a few more variables that we can only get at the end
  req.kvLog.status = res.statusCode;
  req.kvLog.response_time = (new Date() - req._rlStartTime);

  // Send the log off to winston
  var level = req.kvLog._rlLevel;
  delete req.kvLog._rlLevel;
  logger.log(level, '', req.kvLog);
};

The above code runs as middleware in express. Take a look at the code, and if you have further questions, get in touch with me on here or github.

Sign up to request clarification or add additional context in comments.

2 Comments

In current versions of Node.js, res should generate a "finish" event which you can use instead of proxying the end method.
I get: TypeError: winston.loggers is not a constructor
10

It is no longer needed to monkeypatch, as long as there is a finish event emitted on end() function since node.js 0.8.12.

Actually, it was initially published as end in 0.8.8 (check also this) but it broke writable streams' duplexes, so it was renamed to finish.

3 Comments

I've checked in Node 0.8.14 and 0.8.23 and end is emitted, not finish. The commits you've linked are included in 0.9 / 0.10 branches (it's now being displayed by GH below the commit message since a couple of weeks ago).
Is is possible to get the response message on the finish event?
end seems to work for me too, whereas finish does not. I'm confused!
3

If you only want to log (requests and/or responses), check out express-winston. Unlike morgan, it can even log the request/response body.

Example in coffeescript:

expressWinston.requestWhitelist.push('body')
expressWinston.responseWhitelist.push('body')
app.use(expressWinston.logger({
      transports: [
        new winston.transports.Console({
          json: true,
          colorize: true
        })
      ],
      meta: true, // optional: control whether you want to log the meta data about the request (default to true)
      msg: "HTTP {{req.method}} {{req.url}}", // optional: customize the default logging message. E.g. "{{res.statusCode}} {{req.method}} {{res.responseTime}}ms {{req.url}}"
      expressFormat: true, // Use the default Express/morgan request formatting, with the same colors. Enabling this will override any msg and colorStatus if true. Will only output colors on transports with colorize set to true
      colorStatus: true, // Color the status code, using the Express/morgan color palette (default green, 3XX cyan, 4XX yellow, 5XX red). Will not be recognized if expressFormat is true
      ignoreRoute: function (req, res) { return false; } // optional: allows to skip some log messages based on request and/or response
    }));

1 Comment

This is the modern and perhaps most correct answer for today.
-6

If you're using express' res.send() for all responses, and you don't mind inserting code into the express module, you can insert into

.../node_modules/express/lib/response.js:

43 res.send = function(body, headers, status){
44   console.log("\n...your log text here..." + body);
45   // allow status as second arg
46   if ('number' == typeof headers) {
47     status = headers,
48     headers = null;
49   }

I don't think you can listen for a non-error event - "close" doesn't seem to fire upon res.send();. I guess it's because send() is always called somewhere in your code.

1 Comment

This is a bad idea. See the other answers, instead.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.