aws-cloudwatch-forwarder
Version:
Forwards the Stdin to AWS Cloudwatch
247 lines (201 loc) • 6.9 kB
JavaScript
var async = require("async");
var promise = require("the-promise-factory");
module.exports = function (cloudWatchLogs) {
var initConfig = {}
var cachedSequenceToken = null
return {
init: config => {
validateConfig(config)
initConfig = standarizeConfig(config)
logDebugMessage("Configuration: ", initConfig)
return promise.create((fulfill, reject) => {
if (!initConfig.aws.enabled){
fulfill()
return
}
async.waterfall([
initInfo,
readExistingLogGroups,
targetGroupAlreadyExists,
createLogGroup,
readExistingLogStreams,
targetLogStreamAlreadyExists,
readExistingSequenceToken,
createLogStream
], (err, r) => {
if (err){
reject(err)
return
}
fulfill()
})
})
},
send: logLines => {
return promise.create((fulfill, reject) => {
if (!initConfig.aws.enabled){
fulfill()
return
}
logLines = (logLines || []).filter(l => l.message)
if (logLines.length === 0){
fulfill()
return
}
logLines = escapeLineColors(logLines)
var logData = {
logEvents: logLines,
logGroupName: initConfig.aws.logGroupName,
logStreamName: initConfig.aws.logStreamName
}
if (readCachedSequenceToken()){
logData.sequenceToken = readCachedSequenceToken()
}
logDebugMessage("cloudWatchLogs.putLogEvents, length=", logLines.length, "logData=", logData)
cloudWatchLogs.putLogEvents(logData, (err, data) => {
if (err){
reject(err)
return
}
setCachedSequenceToken(data.nextSequenceToken)
fulfill()
})
})
}
}
function readCachedSequenceToken(){
logDebugMessage("readCachedSequenceToken, result= ", cachedSequenceToken)
return cachedSequenceToken
}
function setCachedSequenceToken(value){
logDebugMessage("setCachedSequenceToken, value= ", value)
cachedSequenceToken = value
}
function validateConfig(config){
var awsConfig = ((config || {}).aws || {});
if((awsConfig.logGroupName || "").length === 0){
throw new Error("a logGroupName is required")
}
if((awsConfig.logStreamName || "").length === 0){
throw new Error("a logStreamName is required")
}
}
function standarizeConfig(config){
config = config || {}
config.aws = config.aws || {}
config.aws.debug = config.aws.debug || false
if (config.aws.enabled === false){
config.aws.enabled = false
}
else {
config.aws.enabled = true
}
return config
}
function initInfo(callback){
callback(null, {})
}
function logDebugMessage(message){
if (initConfig.aws.debug){
var updatedArguments = [
`[AWS_FORWARDER_DEBUG] ${message}`
].concat(
Array.from(arguments).slice(1)
)
console.log.apply(console, updatedArguments)
}
}
function readExistingLogGroups(info, callback) {
logDebugMessage("cloudWatchLogs.describeLogGroups")
cloudWatchLogs.describeLogGroups({
logGroupNamePrefix: initConfig.aws.logGroupName
}, (err, data) => {
if (err) {
callback(err)
return
}
info.logGroups = data.logGroups || [];
callback(null, info)
})
}
function targetGroupAlreadyExists(info, callback) {
var result = info.logGroups.find(g => g.logGroupName === initConfig.aws.logGroupName)
info.logGroupAlreadyExists = result;
callback(null, info)
}
function createLogGroup(info, callback){
if (info.logGroupAlreadyExists){
callback(null, info)
return
}
logDebugMessage("cloudWatchLogs.createLogGroup")
cloudWatchLogs.createLogGroup({
logGroupName: initConfig.aws.logGroupName
}, (err, data) => {
if (err){
callback(err)
return
}
callback(null, info)
})
}
function readExistingLogStreams(info, callback){
logDebugMessage("cloudWatchLogs.describeLogStreams")
cloudWatchLogs.describeLogStreams({
logGroupName: initConfig.aws.logGroupName,
logStreamNamePrefix: initConfig.aws.logStreamName
}, (err, data) => {
if (err){
callback(err)
return
}
info.logStreams = data.logStreams || []
callback(null, info)
})
}
function getLogStreamWithName(logStreams, name){
return logStreams.find(s => s.logStreamName === name)
}
function targetLogStreamAlreadyExists(info, callback){
info.logStreamAlreadyExists = getLogStreamWithName(
info.logStreams,
initConfig.aws.logStreamName
)
callback(null, info)
}
function readExistingSequenceToken(info, callback){
if (info.logStreamAlreadyExists){
var logStream = getLogStreamWithName(
info.logStreams,
initConfig.aws.logStreamName
)
setCachedSequenceToken(logStream.uploadSequenceToken)
}
callback(null, info)
}
function createLogStream(info, callback){
if (info.logStreamAlreadyExists){
callback(null, info)
return
}
logDebugMessage("cloudWatchLogs.createLogStream")
cloudWatchLogs.createLogStream({
logGroupName: initConfig.aws.logGroupName,
logStreamName: initConfig.aws.logStreamName
}, (err, data) => {
if (err){
callback(err)
return
}
callback(null, info)
})
}
function escapeLineColors(logLines){
return logLines.map(l => {
return {
timestamp: l.timestamp,
message: l.message.replace(/\[\d+m/g, "")
}
})
}
}