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:
2026-04-07 13:49:02 +03:00
parent bf1b6249a9
commit 5ac26ecb3a
13 changed files with 168 additions and 19 deletions
+2 -1
View File
@@ -5,9 +5,10 @@ import { AuthModule } from '../auth/auth.module';
import { SessionModule } from '../session/session.module';
import { EnvironmentModule } from '../environment/environment.module';
import { BrowserModule } from '../browser/browser.module';
import { CodeExecutorModule } from '../code-executor/code-executor.module';
@Module({
imports: [AuthModule, SessionModule, EnvironmentModule, BrowserModule],
imports: [AuthModule, SessionModule, EnvironmentModule, BrowserModule, CodeExecutorModule],
controllers: [McpController],
providers: [McpService],
})
+3
View File
@@ -8,6 +8,7 @@ import { SessionService } from '../session/session.service';
import { EnvironmentService } from '../environment/environment.service';
import type { EnvironmentUrls } from '../environment/environment.entity';
import { BrowserService } from '../browser/browser.service';
import { CodeExecutorService } from '../code-executor/code-executor.service';
@Injectable()
export class McpService {
@@ -16,6 +17,7 @@ export class McpService {
private readonly sessionService: SessionService,
private readonly environmentService: EnvironmentService,
private readonly browserService: BrowserService,
private readonly codeExecutor: CodeExecutorService,
) {}
async handle(req: Request, res: Response): Promise<void> {
@@ -197,6 +199,7 @@ export class McpService {
},
async ({ sessionName, code, url }) => {
try {
this.codeExecutor.validate(code);
const result = await this.browserService.exec(sessionName, code, url);
return { content: [{ type: 'text' as const, text: JSON.stringify(result) }] };
} catch (err) {