Skip to content

Commit 94e6bbb

Browse files
GHkrishnatipusinghaw
authored andcommitted
feat: trace contextId across services (#1509)
* feat: trace contextId across services, including passed from headers of http request Signed-off-by: Krishna Waske <[email protected]> * fix: import issues caused by merge Signed-off-by: Krishna Waske <[email protected]> * fix: contextId refactoring and coderabbit resolve Signed-off-by: Krishna Waske <[email protected]> * fix: make contextInterceptorModule resilient Signed-off-by: Krishna Waske <[email protected]> --------- Signed-off-by: Krishna Waske <[email protected]>
1 parent 2567509 commit 94e6bbb

File tree

11 files changed

+127
-86
lines changed

11 files changed

+127
-86
lines changed

apps/agent-service/src/agent-service.module.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { CommonModule } from '@credebl/common';
1+
import { CommonModule, NatsInterceptor } from '@credebl/common';
22
import { PrismaService } from '@credebl/prisma-service';
33
import { Logger, Module } from '@nestjs/common';
44
import { ClientsModule, Transport } from '@nestjs/microservices';
@@ -17,13 +17,15 @@ import { ConfigModule as PlatformConfig } from '@credebl/config/config.module';
1717
import { GlobalConfigModule } from '@credebl/config/global-config.module';
1818
import { ContextInterceptorModule } from '@credebl/context/contextInterceptorModule';
1919
import { NATSClient } from '@credebl/common/NATSClient';
20-
20+
import { APP_INTERCEPTOR } from '@nestjs/core';
2121

2222
@Module({
2323
imports: [
2424
ConfigModule.forRoot(),
2525
GlobalConfigModule,
26-
LoggerModule, PlatformConfig, ContextInterceptorModule,
26+
LoggerModule,
27+
PlatformConfig,
28+
ContextInterceptorModule,
2729
ClientsModule.register([
2830
{
2931
name: 'NATS_CLIENT',
@@ -47,7 +49,11 @@ import { NATSClient } from '@credebl/common/NATSClient';
4749
provide: MICRO_SERVICE_NAME,
4850
useValue: 'Agent-service'
4951
},
50-
NATSClient
52+
NATSClient,
53+
{
54+
provide: APP_INTERCEPTOR,
55+
useClass: NatsInterceptor
56+
}
5157
],
5258
exports: [AgentServiceService, AgentServiceRepository, AgentServiceModule]
5359
})

apps/api-gateway/src/main.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ import { getNatsOptions } from '@credebl/common/nats.config';
1414
import helmet from 'helmet';
1515
import { CommonConstants } from '@credebl/common/common.constant';
1616
import NestjsLoggerServiceAdapter from '@credebl/logger/nestjsLoggerServiceAdapter';
17-
import { NatsInterceptor } from '@credebl/common';
1817
import { UpdatableValidationPipe } from '@credebl/common/custom-overrideable-validation-pipe';
1918
import * as useragent from 'express-useragent';
2019

@@ -117,7 +116,6 @@ async function bootstrap(): Promise<void> {
117116
xssFilter: true
118117
})
119118
);
120-
app.useGlobalInterceptors(new NatsInterceptor());
121119
await app.listen(process.env.API_GATEWAY_PORT, `${process.env.API_GATEWAY_HOST}`);
122120
Logger.log(`API Gateway is listening on port ${process.env.API_GATEWAY_PORT}`);
123121
}

