Effective error logging is vital for application stability. Integrating Sentry into a NestJS application can significantly improve how we handle logging. This article will guide you through creating a custom logger that sends error logs to Sentry while keeping the standard console logging.
Step 1: Install Sentry
First, install the Sentry SDK:
npm install @sentry/node
Step 2: Create the Custom Logger
Create a new file named sentry.logger.ts:
import { ConsoleLogger } from "@nestjs/common";
import * as Sentry from "@sentry/node";
export class SentryLogger extends ConsoleLogger {
error(message: any, ...optionalParams: any[]): void {
const errorMessage = message.toString();
let stack: string | object = "";
let logContext = "";
if (optionalParams.length === 1) {
logContext = optionalParams[0];
} else if (optionalParams.length === 2) {
[stack, logContext] = optionalParams;
}
const formattedMessage = logContext
? `${logContext}: ${errorMessage}`
: errorMessage;
Sentry.withScope((scope) => {
scope.setExtra("message", errorMessage);
scope.setExtra("context", logContext);
scope.setExtra("stack", stack);
Sentry.captureMessage(formattedMessage, "error");
});
super.error(errorMessage, ...optionalParams);
}
verbose(message: any, ...optionalParams: any[]): void {
const verboseMessage = message ? message.toString() : "";
const logContext = optionalParams.shift() || "";
const extra = optionalParams;
const formattedMessage = logContext
? `${logContext}: ${verboseMessage}`
: verboseMessage;
Sentry.withScope((scope) => {
scope.setExtra("message", verboseMessage);
scope.setExtra("context", logContext);
scope.setExtra("extra", extra);
Sentry.captureMessage(formattedMessage, "info");
});
super.verbose(verboseMessage, ...extra);
}
}
Explanation
Error Handling: Theerrormethod formats the error message and sends it to Sentry, attaching extra context.
Verbose Logging: Theverbosemethod captures informational messages, providing insights into the application's state.
Step 3: Initialize Sentry
In your main application file (e.g., main.ts), initialize Sentry with the following configuration:
import { Logger } from "@nestjs/common";
import { ConfigService } from "@nestjs/config";
import { NestFactory } from "@nestjs/core";
import { NestExpressApplication } from "@nestjs/platform-express";
import * as Sentry from "@sentry/node";
import { nodeProfilingIntegration } from "@sentry/profiling-node";
import { AppModule } from "./app.module";
import { SentryLogger } from "./utility/logger/sentry.logger";
const logger = new Logger("MyApp");
async function bootstrap() {
const app = await NestFactory.create<NestExpressApplication>(AppModule);
const cfg = app.get(ConfigService);
Sentry.init({
dsn: cfg.get<string>("SENTRY_DNS", ""),
environment: cfg.get<string>("NODE_ENV", "development"),
tracesSampleRate: 1.0,
profilesSampleRate: 1.0,
normalizeDepth: 5,
integrations: [nodeProfilingIntegration()],
});
app.useLogger(new SentryLogger());
await app.listen(3000);
}
bootstrap()
.then(() => logger.log("Server is running"))
.catch((err) => logger.error("Bootstrap failed", err));
Explanation of Sentry Initialization
DSN: The Data Source Name (DSN) allows Sentry to identify and route errors to the correct project.
Environment: Setting the environment (e.g., development or production) helps in distinguishing logs.
Sample Rates: Both tracesSampleRate and profilesSampleRate control how much data is sent to Sentry for performance monitoring, set to 100% (1.0) for full data capture.
Integrations: The nodeProfilingIntegration() is included for additional profiling features.
By implementing a custom logger with Sentry in your NestJS application, you enhance your error tracking and debugging capabilities. With detailed context and real-time monitoring, you can maintain more reliable applications. Start integrating Sentry into your projects today!
SOCIAL SHARE CARD GENERATOR