Feature(s) impacted
I’m using the forestadmin/agent mounted on an express app (only the admin is running on this app though) and I’m setting up Sentry to monitor perf and bugs.
I want to identify the user doing the request, but I don’t understand how I can tap into the agent.
Today, I’m adding a middleware to read and decode the authorization header but maybe there’s a cleaner solution.
Context
- Project name: Muzzo
- Team name: Muzzo
- Environment name: Local
- Agent type & version:
"@forestadmin/agent": "^1.8.8",
"@forestadmin/datasource-sql": "^1.3.0",
"@forestadmin/datasource-toolkit": "^1.4.2"
Also, I’ve noticed something I still don’t understand. When I add a middleware before mounting the agent, I can see it’s executed but when I add it after mounting the agent, it doesn’t seem to be executed.
So I can’t tap into forest context after mounting it
My Setup
const myMiddlewareFactory = (message:string) => (req, res, next) => {
console.log('middleware:', message);
next();
}
const app = express();
app.use(myMiddlewareFactory('before')); // I see logs
await agent.mountOnExpress(app).start();
app.use(myMiddlewareFactory('after')); // can't see logs
app.listen(env.PORT);
Hey @ajubin, and welcome to our community
We do provide a way to customize log using the logger
, loggerLevel
, and customizeErrorMessage
options with documentation here. However, there are currently no way to retrieve the user this way.
Depending on your needs, hooks could maybe also do the trick.
Also, I’ve noticed something I still don’t understand. When I add a middleware before mounting the agent, I can see it’s executed but when I add it after mounting the agent, it doesn’t seem to be executed.
Indeed, after
will not be called on forest routes, but that’s related to how express middleware works.
For eg, if you add a route definition after your after
middleware, you should be able to see before
and after
message being displayed.
Let me know if that helps.
Hi @jeffladira,
thanks for the quick answer and the explanation about forest middleware, as I’m not using them on other projects, maybe I can make silly mistakes
I’ve looked at logger
, loggerLevel
and customizeErrorMessage
but I’m not sure if it’s the appropriate way to report error on Sentry (a monitoring tool)
For the hooks, it’s only at a collection level so it can’t do the trick in my case
Then your solution would be the cleanest we offer right now.
If you want to retrieve info from a route level, express middleware would be the best one.
If you want to retrieve error messages on sentry (Without user infos), Hooks or logger
, loggerLevel
and customizeErrorMessage
would be the way to go.
If you want to retrieve both in a single line, then this is not currently supported, and I can push this to our product board.
Let me know
For the record, here is what I did
To identify user in Sentry
// identify user based on jwt
app.use((req, res, next) => {
if (req.headers.authorization) {
const [, jwtToken] = req.headers.authorization.split(' ');
const decodedToken = jwt.decode(jwtToken, {
complete: true,
});
if (decodedToken.payload.email) {
Sentry.setUser({ email: decodedToken.payload.email });
}
}
next();
});
To report error in Sentry
// on createAgent function
const agent = createAgent({
logger: (level, data, error) => {
// Default logger copy pasted from: https://github.com/ForestAdmin/agent-nodejs/blob/95ee789933417ccde1be26c0ba587b38fd7d4264/packages/agent/src/utils/options-validator.ts#LL20C8-L20C8
const loggerLevel = 'Info';
const loggerPrefix = {
Debug: '\x1b[34mdebug:\x1b[0m',
Info: '\x1b[32minfo:\x1b[0m',
Warn: '\x1b[33mwarning:\x1b[0m',
Error: '\x1b[31merror:\x1b[0m',
};
const levels = Object.keys(loggerPrefix);
if (levels.indexOf(level) >= levels.indexOf(loggerLevel)) {
// eslint-disable-next-line no-console
console.error(loggerPrefix[level], data);
}
// end of default logger
if (level === 'Warn' || level === 'Error') {
Sentry.captureException(error);
}
},
})
1 Like