forked from github.com/GenderDysphoria.fyi
Terraform updates
Attempting to do some log parsing into cloudwatch logs
This commit is contained in:
88
terraform/lambda/src/cloudwatch-logs.js
Normal file
88
terraform/lambda/src/cloudwatch-logs.js
Normal file
@@ -0,0 +1,88 @@
|
||||
const { CloudWatchLogs } = require('aws-sdk');
|
||||
|
||||
// Split up ARN like "arn:aws:logs:eu-west-1:123456789012:log-group:example-group:*"
|
||||
const [,,, region,,, logGroupName] = process.env.CLOUDWATCH_LOGS_GROUP_ARN.split(':');
|
||||
|
||||
const cloudwatchlogs = new CloudWatchLogs({ region });
|
||||
|
||||
|
||||
// Group array of hashes by defined key.
|
||||
//
|
||||
const groupBy = (array, key) => (
|
||||
array.reduce((object, item) => {
|
||||
const result = object;
|
||||
|
||||
if (result[item[key]]) {
|
||||
result[item[key]].push(item);
|
||||
} else if (item[key]) {
|
||||
result[item[key]] = [item];
|
||||
}
|
||||
return result;
|
||||
}, {})
|
||||
);
|
||||
|
||||
// Find log stream by prefix.
|
||||
//
|
||||
const findLogStream = async (logStreamNamePrefix) => {
|
||||
const params = { logGroupName, logStreamNamePrefix };
|
||||
|
||||
const { logStreams } = await cloudwatchlogs.describeLogStreams(params).promise();
|
||||
|
||||
if (logStreams.length > 1) {
|
||||
throw new Error(`Found '${logStreams.length}' matching CloudWatch Logs streams but expected only one.`);
|
||||
}
|
||||
|
||||
return logStreams[0];
|
||||
};
|
||||
|
||||
// Get log stream or creting it if not present yet.
|
||||
//
|
||||
// Name format:
|
||||
// 2000-01-01
|
||||
//
|
||||
const describeLogStream = async (logStreamName) => {
|
||||
let logStream = await findLogStream(logStreamName);
|
||||
|
||||
if (!logStream) {
|
||||
await cloudwatchlogs.createLogStream({ logGroupName, logStreamName }).promise();
|
||||
logStream = await findLogStream(logStreamName);
|
||||
}
|
||||
|
||||
return logStream;
|
||||
};
|
||||
|
||||
// Extend the original record with some additional fields
|
||||
// and encapsule records into CloudWatch Logs event.
|
||||
//
|
||||
const buildlogEvents = records => (
|
||||
records.map((record) => {
|
||||
const payload = record;
|
||||
payload.name = 'logs:cloudfront';
|
||||
|
||||
return {
|
||||
message: JSON.stringify(payload),
|
||||
timestamp: new Date(`${payload.date} ${payload.time} UTC`).getTime(),
|
||||
};
|
||||
}).sort((a, b) => a.timestamp - b.timestamp) // Events in a request must be chronological ordered
|
||||
);
|
||||
|
||||
// Send the given documents to CloudWatch Logs group.
|
||||
//
|
||||
exports.putLogEvents = async (records) => {
|
||||
const groupedRecords = groupBy(records, 'date');
|
||||
|
||||
const putLogEventsCalls = Object.keys(groupedRecords).map(async (key) => {
|
||||
const logStream = await describeLogStream(key);
|
||||
|
||||
const params = {
|
||||
logEvents: buildlogEvents(groupedRecords[key]),
|
||||
logGroupName,
|
||||
logStreamName: logStream.logStreamName,
|
||||
sequenceToken: logStream.uploadSequenceToken,
|
||||
};
|
||||
|
||||
return cloudwatchlogs.putLogEvents(params).promise();
|
||||
});
|
||||
|
||||
return Promise.all(putLogEventsCalls);
|
||||
};
|
||||
Reference in New Issue
Block a user