Mohamed Oraby
Mohamed Oraby

Reputation: 1036

Is there a way to log response body in Morgan?

I want to log the response body in my logs file

I have tried morgan-body but I want to log the response in a file not the console

The following code will log the request body, so is there a way to log the response too?

morgan.token('body', function (req, res) { return JSON.stringify(req.body) });

app.use(morgan(':method :url :status :response-time ms - :res[content-length] :body - :req[content-length]', { 
  stream: logger.successLogStream,
  skip: function (req, res) { return res.statusCode >= 400 }
 }));

 app.use(morgan(':method :url :status :response-time ms - :res[content-length] :body - :req[content-length]', { 
  stream: logger.errorLogStream,
  skip: function (req, res) { return res.statusCode < 400 }
 }));

For example I want to following error message to be logged

return res.status(400).send({ "message": "Campaign id is not defined" })

Upvotes: 5

Views: 12477

Answers (4)

Venkat Cpr
Venkat Cpr

Reputation: 163

use method overriding

   app.use(function (req, res, next) {
var json = res.json
res.json = function (obj) {
    function loging(obj) {
        console.log(obj)
        console.log(req.body)
    }
    loging(obj)

    json.call(this, obj)
}
next()
}

Upvotes: 0

Shrirang
Shrirang

Reputation: 1336

Updating the above answers with node v16 and morgan custom log format

middleware.ts

 export const setResponseBody = (req: any, res: any, next: any) => {
    const oldWrite = res.write,
        oldEnd = res.end,
        chunks: any = [];

    res.write = function (chunk: any) {
        chunks.push(Buffer.from(chunk));
        oldWrite.apply(res, arguments);
    };

    res.end = function (chunk: any) {
        if (chunk) {
            chunks.push(Buffer.from(chunk));
        }
        const body = Buffer.concat(chunks).toString('utf8');
        res.__custombody__ = body;
        oldEnd.apply(res, arguments);
    };
    next();
};

app.ts

morgan.token('responseBody', function (req, res: any) {
    if (res['statusCode'] != 200) {
        return res['__custombody__'] || null;
    }
    return null;
});
const app = express();
app.use(morgan('responseBody=:responseBody'));

Upvotes: 2

Abdusamad
Abdusamad

Reputation: 41

you can use this

const app = express()
const originalSend = app.response.send

app.response.send = function sendOverWrite(body) {
  originalSend.call(this, body)
  this.__custombody__ = body
}

morgan.token('res-body', (_req, res) =>
  JSON.stringify(res.__custombody__),
)

...

app.use(express.json())
app.use(express.urlencoded({ extended: true }))
app.use(morgan(loggerFormat, { stream: logStream }))
app.use(...routers)

Upvotes: 3

Xiaoyiyu
Xiaoyiyu

Reputation: 19

Override the res.send / res.json method, customize :res-body and be careful to put morgan after the routes

morgan.token('resBody', (req, res) => res.resBody);
res.send = (...args) => {
    res.oldsend(...args);
    res.resBody = JSON.stringify(args);
};
app.use(routes)
app.use(morgan(...))

Upvotes: 1

Related Questions