feat: exception logger (#4059)

This commit is contained in:
X1a0t
2023-09-01 12:05:35 +08:00
committed by GitHub
parent b0024080bd
commit d4a83c1c6f
4 changed files with 54 additions and 15 deletions

View File

@@ -3,7 +3,7 @@ import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { ConfigModule } from './config';
import { MetricsModule } from './metrics';
import { BusinessModules } from './modules';
import { BusinessModules, Providers } from './modules';
import { PrismaModule } from './prisma';
import { StorageModule } from './storage';
import { RateLimiterModule } from './throttler';
@@ -17,6 +17,7 @@ import { RateLimiterModule } from './throttler';
RateLimiterModule,
...BusinessModules,
],
providers: Providers,
controllers: [AppController],
})
export class AppModule {}

View File

@@ -7,7 +7,6 @@ import { Plugin } from '@nestjs/apollo';
import { Logger } from '@nestjs/common';
import { Response } from 'express';
import { OPERATION_NAME, REQUEST_ID } from '../constants';
import { Metrics } from '../metrics/metrics';
import { ReqContext } from '../types';
@@ -22,19 +21,10 @@ export class GQLLoggerPlugin implements ApolloServerPlugin {
): Promise<GraphQLRequestListener<GraphQLRequestContext<ReqContext>>> {
const res = reqContext.contextValue.req.res as Response;
const operation = reqContext.request.operationName;
const headers = reqContext.request.http?.headers;
const requestId = headers
? headers.get(`${REQUEST_ID}`)
: 'Unknown Request ID';
const operationName = headers
? headers.get(`${OPERATION_NAME}`)
: 'Unknown Operation Name';
this.metrics.gqlRequest(1, { operation });
const timer = this.metrics.gqlTimer({ operation });
const requestInfo = `${REQUEST_ID}: ${requestId}, ${OPERATION_NAME}: ${operationName}`;
return Promise.resolve({
willSendResponse: () => {
const costInMilliseconds = timer() * 1000;
@@ -42,7 +32,6 @@ export class GQLLoggerPlugin implements ApolloServerPlugin {
'Server-Timing',
`gql;dur=${costInMilliseconds};desc="GraphQL"`
);
this.logger.log(requestInfo);
return Promise.resolve();
},
didEncounterErrors: () => {
@@ -52,7 +41,6 @@ export class GQLLoggerPlugin implements ApolloServerPlugin {
'Server-Timing',
`gql;dur=${costInMilliseconds};desc="GraphQL ${operation}"`
);
this.logger.error(`${requestInfo}, query: ${reqContext.request.query}`);
return Promise.resolve();
},
});

View File

@@ -0,0 +1,38 @@
import {
ArgumentsHost,
Catch,
ExceptionFilter,
HttpException,
Logger,
} from '@nestjs/common';
import { Request, Response } from 'express';
import { REQUEST_ID } from '../constants';
@Catch(HttpException)
export class ExceptionLogger implements ExceptionFilter {
private logger = new Logger('ExceptionLogger');
catch(exception: Error, host: ArgumentsHost) {
const ctx = host.switchToHttp();
const request = ctx.getRequest<Request>();
const requestId = request?.header(REQUEST_ID);
this.logger.error(
new Error(
`${requestId ? `requestId-${requestId}:` : ''}${exception.message}`,
{ cause: exception }
),
exception.stack
);
const response = ctx.getResponse<Response>();
if (exception instanceof HttpException) {
response.json(exception.getResponse());
} else {
response.status(500).json({
message: exception.message,
statusCode: 500,
});
}
}
}

View File

@@ -1,6 +1,8 @@
import { DynamicModule, Type } from '@nestjs/common';
import { DynamicModule, Provider, Type } from '@nestjs/common';
import { APP_FILTER } from '@nestjs/core';
import { GqlModule } from '../graphql.module';
import { ExceptionLogger } from '../middleware/exception-logger';
import { AuthModule } from './auth';
import { DocModule } from './doc';
import { SyncModule } from './sync';
@@ -8,6 +10,7 @@ import { UsersModule } from './users';
import { WorkspaceModule } from './workspaces';
const { SERVER_FLAVOR } = process.env;
const { NODE_ENV } = process.env;
const BusinessModules: (Type | DynamicModule)[] = [];
@@ -37,4 +40,13 @@ switch (SERVER_FLAVOR) {
break;
}
export { BusinessModules };
const Providers: Provider[] = [];
if (NODE_ENV !== 'test') {
Providers.push({
provide: APP_FILTER,
useClass: ExceptionLogger,
});
}
export { BusinessModules, Providers };