Skip to main content
deleted 2 characters in body; edited title
Source Link
Jamal
  • 35.2k
  • 13
  • 134
  • 238

Node/Express: Logging and error middleware

But depending on if the NODE_ENVNODE_ENV is production, the logging middleware should log out the specific error:

Node/Express: Logging and error middleware

But depending on if the NODE_ENV is production, the logging middleware should log out the specific error:

Logging and error middleware

But depending on if the NODE_ENV is production, the logging middleware should log out the specific error:

format JSON
Source Link
Phrancis
  • 20.5k
  • 6
  • 70
  • 155
{
  "name":"Example",
  "hostname":"",
  "pid":18322,
  "level":40,
  "payload":{
    "name":"BadRequest",
    "message":"A specific error message",
    "statusCode":400,
    "errorCode":400
  },
  "msg":"400: A specific error message",
  "time":"2017-10-22T15:26:06.824Z",
  "v":0 
}
{"name":"Example","hostname":"","pid":18322,"level":40,"payload":{"name":"BadRequest","message":"A specific error message","statusCode":400,"errorCode":400},"msg":"400: A specific error message","time":"2017-10-22T15:26:06.824Z","v":0}
{
  "name":"Example",
  "hostname":"",
  "pid":18322,
  "level":40,
  "payload":{
    "name":"BadRequest",
    "message":"A specific error message",
    "statusCode":400,
    "errorCode":400
  },
  "msg":"400: A specific error message",
  "time":"2017-10-22T15:26:06.824Z",
  "v":0 
}
Source Link
cuserjuicer
  • 305
  • 2
  • 7
  • 12

Node/Express: Logging and error middleware

I'm looking for code review on the following basic log/error middleware. The logging middleware uses logger.js which has a bunch of methods like log.error() (which makes a request out to error tracking service like Sentry).

The handleErrors middleware is intended to handle any errors that occur in any of the api routes. So, for example, I have a route /api/users and if an error occurs in that request, the catch will execute and pass along the error to the handleErrors middleware.

const getUsers = (req, res, next) => {
  return apiHttpClient.get(req, '/api/users')
    .then(users => res.status(HttpStatus.OK).json(users))
    .catch(err => next(err));
};

The error middleware should create an error context for the client without exposing the specific error. So for example, if a 400 error occurs, the message sent to the browser would look like:

{
  "message": "Bad Request",
  "status": 400
}    

But depending on if the NODE_ENV is production, the logging middleware should log out the specific error:

{"name":"Example","hostname":"","pid":18322,"level":40,"payload":{"name":"BadRequest","message":"A specific error message","statusCode":400,"errorCode":400},"msg":"400: A specific error message","time":"2017-10-22T15:26:06.824Z","v":0}

Usage

express.js

const { logErrors, handleErrors } = require('./errorMiddleware');

// other middleware
// api routes
 
app.use(logErrors())
app.use(handleErrors());

errorMiddleware.js

const log = require('../../logger');
const HttpStatus = require('http-status-codes');

const isServerError = (statusCode) => {
  return statusCode >= HttpStatus.INTERNAL_SERVER_ERROR;
};

const isProdEnv = (env) => {
  return env === 'production';
};

const getStatusCode = (statusCode) => {
  return statusCode || HttpStatus.INTERNAL_SERVER_ERROR;
};

const createErrorContext = (statusCode) => {
  return {
    message: HttpStatus.getStatusText(statusCode),
    status: statusCode
  };
};

const createErrorMessage = (err) => {
  const statusCode = getStatusCode(err.statusCode);
  return `${statusCode}: ${err.message}`;
};

const deleteErrorStack = (env, err) => {
  if (isProdEnv(env)) delete err.stack;
};

const getLogLevel = (statusCode) => {
  return isServerError(statusCode) ? 'error' : 'warn';
};

const logErrors = () => {
  return (err, req, res, next) => {
    const statusCode = getStatusCode(err.statusCode);
    const logLevel = getLogLevel(statusCode);
    const errMessage = createErrorMessage(err);
    const extraData = req.path;

    log[logLevel](errMessage, err, extraData);

    next(err);
  };
};

const handleErrors = () => {
  return (err, req, res, next) => {
    const statusCode = getStatusCode(err.statusCode);
    const errorContext = createErrorContext(statusCode);

    deleteErrorStack(req.app.get('env'), err);
    res.status(statusCode).json(errorContext);
  };
};

module.exports = {
  logErrors: logErrors,
  handleErrors: handleErrors
};