Skip to content
Advertisement

Expose normal http endpoint in NestJS Microservices

I have this microservice written with NestJs:

async function bootstrap() {
  const port = parseInt(process.env.PORT || '5000', 10);

  const app = await NestFactory.createMicroservice(ApplicationModule, {
    transport: Transport.TCP,
    options: { host: '0.0.0.0', port }
  });
  app.listen(() => console.log(`Microservice is listening on port ${port}`));
}
bootstrap();

But now I need to implement an endpoint /metrics for Prometheus. So the question is how do I do this with NestJs microservice

From this issue I get the impression that it is not possible. Is this true and if so, is there a workaround I can use?

I tried to apply middleware as follows

Module({
  imports: [],
  controllers: [AppController],
  providers: [AppService, DBService],
})
export class ApplicationModule {
  configure(consumer: MiddlewareConsumer) {
    consumer
      .apply(MetricsMiddleware)
      .forRoutes('/metrics') // Also tried '*'
  }
}

But when I do curl http://localhost:5000/metrics nothing happens, the middleware is not called

@Injectable()
export class MetricsMiddleware implements NestMiddleware {
    constructor() {}

    use(req, res, next) {
        console.log('yes');
        next();
    }
}

Update: This issue will also not help 🙁

Advertisement

Answer

If you want your application to support both http requests and a microservice, you can create a hybrid application.

// Create your regular nest application.
const app = await NestFactory.create(ApplicationModule);

// Then combine it with your microservice
const microservice = app.connectMicroservice({
  transport: Transport.TCP,
  options: { host: '0.0.0.0', port: 5000 }
});

await app.startAllMicroservices();
await app.listen(3001);
User contributions licensed under: CC BY-SA
2 People found this is helpful
Advertisement