Reputation: 15237
I'm working in a NestJS app, and I wish to setup AWS X-Ray on it. I'm new to NestJS, and I'm not clear on how to do this.
In an Express app, the AWS docs say you do this:
var app = express();
var AWSXRay = require('aws-xray-sdk');
app.use(AWSXRay.express.openSegment('MyApp'));
app.get('/', function (req, res) {
res.render('index');
});
app.use(AWSXRay.express.closeSegment());
But there isn't that linear flow in NestJS, so I'm not sure how AWS X-Ray would be integrated. I noticed this answer from 2 years ago (not sure if there's a better way now), but that doesn't show the middleware setup necessary, and it also doesn't show how the interceptor would integrate into the app (i.e. what will the setup be like)
ATTEMPTED SOLUTION
I created a Middleware class:
import { Injectable, NestMiddleware } from '@nestjs/common';
import { Request, Response, NextFunction } from 'express';
import AWSXRay from 'aws-xray-sdk';
@Injectable()
export class XRayMiddleware implements NestMiddleware {
use(req: Request, res: Response, next: NextFunction) {
AWSXRay.express.openSegment('application-name');
next();
}
}
I then created an Interceptor class:
import { Injectable, NestInterceptor, ExecutionContext, CallHandler } from '@nestjs/common';
import { Observable } from 'rxjs';
import { tap } from 'rxjs/operators';
import AWSXRay from 'aws-xray-sdk';
import { HttpAdapterHost } from '@nestjs/core';
@Injectable()
export class XRayInterceptor implements NestInterceptor {
constructor(private readonly httpAdapter: HttpAdapterHost) {}
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
return next.handle().pipe(tap(() => this.httpAdapter.httpAdapter.use(AWSXRay.express.closeSegment())));
}
}
I then updated the app.module.ts
to:
import { AppConfigModule } from '@app-config/app-config.module';
import { Module, NestModule, MiddlewareConsumer, RequestMethod } from '@nestjs/common';
import { CustomersModule } from './customers/customers.module';
import { HealthModule } from './health/health.module';
import { XRayMiddleware } from './middleware/xray.middleware';
@Module({
imports: [AppConfigModule, HealthModule, CustomersModule],
providers: [],
})
export class AppModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
consumer.apply(XRayMiddleware).forRoutes({ path: '*', method: RequestMethod.ALL });
}
}
And finally, I added this line to my main.ts
:
const app = await NestFactory.create(AppModule);
app.useGlobalInterceptors(new XRayInterceptor(app.get(HttpAdapterHost)));
When I run the application, and hit an endpoint, I get the following error:
Thanks
Upvotes: 5
Views: 1928
Reputation: 273
The X-Ray SDK for Node.js does not support instrumenting NestJS, but OpenTelemetry JavaScript does: https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/opentelemetry-instrumentation-nestjs-core
You can send traces to X-Ray using OpenTelemetry by following the steps in this getting started guide: https://aws-otel.github.io/docs/getting-started/js-sdk/trace-manual-instr
Upvotes: 2