Reputation: 445
All the articles and documentation I have read so far talk about the integration of Cloudwatch and Winston on a vanilla Node app, but nothing on Nestjs
So far I have on my app.module.ts:
imports: [
ConfigModule.forRoot({ isGlobal: true }),
MongooseModule.forRoot(
`mongodb://${environment.MONGO_INITDB_ROOT_USERNAME}:${environment.MONGO_INITDB_ROOT_PASSWORD}@${environment.MONGODB_HOST}/${environment.MONGO_INITDB_DATABASE}`,
),
VoucherModule,
ApiKeyModule,
WinstonModule.forRoot(loggerConfig),
],
where loggerConfig are the basic Winston configs depending on the env.
Using winston-cloudwatch package I need to create a new Transporter and add it add it to winston, but can't seem to find a way to do this.
Upvotes: 7
Views: 9792
Reputation: 531
I recently implemented aws-cloudwatch in nestjs and faced similar issue but after some browsing and reading about winston and cloudwatch, came up with this solution.
//main.ts
import {
utilities as nestWinstonModuleUtilities,
WinstonModule,
} from 'nest-winston';
import * as winston from 'winston';
import CloudWatchTransport from 'winston-cloudwatch';
const app = await NestFactory.create(AppModule, {
logger: WinstonModule.createLogger({
format: winston.format.uncolorize(), //Uncolorize logs as weird character encoding appears when logs are colorized in cloudwatch.
transports: [
new winston.transports.Console({
format: winston.format.combine(
winston.format.timestamp(),
winston.format.ms(),
nestWinstonModuleUtilities.format.nestLike()
),
}),
new CloudWatchTransport({
name: "Cloudwatch Logs",
logGroupName: process.env.CLOUDWATCH_GROUP_NAME,
logStreamName: process.env.CLOUDWATCH_STREAM_NAME,
awsAccessKeyId: process.env.AWS_ACCESS_KEY,
awsSecretKey: process.env.AWS_KEY_SECRET,
awsRegion: process.env.CLOUDWATCH_AWS_REGION,
messageFormatter: function (item) {
return (
item.level + ": " + item.message + " " + JSON.stringify(item.meta)
);
},
}),
],
}),
});
Here, we have defined two transports one is transports.Console() which is the default winston transport and another one is the cloudwatch transport.
What this basically does is, replaces the default nestjs Logger(imported from @nestjs/common). So, we don't have to import winston in any module not even in 'app.module.ts'. Instead just import Logger in whichever module you need, and whenever we log anything it will be shown in the terminal and will upload it to the cloudwatch.
EDIT: With configService..
//main.js
import {
utilities as nestWinstonModuleUtilities,
WinstonModule,
} from 'nest-winston';
import * as winston from 'winston';
import CloudWatchTransport from 'winston-cloudwatch';
import { ConfigService } from '@nestjs/config';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
const configService = app.get(ConfigService);
app.useLogger(
WinstonModule.createLogger({
format: winston.format.uncolorize(),
transports: [
new winston.transports.Console({
format: winston.format.combine(
winston.format.timestamp(),
winston.format.ms(),
nestWinstonModuleUtilities.format.nestLike(),
),
}),
new CloudWatchTransport({
name: 'Cloudwatch Logs',
logGroupName: configService.get('CLOUDWATCH_GROUP_NAME'),
logStreamName: configService.get('CLOUDWATCH_STREAM_NAME'),
awsAccessKeyId: configService.get('AWS_ACCESS_KEY'),
awsSecretKey: configService.get('AWS_KEY_SECRET'),
awsRegion: configService.get('CLOUDWATCH_AWS_REGION'),
messageFormatter: function (item) {
return (
item.level + ': ' + item.message + ' ' + JSON.stringify(item.meta)
);
},
}),
],
}),
);
await app.listen(configService.get('PORT') || 3000);
}
Upvotes: 16