feat(observability): add exception filter, logging interceptor, and CodeExecutorModule
- add HttpExceptionFilter logging BadRequestException at warn and InternalServerErrorException at error with cause chain
- add LoggingInterceptor logging request/response pairs at debug level with method, path, body, status, and duration
- extract CodeExecutorService into standalone CodeExecutorModule imported by BrowserModule and McpModule
- thread { cause: err } into all catch blocks across auth, browser, and code-executor services
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
import {
|
||||
CallHandler,
|
||||
ExecutionContext,
|
||||
Injectable,
|
||||
Logger,
|
||||
NestInterceptor,
|
||||
} from '@nestjs/common';
|
||||
import type { Request, Response } from 'express';
|
||||
import { Observable, tap } from 'rxjs';
|
||||
|
||||
@Injectable()
|
||||
export class LoggingInterceptor implements NestInterceptor {
|
||||
private readonly logger = new Logger(LoggingInterceptor.name);
|
||||
|
||||
intercept(context: ExecutionContext, next: CallHandler): Observable<unknown> {
|
||||
const http = context.switchToHttp();
|
||||
const req = http.getRequest<Request>();
|
||||
const res = http.getResponse<Response>();
|
||||
const { method, url, body } = req;
|
||||
const start = Date.now();
|
||||
|
||||
this.logger.debug(`→ ${method} ${url} ${JSON.stringify(body)}`);
|
||||
|
||||
return next.handle().pipe(
|
||||
tap((responseBody) => {
|
||||
const ms = Date.now() - start;
|
||||
this.logger.debug(`← ${method} ${url} ${res.statusCode} (${ms}ms) ${JSON.stringify(responseBody)}`);
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user