我需要对某些API调用进行事件跟踪(基于处理程序名称),它基本上是一个记录活动的函数。
此刻,我有一个拦截器可以进行此事件跟踪,并且工作正常。
但是问题是只要有错误,我就会使用全局异常过滤器捕获它,并且这会立即返回响应,而无需输入拦截器和事件跟踪代码(我需要类名,处理程序名和返回的数据(如果可用) )。
这是我的设置
app.module.ts
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { MongooseModule } from '@nestjs/mongoose';
import { APP_INTERCEPTOR, APP_FILTER } from '@nestjs/core';
import { AuthModule } from './auth/auth.module';
import { MembersModule } from './members/members.module';
import { DatabaseConfigService } from './_database/database-config.service';
import { EventTrackerService } from './event-tracker/event-tracker.service';
import { LoggingInterceptor } from './_interceptors/logging.interceptor';
import { EventsTrackerInterceptor } from './_interceptors/events-tracker.interceptor';
import { AllExceptionsFilter } from './_filters/all-exception.filter';
@Module({
imports: [
ConfigModule.forRoot({
isGlobal: true,
}),
MongooseModule.forRootAsync({
useClass: DatabaseConfigService,
}),
AuthModule,
MembersModule,
],
providers: [
{
provide: APP_INTERCEPTOR,
useClass: LoggingInterceptor,
},
{
provide: APP_INTERCEPTOR,
useClass: EventsTrackerInterceptor,
},
{
provide: APP_FILTER,
useClass: AllExceptionsFilter,
},
EventTrackerService,
],
})
export class AppModule {}
events-tracker.interceptor.ts
import {
CallHandler,
ExecutionContext,
Injectable,
NestInterceptor,
} from '@nestjs/common';
import { Observable } from 'rxjs';
import { tap } from 'rxjs/operators';
import { EventTrackerService } from '../event-tracker/event-tracker.service';
@Injectable()
export class EventsTrackerInterceptor implements NestInterceptor {
constructor(private readonly eventTrackerService: EventTrackerService) {}
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
const request = context.switchToHttp().getRequest();
const response = context.switchToHttp().getResponse();
const className = context.getClass().name;
const handler = context.getHandler().name;
return next.handle().pipe(
tap(data => {
this.eventTrackerService.handleEvent(
request.url,
className,
handler,
data,
);
}),
);
}
}
all-exception.filter.ts
import {
ExceptionFilter,
Catch,
ArgumentsHost,
HttpException,
HttpStatus,
Logger,
} from '@nestjs/common';
import { EventTrackerService } from '../event-tracker/event-tracker.service';
@Catch()
export class AllExceptionsFilter implements ExceptionFilter {
constructor(private readonly eventTrackerService: EventTrackerService) {}
catch(exception: any, host: ArgumentsHost) {
const ctx = host.switchToHttp();
const response = ctx.getResponse();
const request = ctx.getRequest();
const status =
exception instanceof HttpException
? exception.getStatus()
: HttpStatus.FORBIDDEN;
const message =
typeof exception.message === 'string'
? exception.message
: exception.message.message;
const errorResponse = {
statusCode: status,
timestamp: new Date().toISOString(),
path: request.url,
message: message || 'Something went wrong',
};
Logger.error(
`${request.method} ${request.url} ${status}`,
JSON.stringify(errorResponse),
'AllExceptionsFilter',
true,
);
response.status(status).json(errorResponse);
}
}
我的最终问题是:尽管抛出异常,如何在拦截器中调用事件跟踪器?
答案 0 :(得分:1)
拦截器有两个选择之一:1)实现catchError
的{{1}}分支,执行逻辑并重新引发错误,或者2)pipe
可以接受一个类似于tap
的对象,并为可观察对象发生的事情运行某些功能。水龙头看起来像
next, error, complete
现在您有了一个return next.handle().pipe(
tap({
next: (data) => this.eventTrackerService.handleEvent(
request.url,
className,
handler,
data,
),
error: (err) => this.eventTrackerService.handleEvent(
request.url,
className,
handler,
error,
)
})
);
来处理成功和错误,但是现在您还传递了错误,而不是将什么数据返回给跟踪器。