如何在Nestjs中记录GRPC请求和响应?



我正在尝试在我的nestjs项目中记录grpc请求和响应。中间件似乎可以帮助我做到这一点。然而,nesjs中的中间件仅用于HTTP。那么,还有其他方法可以解决我的问题吗?也许拦截器?

基于本github上的示例。我使用以下代码记录请求/响应,并为gRPC客户端编辑日志:

// users.module.ts
@Module({
imports: [
ConfigModule.forRoot(),
ClientsModule.registerAsync([
{
name: USERS_PACKAGE,
imports: [ConfigModule],
useFactory: async (configService: ConfigService) => ({
transport: Transport.GRPC,
options: {
package: 'users',
credentials: credentials.createInsecure(),
protoPath: join(__dirname, './proto/users.proto'),
url: configService.get<string>('services.users.url'),
loader: { keepCase: true },
channelOptions: {
interceptors: [
(options, nextCall) => {
const logger: Logger = new Logger('UsersModule');
const redactedFields: string[] = configService.get<string[]>('logger.redact.fields');
const path: string = options.method_definition.path;
logger.verbose('-------------------------------------- GRPC CALL ----------------------------------');
const interceptingCall = new InterceptingCall(
nextCall(options),
GrpcLoggingInterceptor(path, redactedFields),
);
return interceptingCall;
},
],
},
},
}),
inject: [ConfigService],
},
]),
],
providers: [GetUsersClient],
exports: [GetUsersClient],
})
export class UsersModule {}

用于拦截grpc请求的grpc日志拦截器

// grpc-logging.interceptor.ts
import { Logger } from '@nestjs/common';
export const GrpcLoggingInterceptor = (path: string, redactedFields: string[]) => {
const logger: Logger = new Logger('GrpcLoggingInterceptor');
function redact(data: string): string {
return JSON.stringify(data, (k, v) => (redactedFields.includes(k) ? `[Redacted]` : v));
}
return {
start: function (metadata, listener, next) {
const newListener = {
onReceiveMetadata: function (metadata, next) {
logger.verbose(`response metadata : ${redact(metadata)}`);
next(metadata);
},
onReceiveMessage: function (message, next) {
logger.verbose(`response body : ${redact(message)}`);
next(message);
},
onReceiveStatus: function (status, next) {
logger.verbose(`response status : ${redact(status)}`);
next(status);
},
};
next(metadata, newListener);
},
sendMessage: function (message, next) {
logger.verbose(`path: ${JSON.stringify(path)}`);
logger.verbose(`request body : ${redact(message)}`);
next(message);
},
};
};

要编辑的字段:

// config.yaml
logger:
redact:
fields:
- token
- password
- address
- telephone

你可以使用拦截器。事实上,这正是我的ogmaininterceptor所做的,甚至还有一个gRPC插件。一般来说,就是像

这样简单的东西
@Injectable()
export class LoggingInterceptor {
intercept(context: ExecutionContext, next: CallHandler) {
const start = Date.now()
console.log('Request start');
return next.handle().pipe(
tap((data) => {
console.log(`Request took ${Date.now() - start}ms. Response length: ${Buffer.from(JSON.stringify(data) ?? '').length} bytes`);
})
);
}
}

将是为

写一些东西的简单的第一步。

最新更新