Nodejs AsyncLocalStorage getStore() return undefined

3.9k views Asked by At

I read this post AsyncLocalStorage for Easy Context Passing in Node.js I try to get logId in my logs, but i cant, beacause asyncLocalStorage.getStore() return undefined. It seems that context was lost inside MyLogger class. How to solve it?

Here is my express App

  const asyncLocalStorage = new AsyncLocalStorage();

  app.use((req, res, next) => {
          asyncLocalStorage.run(new Map(), () => {
            asyncLocalStorage.getStore().set("requestId", uuid());
            next();
          });
        });
    
    module.exports.asyncLocalStorage = asyncLocalStorage;

Here is MyLogger class

   static log(logId, className, text) {
    const { asyncLocalStorage } = require("../server.js");
    const store = asyncLocalStorage.getStore()
    console.log(this._getBaseStaticLog(logId, logTypes.LOG, text, className));
  }
2

There are 2 answers

2
Masquitos On BEST ANSWER

I solve the problem. The problem was that i lose context due to bodyparser middleware. I change that middleware before set context, and now its ok. Was:

app.use((req, res, next) => {
  asyncLocalStorage.run(new Map(), () => {
    asyncLocalStorage.getStore().set("requestId", uuid());
    next();
  });
});

// body parser
app.use(
  bodyParser.json({
    limit: "10mb"
  })
);

Change:

// body parser
app.use(
  bodyParser.json({
    limit: "10mb"
  })
);

app.use((req, res, next) => {
  asyncLocalStorage.run(new Map(), () => {
    asyncLocalStorage.getStore().set("requestId", uuid());
    next();
  });
});

And now its ok)

0
Longwelwind On

I encountered the same issue when using express.json(). I also had to change the order of my middleware to make the AsyncLocalStorage work properly, like this:

app.use(loggerMiddleware);

app.use(express.json());

app.use((req, res, next) => {
    LOGGER.info("new request", {
        originalUrl: req.originalUrl,
        body: req.body,
    });
    next();
});

To this:

app.use(express.json());

app.use(loggerMiddleware);

app.use((req, res, next) => {
    LOGGER.info("new request", {
        originalUrl: req.originalUrl,
        body: req.body,
    });
    next();
});

Where loggerMiddleware is the logger that runs asyncLocalStorage.run() and LOGGER.info is my logger that access the content of asyncLocalStorage.

This seems to be documented: https://github.com/expressjs/express/issues/4396