我在 nest 中有一个全局记录器模块,它记录到云日志服务。我正在尝试创建一个添加日志记录功能的类方法装饰器。但是我正在努力如何在装饰器中注入全局嵌套模块的服务,因为我在文档中找到的所有依赖注入机制依赖都是基于类或类属性的注入。
export function logDecorator() {
// I would like to inject a LoggerService that is a provider of a global logger module
let logger = ???
return (target: any, propertyKey: string, propertyDescriptor: PropertyDescriptor) => {
//get original method
const originalMethod = propertyDescriptor.value;
//redefine descriptor value within own function block
propertyDescriptor.value = function(...args: any[]) {
logger.log(`${propertyKey} method called with args.`);
//attach original method implementation
const result = originalMethod.apply(this, args);
//log result of method
logger.log(`${propertyKey} method return value`);
};
};
}
Run Code Online (Sandbox Code Playgroud)
更新:每个请求一个简单的例子 基本的例子是使用我的自定义记录器(在我的例子中记录到云服务)记录对服务方法的调用:
class MyService {
@logDecorator()
someMethod(name: string) {
// calls to this method as well as method return values would be logged to CloudWatch
return `Hello ${name}`
}
}
Run Code Online (Sandbox Code Playgroud)
另一个扩展用例是捕获一些错误,然后记录它们。我有很多这种逻辑可以在我的所有服务中重用。
flo*_*nkt 14
好的,找到了解决办法。以防其他人偶然发现这一点。首先请记住装饰器是如何工作的——它们是基于类构造函数的,而不是基于实例的。
就我而言,我希望将我的记录器服务注入到类实例中。所以解决办法就是告诉装饰器中的Nest,将LoggerService注入到包含被装饰方法的类的实例中。
import { Inject } from '@nestjs/common';
import { LoggerService } from '../../logger/logger.service';
export function logErrorDecorator(bubble = true) {
const injectLogger = Inject(LoggerService);
return (target: any, propertyKey: string, propertyDescriptor: PropertyDescriptor) => {
injectLogger(target, 'logger'); // this is the same as using constructor(private readonly logger: LoggerService) in a class
//get original method
const originalMethod = propertyDescriptor.value;
//redefine descriptor value within own function block
propertyDescriptor.value = async function(...args: any[]) {
try {
return await originalMethod.apply(this, args);
} catch (error) {
const logger: LoggerService = this.logger;
logger.setContext(target.constructor.name);
logger.error(error.message, error.stack);
// rethrow error, so it can bubble up
if (bubble) {
throw error;
}
}
};
};
}
Run Code Online (Sandbox Code Playgroud)
这提供了在方法中捕获错误、将它们记录在服务上下文中并重新抛出它们(以便您的控制器可以处理用户响应)或不重新抛出的可能性。就我而言,我还必须在这里实现一些与事务相关的逻辑。
export class FoobarService implements OnModuleInit {
onModuleInit() {
this.test();
}
@logErrorDecorator()
test() {
throw new Error('Oh my');
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2749 次 |
| 最近记录: |