File tree Expand file tree Collapse file tree 9 files changed +71
-0
lines changed Expand file tree Collapse file tree 9 files changed +71
-0
lines changed Original file line number Diff line number Diff line change @@ -6,6 +6,7 @@ import { ToolsModule } from './mcp/tools/tools.module';
66import { GlobalProvidersModule } from './shared/global/globalProviders.module' ;
77import { ResourcesModule } from './mcp/resources/resources.module' ;
88import { randomUUID } from 'crypto' ;
9+ import { TimingInterceptorMiddleware } from './shared/global/timingInterceptor' ;
910
1011@Module ( {
1112 imports : [
@@ -28,5 +29,6 @@ import { randomUUID } from 'crypto';
2829export class AppModule implements NestModule {
2930 configure ( consumer : MiddlewareConsumer ) {
3031 consumer . apply ( TokenValidatorMiddleware ) . forRoutes ( '*' ) ;
32+ consumer . apply ( TimingInterceptorMiddleware ) . forRoutes ( '*' ) ;
3133 }
3234}
Original file line number Diff line number Diff line change @@ -2,6 +2,7 @@ import { Injectable } from '@nestjs/common';
22import { Resource } from '@tc/mcp-nest' ;
33import axios from 'axios' ;
44import { Logger } from 'src/shared/global' ;
5+ import { LogTime } from 'src/shared/global/logTime.decorator' ;
56
67const SPEC_URL =
78 'https://raw.githubusercontent.com/topcoder-platform/challenge-api-v6/refs/heads/develop/docs/swagger.yaml' ;
@@ -16,6 +17,7 @@ export class ChallengesApiSwaggerResource {
1617 description : 'Swagger documentation for the Challenges V6 API' ,
1718 mimeType : 'text/yaml' ,
1819 } )
20+ @LogTime ( 'ChallengesApiSwaggerResource' )
1921 async getChallengesApiSwagger ( ) {
2022 this . logger . debug ( 'Fetching Challenges V6 API Swagger' ) ;
2123 // Fetch the content from the URI and return it.
Original file line number Diff line number Diff line change @@ -2,6 +2,7 @@ import { Injectable } from '@nestjs/common';
22import { Resource } from '@tc/mcp-nest' ;
33import axios from 'axios' ;
44import { Logger } from 'src/shared/global' ;
5+ import { LogTime } from 'src/shared/global/logTime.decorator' ;
56
67const SPEC_URL =
78 'https://raw.githubusercontent.com/topcoder-platform/identity-api-v6/refs/heads/develop/doc/swagger.yaml' ;
@@ -16,6 +17,7 @@ export class IdentityApiSwaggerResource {
1617 description : 'Swagger documentation for the Identity V6 API' ,
1718 mimeType : 'text/yaml' ,
1819 } )
20+ @LogTime ( 'IdentityApiSwaggerResource' )
1921 async getIdentityApiSwagger ( ) {
2022 this . logger . debug ( 'Fetching Identity V6 API Swagger' ) ;
2123 // Fetch the content from the URI and return it.
Original file line number Diff line number Diff line change @@ -2,6 +2,7 @@ import { Injectable } from '@nestjs/common';
22import { Resource } from '@tc/mcp-nest' ;
33import axios from 'axios' ;
44import { Logger } from 'src/shared/global' ;
5+ import { LogTime } from 'src/shared/global/logTime.decorator' ;
56
67const SPEC_URL =
78 'https://raw.githubusercontent.com/topcoder-platform/member-api-v6/refs/heads/develop/docs/swagger.yaml' ;
@@ -16,6 +17,7 @@ export class MemberApiSwaggerResource {
1617 description : 'Swagger documentation for the Member V6 API' ,
1718 mimeType : 'text/yaml' ,
1819 } )
20+ @LogTime ( 'MemberApiSwaggerResource' )
1921 async getMemberApiSwagger ( ) {
2022 this . logger . debug ( 'Fetching Member V6 API Swagger' ) ;
2123 // Fetch the content from the URI and return it.
Original file line number Diff line number Diff line change @@ -2,6 +2,7 @@ import { Injectable } from '@nestjs/common';
22import { Resource } from '@tc/mcp-nest' ;
33import axios from 'axios' ;
44import { Logger } from 'src/shared/global' ;
5+ import { LogTime } from 'src/shared/global/logTime.decorator' ;
56
67const SPEC_URL = 'https://api.topcoder-dev.com/v6/review/api-docs-yaml' ;
78
@@ -15,6 +16,7 @@ export class ReviewApiSwaggerResource {
1516 description : 'Swagger documentation for the Review V6 API' ,
1617 mimeType : 'text/yaml' ,
1718 } )
19+ @LogTime ( 'ReviewApiSwaggerResource' )
1820 async getReviewApiSwagger ( ) {
1921 this . logger . debug ( 'Fetching Review V6 API Swagger' ) ;
2022 // Fetch the content from the URI and return it.
Original file line number Diff line number Diff line change @@ -5,6 +5,7 @@ import { QUERY_CHALLENGES_TOOL_PARAMETERS } from './queryChallenges.parameters';
55import { TopcoderChallengesService } from 'src/shared/topcoder/challenges.service' ;
66import { Logger } from 'src/shared/global' ;
77import { QUERY_CHALLENGES_TOOL_OUTPUT_SCHEMA } from './queryChallenges.output' ;
8+ import { LogTime } from 'src/shared/global/logTime.decorator' ;
89
910@Injectable ( )
1011export class QueryChallengesTool {
@@ -131,6 +132,7 @@ export class QueryChallengesTool {
131132 readOnlyHint : true ,
132133 } ,
133134 } )
135+ @LogTime ( 'ChallengesTool' )
134136 async queryChallenges ( params ) {
135137 return this . _queryChallenges ( params ) ;
136138 }
Original file line number Diff line number Diff line change @@ -5,6 +5,7 @@ import { Logger } from 'src/shared/global';
55import { QUERY_SKILLS_TOOL_PARAMETERS } from './querySkills.parameters' ;
66import { QUERY_SKILLS_TOOL_OUTPUT_SCHEMA } from './querySkills.output' ;
77import { TopcoderSkillsService } from 'src/shared/topcoder/skills.service' ;
8+ import { LogTime } from 'src/shared/global/logTime.decorator' ;
89
910@Injectable ( )
1011export class QuerySkillsTool {
@@ -125,6 +126,7 @@ export class QuerySkillsTool {
125126 readOnlyHint : true ,
126127 } ,
127128 } )
129+ @LogTime ( 'SkillsTool' )
128130 async querySkills ( params ) {
129131 return this . _querySkills ( params ) ;
130132 }
Original file line number Diff line number Diff line change 1+ import { Logger } from '@nestjs/common' ;
2+
3+ export function LogTime ( label ?: string ) {
4+ const logger = new Logger ( 'ExecutionTime' ) ;
5+
6+ return function (
7+ target : any ,
8+ propertyKey : string ,
9+ descriptor : PropertyDescriptor ,
10+ ) {
11+ const originalMethod = descriptor . value ;
12+
13+ descriptor . value = async function ( ...args : any [ ] ) {
14+ const start = Date . now ( ) ;
15+
16+ try {
17+ const result = await originalMethod . apply ( this , args ) ;
18+ const ms = Date . now ( ) - start ;
19+ logger . log ( `${ label || propertyKey } executed in ${ ms } ms` ) ;
20+ return result ;
21+ } catch ( error ) {
22+ const ms = Date . now ( ) - start ;
23+ logger . error (
24+ `${ label || propertyKey } failed after ${ ms } ms – ${ error . message } ` ,
25+ ) ;
26+ throw error ;
27+ }
28+ } ;
29+
30+ return descriptor ;
31+ } ;
32+ }
Original file line number Diff line number Diff line change 1+ import { Injectable , NestMiddleware , Logger } from '@nestjs/common' ;
2+
3+ import { Request , Response , NextFunction } from 'express' ;
4+
5+ @Injectable ( )
6+ export class TimingInterceptorMiddleware implements NestMiddleware {
7+ private logger = new Logger ( 'TimingInterceptor' ) ;
8+
9+ use ( request : Request , response : Response , next : NextFunction ) : void {
10+ const { method, originalUrl : url } = request ;
11+ const start = Date . now ( ) ;
12+ const mcpMethod = request . body ?. method ;
13+
14+ response . on ( 'close' , ( ) => {
15+ const { statusCode } = response ;
16+ const duration = Date . now ( ) - start ;
17+
18+ this . logger . log (
19+ `${ method } ${ mcpMethod ? `{${ mcpMethod } } ` : '' } ${ url } ${ statusCode } took ${ duration } ms`
20+ ) ;
21+ } ) ;
22+
23+ next ( ) ;
24+ }
25+ }
You can’t perform that action at this time.
0 commit comments