Mastering Nest.js Monitoring with Grafana and Prometheus: A Comprehensive Guide
NestJS, a powerful framework built on top of Node.js and TypeScript, offers developers a robust structure for building scalable and maintainable applications. However, as your NestJS application grows, monitoring its performance and health becomes crucial.
This blog post will guide you through setting up a comprehensive monitoring system for your NestJS application using the dynamic duo of Grafana and Prometheus. We'll cover everything from logging configuration to building insightful dashboards, allowing you to keep a watchful eye on your application's health and performance.
1. Setting up Logging in NestJS
Before we can monitor, we need data to monitor. NestJS provides a flexible logging system through its built-in Logger
service. Here's how to get started:
1.1 Install Dependencies
npm install @nestjs/platform-logger pino
1.2 Configure Logging in your main.ts
file:
import { Logger } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
const logger = new Logger('Bootstrap');
logger.log('Starting application...');
await app.listen(3000);
logger.log('Application started on port 3000');
}
bootstrap();
1.3 Using the Logger Service:
import { Injectable, Logger } from '@nestjs/common';
@Injectable()
export class MyService {
private readonly logger = new Logger(MyService.name);
doSomething() {
this.logger.log('Doing something...');
}
}
1.4 Using Pino for Enhanced Logging:
Pino is a high-performance Node.js logger that excels in performance and structured logging.
import { Injectable, Logger } from '@nestjs/common';
import { PinoLogger } from 'nestjs-pino';
@Injectable()
export class MyService {
constructor(private readonly logger: PinoLogger) {
}
doSomething() {
this.logger.info('Doing something...', { event: 'somethingDone' });
}
}
By using PinoLogger
you can log structured JSON data, enabling more insightful monitoring.
2. Introducing Prometheus: Your Monitoring Workhorse
Prometheus is an open-source monitoring system that gathers metrics from your application and stores them in a time series database.
2.1 Installation:
docker run -d -p 9090:9090 --name prometheus prometheus/prometheus
This command downloads and runs the Prometheus image as a Docker container.
2.2 Exposing Metrics in NestJS:
To expose metrics for Prometheus to scrape, we'll use the @nestjs/prometheus
package.
2.2.1 Install dependencies:
npm install @nestjs/prometheus prom-client
2.2.2 Configure in your main.ts
:
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { registerMetrics } from './metrics';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
// Register metrics with Prometheus
registerMetrics(app);
await app.listen(3000);
}
bootstrap();
2.2.3 Create a metrics helper file (metrics.ts
):
import { Injectable } from '@nestjs/common';
import { register } from 'prom-client';
import { Instrument } from '@nestjs/prometheus';
import { Gauge } from 'prom-client';
@Injectable()
export class MetricsService {
constructor(@Instrument() private gauge: Gauge<string>) {
}
incrementCounter(): void {
this.gauge.inc();
}
}
export function registerMetrics(app) {
const gauge = new Gauge({
name: 'my_app_requests',
help: 'The number of requests processed by the application',
labelNames: ['status'],
});
register.registerMetric(gauge);
app.useGlobalGuards(new MetricsGuard(gauge));
}
export class MetricsGuard {
constructor(private readonly gauge: Gauge<string>) {
}
canActivate(): boolean {
this.gauge.inc({ status: 'success' });
return true;
}
}
This example shows how to track the number of successful requests to your application.
3. Grafana: Visualizing Your Data
Grafana provides a powerful and user-friendly interface for visualizing your Prometheus metrics.
3.1 Install and Run Grafana:
docker run -d -p 3000:3000 --name grafana grafana/grafana
3.2 Add Prometheus as a Data Source:
- Access Grafana at
http://localhost:3000
. - Login with default credentials:
admin
andadmin
. - Go to
Configuration
->Data Sources
and add a new Prometheus data source. - Fill in the details, including the Prometheus endpoint (
http://localhost:9090
).
3.3 Creating a Dashboard:
- Create a new dashboard in Grafana.
- Add panels and configure them to display your Prometheus metrics.
- You can use Grafana's query builder to create complex queries and visualize your data in different ways (graphs, charts, tables).
4. Alerts: Notifying You of Issues
Grafana allows you to set up alerts based on Prometheus metrics. These alerts can notify you via email, Slack, or other channels if predefined thresholds are exceeded.
4.1 Create an Alert Rule in Prometheus:
groups: - name: request_errors rules: - alert: RequestErrors expr: my_app_errors > 10 for: 5m labels: severity: warning annotations: summary: "High number of request errors" description: "The number of request errors is above 10 for the last 5 minutes."
This rule triggers an alert if the my_app_errors
metric exceeds 10 for 5 minutes.
4.2 Configure Alerting in Grafana:
- Go to
Alerting
in Grafana. - Configure the alerting settings for your Prometheus data source.
- Select the desired notification channels and configure them.
Conclusion
By implementing the steps outlined in this blog post, you can confidently monitor your NestJS application with Grafana and Prometheus. This powerful combination empowers you to track key metrics, identify potential issues, and proactively maintain your application's health and performance. From logging configuration to building insightful dashboards, this guide has equipped you with the knowledge to build a robust monitoring system, making your NestJS application even more reliable and efficient.
Don't hesitate to explore the vast possibilities of Grafana and Prometheus beyond the basic setup presented here. You can create custom dashboards, utilize advanced querying techniques, and leverage the rich alerting capabilities to gain deeper insights into your application's behavior and ensure its optimal performance.