gpt4 book ai didi

How can I use fastify request logger in other classes without having to pass it as a parameter?(如何在不将其作为参数传递的情况下在其他类中使用Fastify请求记录器?)

转载 作者:bug小助手 更新时间:2023-10-28 10:18:56 32 4
gpt4 key购买 nike



I'm new in nodejs, I'm using fastify and I want to be able to use the req.logger in all the classes functions of the flow, this because I have a the request-id on req.logger, the first solution that came to my mind is to pass as a parameter the logger through all the function/classes but I think that would make the code kind of dirty, here is an example of my code:

我是NodeJS的新手,我正在使用Fastify,我希望能够在流的所有类函数中使用req.logger,这是因为我在req.logger上有一个请求id,我想到的第一个解决方案是将记录器作为参数传递给所有函数/类,但我认为这会使代码变得有点脏,以下是我的代码示例:


app.ts

App.ts


import pino from 'pino';
import fastify from 'fastify';

declare module 'fastify' {
interface FastifyInstance {
// augment fastify instance with the config object types
config: Config;
}
}

function build() {

const app = fastify({
logger: pino({
name: process.env.NAME,
level: process.env.LOG_LEVEL,
}),
disableRequestLogging: true,
requestIdHeader: 'correlation-id',
requestIdLogLabel: 'correlationId',
});
// register plugins

app.register(apiRoutes, fastify => ({
getObjectUseCase: new GetObjectUseCase(
new TestClass()),
}));

return app;
}
export { build };

routes.ts

routes.ts


import { FastifyPluginCallback } from 'fastify';
import { StatusCodes } from 'http-status-codes';

export const apiRoutes: FastifyPluginCallback<RoutesOpts> = async (fastify, options, done) => {
const getObjectUseCase = options.getObjectUseCase;

fastify.get<object>('/v1/api/:id', async (req, reply) => {
const id = req.params.payoutId;
req.logger.info('This is a logger print'); // has the correlation id inside it while printing
const storedObject = await getObjectCase.execute(id);
reply.code(StatusCodes.OK).send(storedObject);
});
}

GetObjectUseCase.ts

GetObjectUseCase.ts


export class GetObjectUseCase {
private anotherClass: TestClass;

constructor(anotherClass: TestClass) {
this. anotherClass = anotherClass;
}

async execute(id: string): Promise<StoredObject> {
// I want to use the logger here with have the correlation id on it without having to pass it as an argument on the method, how is it posible?
return this.anotherClass.getById(id);
// also needed to use it inside anotherClass.getById so I will need to pass the logger also in the method

}
}

Hope I have been clear.
Thanks!

希望我已经说清楚了。谢谢!


更多回答

Did you call new GetObjectUsecase? You could set as construction parameter

您是否调用了新的GetObjectUsecase?您可以设置为构造参数

@ManuelSpigolon thanks for the response, sorry just updated the question, the GetObjectUseCase instance is created while registering the routes, if I put the logger on the constructor param I would need to create a new instance of the object on each request and also propagate the logger to all the classes/funtions that are used inside GetObjectUseCase, that's what I'm trying to avoid, do you know any other possible workaround?

@ManuelSpigolon感谢您的回复,对不起,刚刚更新了问题,GetObjectUseCase实例是在注册路由时创建的,如果我将记录器放在构造函数参数上,我将需要在每个请求上创建对象的新实例,并将记录器传播到GetObjectUseCase中使用的所有类/函数,这就是我试图避免的,您知道其他可能的解决方法吗?

优秀答案推荐

This may not be the best or only way to do it, but this has worked for me in the past.

这可能不是最好的或唯一的方法,但这在过去对我很管用。


Typically I structure my projects with an app.ts that just instantiates my FastifyInstance and then exports the log from that created instance. This allows me to use the log where ever I want to.

通常,我使用app.ts来组织我的项目,该app.ts只是实例化我的FastifyInstance,然后从创建的实例中导出日志。这使我可以在任何我想使用的地方使用日志。


It looks something like this.

它看起来像这样。


app.ts

App.ts


import fastify from 'fastify';

const app = fastify({ logger: true /* Your logging configuration */ });

export default app;
export const logger = app.log; // Allows me to log where ever I want.

server.ts

Server.ts


import app from './app';

... // All your fastify configuration and other stuff.

app.listen({ ... });

Now I can use the logger outside of fastify stuff.

现在我可以在Fastify内容之外使用记录器了。


get-object-use-case.ts

Get-object-use-case.ts


import { logger } from './app'; // Import your fastify logger to use in this class.

export class GetObjectUseCase {
private anotherClass: TestClass;

constructor(anotherClass: TestClass) {
this. anotherClass = anotherClass;
}

async execute(id: string): Promise<StoredObject> {
logger.info({/* Whatever you want to log here. */}); // Now you can use the logger here.
return this.anotherClass.getById(id); // You can just import the logger into the TestClass file to get logging enabled there.
}
}

This even allows you to log before your FastifyInstance is started. Check out this codesandbox for a running example.

这甚至允许你在你的FastifyInstance启动之前登录。查看这个codesandbox以获得一个运行的示例。



My solution

我的解决方案


/utils/logger.ts

/utils/logger.ts


import { FastifyBaseLogger } from 'fastify';

export const logger: {
instance: FastifyBaseLogger | null;
init: (fastifyLogger: FastifyBaseLogger) => void;
get: () => FastifyBaseLogger | null;
} = {
instance: null,
init: (fastifyLogger: FastifyBaseLogger) => (logger.instance = fastifyLogger),
get: () => logger.instance,
};

/app.ts

/app.ts


export const app = (options: { logger: { level?: LogLevel } | boolean }) => {
const fastify = Fastify({
...options,
});

...
logger.init(fastify.log);
...

return fastify;
};

randomFile.ts

RandomFile.ts


import { logger } from 'src/utils/logger';

const randomFunction = () => {
...
logger.get()?.debug('🛠️ ~ Test debug log');
...
}

更多回答

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com