Log to AWS CloudWatch Logs in Nodejs

Steve Mu
2 min readMar 22, 2020

We can use the JavaScript AWS SDK. Set up a role on your EC2 that allows SSM. Here are the code:

var AWS = require("aws-sdk");AWS.config.region = "us-east-2";async function getSSMParameterByName(name) {
let ssm = new AWS.SSM();
return new Promise((resolve, reject) => {
ssm.getParameter({ Name: name }, function(err, data) {
if (err) reject(err);
resolve(data.Parameter.Value);
});
});
}
exports.getSSMParameterByName = getSSMParameterByName;
function cloudWatchPutLogEvents(events, group, stream, sequenceToken) {
return new Promise((resolve, reject) => {
const cloudwatchlogs = new AWS.CloudWatchLogs();
var params = {
logEvents: events,
logGroupName: group,
logStreamName: stream,
sequenceToken: sequenceToken
};
cloudwatchlogs.putLogEvents(params, function(err, data) {
if (err) reject(err);
resolve(data);
});
});
}
exports.cloudWatchPutLogEvents = cloudWatchPutLogEvents;
function cloudWatchDescribeLogStreams(group) {
return new Promise((resolve, reject) => {
const cloudwatchlogs = new AWS.CloudWatchLogs();
var params = {
logGroupName: group,
};
cloudwatchlogs.describeLogStreams(params, function(err, data) {
if (err) reject(err);
resolve(data);
});
});
}
exports.cloudWatchDescribeLogStreams = cloudWatchDescribeLogStreams;

To use it, create a logger.js:

const {
cloudWatchPutLogEvents,
cloudWatchDescribeLogStreams
} = require("./aws");
const { getConfig } = require("../config");
let nextSequenceToken = null; // need this for sending log to AWS. Will update after each request.let eventsQueue = [];
let interval = null;
// use a queue to send log to couldWatch one at a time to avoid throttling
async function startLogQueueToCloudWatch() {
if (interval == null) {
interval = setInterval(async () => {
if (eventsQueue.length == 0) {
clearInterval(interval);
interval = null;
return;
}
let event = eventsQueue.shift();
try {
console.log(event);
let res = await cloudWatchPutLogEvents(
[event],
"api",
"prod",
nextSequenceToken
);
nextSequenceToken = res.nextSequenceToken; // store the new sequence token
} catch (error) { // to allow retry
console.log(error);
}

}, 1000);
}
}
async function log(message) {if (nextSequenceToken == null) {
// just ran server, get the token from AWS
let res = await cloudWatchDescribeLogStreams("api");
nextSequenceToken = res.logStreams[0].uploadSequenceToken;
}
eventsQueue.push({
message: message,
timestamp: (new Date()).getTime()
});
await startLogQueueToCloudWatch();
}
exports.log = log;

When you need to log, just call await log('message') . It will log to console when process.env.NODE_ENV=development, and log to CloudWatch if not.

--

--