主题
异常过滤器和日志
抛出异常
抛出标准异常
ts
throw new HttpException('Forbidden', HttpStatus.FORBIDDEN);
throw new HttpException({
status: HttpStatus.FORBIDDEN,
error: 'This is a custom message',
}, HttpStatus.FORBIDDEN, {
cause: error
});抛出自定义异常
ts
// 定义异常
export class ForbiddenException extends HttpException {
constructor() {
super('Forbidden', HttpStatus.FORBIDDEN);
}
}
// 使用
threw new ForbiddenException();异常过滤器
异常过滤器是处理异常的,当抛出异常时,会调用异常过滤器。
定义异常处理逻辑
common/filters/AllException.filters.ts
ts
import {
ExceptionFilter,
Catch,
ArgumentsHost,
HttpStatus,
} from '@nestjs/common';
import { Request, Response } from 'express';
@Catch() // 👈 不传参数,表示捕获所有异常
export class AllExceptionFilter implements ExceptionFilter {
catch(exception: Error, host: ArgumentsHost) {
const ctx = host.switchToHttp();
const response = ctx.getResponse<Response>();
const request = ctx.getRequest<Request>();
const status = HttpStatus.INTERNAL_SERVER_ERROR;
const message = exception.message || '服务器错误';
// 返回标准格式
response.status(status).json({
code: status,
message,
path: request.url,
});
}
}common/filters/HttpException.filters.ts
ts
import {
ExceptionFilter,
Catch,
ArgumentsHost,
HttpException,
HttpStatus,
} from '@nestjs/common';
import { Request, Response } from 'express';
@Catch(HttpException) // 👈 只捕获 HttpException 及其子类
export class HttpExceptionFilter implements ExceptionFilter {
catch(exception: HttpException, host: ArgumentsHost) {
const ctx = host.switchToHttp();
const response = ctx.getResponse<Response>();
const request = ctx.getRequest<Request>();
const status = exception.getStatus() || HttpStatus.INTERNAL_SERVER_ERROR;
// Nest 内置异常结构中 getResponse() 可能返回 string 或 object
const exceptionResponse = exception.getResponse();
const message =
typeof exceptionResponse === 'string'
? exceptionResponse
: (exceptionResponse as { message: string }).message ||
exception.message;
// 返回统一格式
response.status(status).json({
code: status,
message,
path: request.url,
params: request.params,
});
}
}绑定过滤器
user.controller.ts
ts
@Post()
@UseFilters(new HttpExceptionFilter())
async create(@Body() createCatDto: CreateCatDto) {
throw new ForbiddenException();
}全局作用域
main.ts
ts
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.useGlobalFilters(new HttpExceptionFilter());
await app.listen(process.env.PORT ?? 3000);
}
bootstrap();日志
在 main.ts 中开启日志
ts
const app = await NestFactory.create(AppModule, {
logger: ['error', 'warn'],
});在类中使用
ts
export class UserService {
private readonly logger = new Logger(UserService.name);
findAll() {
this.logger.error(12);
}
}自定义日志
common/logger/logger.ts
ts
import { LoggerService, Injectable, LogLevel } from '@nestjs/common';
import { Request } from 'express';
@Injectable()
export class MyLogger implements LoggerService {
private getTimestamp(): number {
return new Date().getTime();
}
private getContext(...rest: any[]): string {
let context = '';
if (typeof rest === 'object' && !(rest instanceof Array)) {
context = rest;
} else {
context = rest.toString();
}
return context;
}
getReqInfo = (request: Request) => {
const reqInfo: Record<string, any> = {};
reqInfo.url = request.url;
reqInfo.method = request.method;
reqInfo.ip = request.ip;
if (request.body !== undefined) {
reqInfo.body = JSON.stringify(request.body);
}
if (request.params !== undefined) {
reqInfo.params = JSON.stringify(request.params);
}
if (request.query !== undefined) {
reqInfo.query = JSON.stringify(request.query);
}
if (reqInfo.ip === '::1') {
reqInfo.ip = '127.0.0.1';
}
return reqInfo;
};
private getLogger = (
level: LogLevel,
message: string,
request: Request,
...rest: any[]
) => {
const timestamp = this.getTimestamp();
const context = this.getContext(rest);
const reqInfo = this.getReqInfo(request);
return {
level,
timestamp,
context,
message,
...reqInfo,
};
};
log(message: string, request: null | Request, ...rest: any[]) {
console.log(this.getLogger('log', message, request, rest));
}
error(message: string, request: null | Request, ...rest: any[]) {
console.log(this.getLogger('error', message, request, rest));
}
warn(message: string, request: null | Request, ...rest: any[]) {
console.log(this.getLogger('warn', message, request, rest));
}
debug?(message: string, request: null | Request, ...rest: any[]) {
console.log(this.getLogger('debug', message, request, rest));
}
verbose?(message: string, request: null | Request, ...rest: any[]) {
console.log(this.getLogger('verbose', message, request, rest));
}
fatal?(message: string, request: null | Request, ...rest: any[]) {
console.log(this.getLogger('fatal', message, request, rest));
}
}main.ts
ts
import { MyLogger } from './common/logger/logger.service';
const app = await NestFactory.create(AppModule, {
logger: new MyLogger(),
});
