fix: logger filter should pass graphql context (#4209)

This commit is contained in:
X1a0t 2023-09-06 23:16:38 +08:00 committed by GitHub
parent 1b6a78cd00
commit 22d3411e6e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 103 additions and 2 deletions

View File

@ -4,10 +4,13 @@ import {
ExceptionFilter,
HttpException,
Logger,
NotFoundException,
} from '@nestjs/common';
import { GqlContextType } from '@nestjs/graphql';
import { Request, Response } from 'express';
import { REQUEST_ID } from '../constants';
const TrivialExceptions = [NotFoundException];
@Catch()
export class ExceptionLogger implements ExceptionFilter {
@ -16,15 +19,26 @@ export class ExceptionLogger implements ExceptionFilter {
catch(exception: Error, host: ArgumentsHost) {
// with useGlobalFilters, the context is always HTTP
const ctx = host.switchToHttp();
const request = ctx.getRequest<Request>();
const requestId = request?.header(REQUEST_ID);
const shouldVerboseLog = !TrivialExceptions.some(
e => exception instanceof e
);
this.logger.error(
new Error(
`${requestId ? `requestId-${requestId}:` : ''}${exception.message}`,
{ cause: exception }
),
exception.stack
)
);
if (shouldVerboseLog) {
this.logger.error(exception.stack);
}
if (host.getType<GqlContextType>() === 'graphql') {
return;
}
const response = ctx.getResponse<Response>();
if (exception instanceof HttpException) {

View File

@ -0,0 +1,87 @@
import { Controller, Get, INestApplication } from '@nestjs/common';
import { Test } from '@nestjs/testing';
import test from 'ava';
// @ts-expect-error graphql-upload is not typed
import graphqlUploadExpress from 'graphql-upload/graphqlUploadExpress.mjs';
import request from 'supertest';
import { AppModule } from '../app';
import { ExceptionLogger } from '../middleware/exception-logger';
import { PrismaService } from '../prisma';
const gql = '/graphql';
const rest = '/rest';
let app: INestApplication;
class FakePrisma {
get workspace() {
return {
async findUnique() {
throw Error('exception from graphql');
},
};
}
}
@Controller('rest')
export class MockController {
@Get()
test(): string {
throw new Error('exception from rest api');
}
}
test.beforeEach(async () => {
const module = await Test.createTestingModule({
imports: [AppModule],
controllers: [MockController],
})
.overrideProvider(PrismaService)
.useClass(FakePrisma)
.compile();
app = module.createNestApplication({
cors: true,
bodyParser: true,
});
app.useGlobalFilters(new ExceptionLogger());
app.use(
graphqlUploadExpress({
maxFileSize: 10 * 1024 * 1024,
maxFiles: 5,
})
);
await app.init();
});
test.afterEach(async () => {
await app.close();
});
test('should get response from graphql', async t => {
const id = 'workspace';
const response = await request(app.getHttpServer())
.post(gql)
.send({
name: 'getPublicWorkspace',
query: `
query getPublicWorkspace($id: String!) {
publicWorkspace(id: $id) {
id
}
}
`,
variables: { id },
});
t.is(response.status, 200);
t.is(response.body.errors[0].message, 'exception from graphql');
});
test('should get response from rest api', async t => {
const response = await request(app.getHttpServer()).get(rest);
t.is(response.status, 500);
t.is(response.body.error, 'exception from rest api');
});