apps/api-gateway/src/oid4vc-verification/oid4vc-verification.controller.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ import { Oid4vpPresentationWhDto } from '../oid4vc-issuance/dtos/oid4vp-presenta
5454
@ApiUnauthorizedResponse({ description: 'Unauthorized', type: UnauthorizedErrorDto })
5555
@ApiForbiddenResponse({ description: 'Forbidden', type: ForbiddenErrorDto })
5656
export class Oid4vcVerificationController {
57-
private readonly logger = new Logger('Oid4vpVerificationController');
57+
private readonly logger = new Logger('Oid4vcVerificationController');
5858

5959
constructor(private readonly oid4vcVerificationService: Oid4vcVerificationService) {}
6060
/**

apps/api-gateway/src/oid4vc-verification/oid4vc-verification.service.ts

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,20 @@
11
import { NATSClient } from '@credebl/common/NATSClient';
2-
import { Inject, Injectable } from '@nestjs/common';
2+
import { Inject, Injectable, Logger } from '@nestjs/common';
33
import { ClientProxy } from '@nestjs/microservices';
4-
import { BaseService } from 'libs/service/base.service';
54
// eslint-disable-next-line camelcase
65
import { oid4vp_verifier, user } from '@prisma/client';
76
import { CreateVerifierDto, UpdateVerifierDto } from './dtos/oid4vc-verifier.dto';
87
import { VerificationPresentationQueryDto } from './dtos/oid4vc-verifier-presentation.dto';
98
import { Oid4vpPresentationWhDto } from '../oid4vc-issuance/dtos/oid4vp-presentation-wh.dto';
109

1110
@Injectable()
12-
export class Oid4vcVerificationService extends BaseService {
11+
export class Oid4vcVerificationService {
12+
private readonly logger = new Logger('Oid4vcVerificationService');
13+
1314
constructor(
1415
@Inject('NATS_CLIENT') private readonly oid4vpProxy: ClientProxy,
1516
private readonly natsClient: NATSClient
16-
) {
17-
super('Oid4vcVerificationService');
18-
}
17+
) {}
1918

2019
async oid4vpCreateVerifier(
2120
createVerifier: CreateVerifierDto,

apps/oid4vc-verification/src/main.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { NestFactory } from '@nestjs/core';
2-
import { HttpExceptionFilter } from 'libs/http-exception.filter';
32
import { Logger } from '@nestjs/common';
43
import { MicroserviceOptions, Transport } from '@nestjs/microservices';
54
import { getNatsOptions } from '@credebl/common/nats.config';
@@ -15,7 +14,8 @@ async function bootstrap(): Promise<void> {
1514
options: getNatsOptions(CommonConstants.OIDC4VC_VERIFICATION_SERVICE, process.env.OIDC4VC_VERIFICATION_NKEY_SEED)
1615
});
1716
app.useLogger(app.get(NestjsLoggerServiceAdapter));
18-
app.useGlobalFilters(new HttpExceptionFilter());
17+
// TODO: Not sure if we want the below
18+
// app.useGlobalFilters(new HttpExceptionFilter());
1919

2020
await app.listen();
2121
logger.log('OID4VC-Verification-Service Microservice is listening to NATS ');

apps/oid4vc-verification/src/oid4vc-verification.controller.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,10 @@ import { Oid4vpPresentationWh } from '../interfaces/oid4vp-verification-sessions
88

99
@Controller()
1010
export class Oid4vpVerificationController {
11-
private readonly logger = new Logger('Oid4vpVerificationController');
12-
constructor(private readonly oid4vpVerificationService: Oid4vpVerificationService) {}
11+
constructor(
12+
private readonly oid4vpVerificationService: Oid4vpVerificationService,
13+
private logger: Logger
14+
) {}
1315

1416
@MessagePattern({ cmd: 'oid4vp-verifier-create' })
1517
async oid4vpCreateVerifier(payload: {

apps/oid4vc-verification/src/oid4vc-verification.module.ts

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,24 @@ import { Oid4vpVerificationService } from './oid4vc-verification.service';
44
import { ClientsModule, Transport } from '@nestjs/microservices';
55
import { getNatsOptions } from '@credebl/common/nats.config';
66
import { CommonModule } from '@credebl/common';
7-
import { CommonConstants } from '@credebl/common/common.constant';
7+
import { CommonConstants, MICRO_SERVICE_NAME } from '@credebl/common/common.constant';
88
import { GlobalConfigModule } from '@credebl/config';
99
import { ContextInterceptorModule } from '@credebl/context';
10-
import { LoggerModule } from '@credebl/logger';
10+
import { LoggerModule } from '@credebl/logger/logger.module';
1111
import { CacheModule } from '@nestjs/cache-manager';
1212
import { ConfigModule as PlatformConfig } from '@credebl/config/config.module';
1313
import { NATSClient } from '@credebl/common/NATSClient';
14-
import { PrismaService } from '@credebl/prisma-service';
14+
import { PrismaService, PrismaServiceModule } from '@credebl/prisma-service';
1515
import { Oid4vpRepository } from './oid4vc-verification.repository';
16+
import { ConfigModule } from '@nestjs/config';
1617

1718
@Module({
1819
imports: [
20+
ConfigModule.forRoot(),
21+
ContextInterceptorModule,
22+
PlatformConfig,
23+
LoggerModule,
24+
CacheModule.register(),
1925
ClientsModule.register([
2026
{
2127
name: 'NATS_CLIENT',
@@ -28,12 +34,19 @@ import { Oid4vpRepository } from './oid4vc-verification.repository';
2834
]),
2935
CommonModule,
3036
GlobalConfigModule,
31-
LoggerModule,
32-
PlatformConfig,
33-
ContextInterceptorModule,
34-
CacheModule.register()
37+
PrismaServiceModule
3538
],
3639
controllers: [Oid4vpVerificationController],
37-
providers: [Oid4vpVerificationService, Oid4vpRepository, PrismaService, Logger, NATSClient]
40+
providers: [
41+
Oid4vpVerificationService,
42+
Oid4vpRepository,
43+
PrismaService,
44+
Logger,
45+
NATSClient,
46+
{
47+
provide: MICRO_SERVICE_NAME,
48+
useValue: 'Oid4vc-verification-service'
49+
}
50+
]
3851
})
3952
export class Oid4vpModule {}

apps/oid4vc-verification/src/oid4vc-verification.service.ts

Lines changed: 33 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,9 @@
99
import {
1010
BadRequestException,
1111
ConflictException,
12-
HttpException,
1312
Inject,
1413
Injectable,
1514
InternalServerErrorException,
16-
Logger,
1715
NotFoundException
1816
} from '@nestjs/common';
1917
import { Oid4vpRepository } from './oid4vc-verification.repository';
@@ -27,13 +25,16 @@ import { CreateVerifier, UpdateVerifier, VerifierRecord } from '@credebl/common/
2725
import { buildUrlWithQuery } from '@credebl/common/cast.helper';
2826
import { VerificationSessionQuery } from '../interfaces/oid4vp-verifier.interfaces';
2927
import { BaseService } from 'libs/service/base.service';
28+
import { NATSClient } from '@credebl/common/NATSClient';
29+
3030
import { Oid4vpPresentationWh, RequestSigner } from '../interfaces/oid4vp-verification-sessions.interfaces';
3131
import { X509CertificateRecord } from '@credebl/common/interfaces/x509.interface';
3232
import { SignerMethodOption } from '@credebl/enum/enum';
3333
@Injectable()
3434
export class Oid4vpVerificationService extends BaseService {
3535
constructor(
3636
@Inject('NATS_CLIENT') private readonly oid4vpVerificationServiceProxy: ClientProxy,
37+
private readonly natsClient: NATSClient,
3738
private readonly oid4vpRepository: Oid4vpRepository
3839
) {
3940
super('Oid4vpVerificationService');
@@ -363,9 +364,12 @@ export class Oid4vpVerificationService extends BaseService {
363364
async _createOid4vpVerifier(verifierDetails: CreateVerifier, url: string, orgId: string): Promise<any> {
364365
this.logger.debug(`[_createOid4vpVerifier] sending NATS message for orgId=${orgId}`);
365366
try {
366-
const pattern = { cmd: 'agent-create-oid4vp-verifier' };
367367
const payload = { verifierDetails, url, orgId };
368-
const response = await this.natsCall(pattern, payload);
368+
const response = await this.natsClient.sendNatsMessage(
369+
this.oid4vpVerificationServiceProxy,
370+
'agent-create-oid4vp-verifier',
371+
payload
372+
);
369373
this.logger.debug(`[_createOid4vpVerifier] NATS response received`);
370374
return response;
371375
} catch (error) {
@@ -379,9 +383,12 @@ export class Oid4vpVerificationService extends BaseService {
379383
async _deleteOid4vpVerifier(url: string, orgId: string): Promise<any> {
380384
this.logger.debug(`[_deleteOid4vpVerifier] sending NATS message for orgId=${orgId}`);
381385
try {
382-
const pattern = { cmd: 'agent-delete-oid4vp-verifier' };
383386
const payload = { url, orgId };
384-
const response = await this.natsCall(pattern, payload);
387+
const response = await this.natsClient.sendNatsMessage(
388+
this.oid4vpVerificationServiceProxy,
389+
'agent-delete-oid4vp-verifier',
390+
payload
391+
);
385392
this.logger.debug(`[_deleteOid4vpVerifier] NATS response received`);
386393
return response;
387394
} catch (error) {
@@ -395,9 +402,12 @@ export class Oid4vpVerificationService extends BaseService {
395402
async _updateOid4vpVerifier(verifierDetails: UpdateVerifier, url: string, orgId: string): Promise<any> {
396403
this.logger.debug(`[_updateOid4vpVerifier] sending NATS message for orgId=${orgId}`);
397404
try {
398-
const pattern = { cmd: 'agent-update-oid4vp-verifier' };
399405
const payload = { verifierDetails, url, orgId };
400-
const response = await this.natsCall(pattern, payload);
406+
const response = await this.natsClient.sendNatsMessage(
407+
this.oid4vpVerificationServiceProxy,
408+
'agent-update-oid4vp-verifier',
409+
payload
410+
);
401411
this.logger.debug(`[_updateOid4vpVerifier] NATS response received`);
402412
return response;
403413
} catch (error) {
@@ -411,9 +421,12 @@ export class Oid4vpVerificationService extends BaseService {
411421
async _createVerificationSession(sessionRequest: any, url: string, orgId: string): Promise<any> {
412422
this.logger.debug(`[_createVerificationSession] sending NATS message for orgId=${orgId}`);
413423
try {
414-
const pattern = { cmd: 'agent-create-oid4vp-verification-session' };
415424
const payload = { sessionRequest, url, orgId };
416-
const response = await this.natsCall(pattern, payload);
425+
const response = await this.natsClient.sendNatsMessage(
426+
this.oid4vpVerificationServiceProxy,
427+
'agent-create-oid4vp-verification-session',
428+
payload
429+
);
417430
this.logger.debug(`[_createVerificationSession] NATS response received`);
418431
return response;
419432
} catch (error) {
@@ -427,9 +440,12 @@ export class Oid4vpVerificationService extends BaseService {
427440
async _getOid4vpVerifierSession(url: string, orgId: string): Promise<any> {
428441
this.logger.debug(`[_getOid4vpVerifierSession] sending NATS message for orgId=${orgId}`);
429442
try {
430-
const pattern = { cmd: 'agent-get-oid4vp-verifier-session' };
431443
const payload = { url, orgId };
432-
const response = await this.natsCall(pattern, payload);
444+
const response = await this.natsClient.sendNatsMessage(
445+
this.oid4vpVerificationServiceProxy,
446+
'agent-get-oid4vp-verifier-session',
447+
payload
448+
);
433449
this.logger.debug(`[_getOid4vpVerifierSession] NATS response received`);
434450
return response;
435451
} catch (error) {
@@ -443,9 +459,12 @@ export class Oid4vpVerificationService extends BaseService {
443459
async _getVerificationSessionResponse(url: string, orgId: string): Promise<any> {
444460
this.logger.debug(`[_getVerificationSessionResponse] sending NATS message for orgId=${orgId}`);
445461
try {
446-
const pattern = { cmd: 'agent-get-oid4vp-verifier-session' };
447462
const payload = { url, orgId };
448-
const response = await this.natsCall(pattern, payload);
463+
const response = await this.natsClient.sendNatsMessage(
464+
this.oid4vpVerificationServiceProxy,
465+
'agent-get-oid4vp-verifier-session',
466+
payload
467+
);
449468
this.logger.debug(`[_getVerificationSessionResponse] NATS response received`);
450469
return response;
451470
} catch (error) {
@@ -455,26 +474,4 @@ export class Oid4vpVerificationService extends BaseService {
455474
throw error;
456475
}
457476
}
458-
459-
async natsCall(pattern: object, payload: object): Promise<string> {
460-
try {
461-
return this.oid4vpVerificationServiceProxy
462-
.send<string>(pattern, payload)
463-
.pipe(map((response) => response))
464-
.toPromise()
465-
.catch((error) => {
466-
this.logger.error(`catch: ${JSON.stringify(error)}`);
467-
throw new HttpException(
468-
{
469-
status: error.statusCode,
470-
error: error.message
471-
},
472-
error.error
473-
);
474-
});
475-
} catch (error) {
476-
this.logger.error(`[natsCall] - error in nats call : ${JSON.stringify(error)}`);
477-
throw error;
478-
}
479-
}
480477
}

libs/context/src/contextInterceptorModule.ts

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,10 @@
1-
import { ExecutionContext, Global, Module} from '@nestjs/common';
2-
import { v4 } from 'uuid';
1+
import { ExecutionContext, Global, Logger, Module } from '@nestjs/common';
2+
import { v4 as uuid } from 'uuid';
33
import { ClsModule } from 'nestjs-cls';
44

55
import { ContextStorageServiceKey } from './contextStorageService.interface';
66
import NestjsClsContextStorageService from './nestjsClsContextStorageService';
77

8-
9-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
10-
const isNullUndefinedOrEmpty = (obj: any): boolean => null === obj || obj === undefined || ('object' === typeof obj && 0 === Object.keys(obj).length);
11-
128
@Global()
139
@Module({
1410
imports: [
@@ -17,17 +13,30 @@ const isNullUndefinedOrEmpty = (obj: any): boolean => null === obj || obj === un
1713
interceptor: {
1814
mount: true,
1915

20-
generateId: true,
21-
idGenerator: (context: ExecutionContext) => {
22-
const rpcContext = context.switchToRpc().getContext();
23-
const headers = rpcContext.getHeaders();
24-
if (!isNullUndefinedOrEmpty(headers)) {
25-
return context.switchToRpc().getContext().getHeaders()['_description'];
26-
} else {
27-
return v4();
16+
generateId: true,
17+
idGenerator: (context: ExecutionContext) => {
18+
try {
19+
const logger = new Logger('ContextInterceptorModule');
20+
const rpcContext = context.switchToRpc().getContext();
21+
const headers = rpcContext.getHeaders() ?? {};
22+
const contextId = headers.get?.('contextId');
23+
24+
if (contextId) {
25+
logger.debug(`[idGenerator] Received contextId in headers: ${contextId}`);
26+
return contextId;
27+
} else {
28+
const uuidGenerated = uuid();
29+
logger.debug(
30+
'[idGenerator] Did not receive contextId in header, generated new contextId: ',
31+
uuidGenerated
32+
);
33+
return uuidGenerated;
34+
}
35+
} catch (error) {
36+
// eslint-disable-next-line no-console
37+
console.log('[idGenerator] Error in idGenerator: ', error);
2838
}
29-
}
30-
39+
}
3140
}
3241
})
3342
],
@@ -40,6 +49,4 @@ const isNullUndefinedOrEmpty = (obj: any): boolean => null === obj || obj === un
4049
],
4150
exports: [ContextStorageServiceKey]
4251
})
43-
4452
export class ContextInterceptorModule {}
45-

0 commit comments

Comments
 (0)