// Edit in other repo then uglify to fit
const AWS=require("aws-sdk");const zlib=require("zlib");AWS.config.update({region:process.env.AWS_REGION});AWS.events.on("retry",function(resp){if(resp.error&&resp.error.code==="Throttling"){resp.error.retryable=true}});AWS.config.update({retryDelayOptions:{base:500}});AWS.config.update({maxRetries:5});const cloudwatch=new AWS.CloudWatch;const sns=new AWS.SNS;const TaggableNamespaces=["AWS/ApplicationELB"];let tagCache={};exports.handler=((event,context,callback)=>{let timestamp=Math.round((new Date).getTime()/1e3);collectMetrics(timestamp).then(metricPromises=>{Promise.all(metricPromises).then(metrics=>{sensuMetrics(metrics).then(result=>{callback(null,result)}).catch(err=>{callback(err)})}).catch(err=>{callback(err)})}).catch(err=>{callback(err)})});const collectMetrics=timestamp=>{return new Promise((resolve,reject)=>{let metricPromises=[];cloudwatch.listMetrics().eachPage((err,data)=>{if(err){console.log(err);reject(err);return}if(data===null){resolve(metricPromises);return}metricPromises=metricPromises.concat(data.Metrics.map(metricDefinition=>{return getMetric(metricDefinition,timestamp)}))})})};const getMetric=(metricDefinition,timestamp)=>{let params={StartTime:timestamp-300,EndTime:timestamp,MetricName:metricDefinition.MetricName,Namespace:metricDefinition.Namespace,Period:60,Dimensions:metricDefinition.Dimensions,Statistics:["Average","Maximum","Minimum","Sum","SampleCount"]};return new Promise((resolve,reject)=>{cloudwatch.getMetricStatistics(params,(err,metric)=>{if(err){console.log(err);reject(err);return}if(metric.Datapoints.length===0){resolve();return}resolve({Definition:metricDefinition,Metric:metric})})})};const sensuMetrics=metrics=>{return new Promise((resolve,reject)=>{let date=Math.round((new Date).getTime()/1e3);let output=[];for(let i=0;i<metrics.length;i++){if(metrics[i]===undefined)continue;let tagSet={};for(let j=0;j<metrics[i].Definition.Dimensions.length;j++){tagSet[metrics[i].Definition.Dimensions[j].Name]=metrics[i].Definition.Dimensions[j].Value}tagSet.Namespace=metrics[i].Definition.Namespace;tagSet.AwsAccountId=process.env.AWSAccountId;tagSet.Stage=process.env.STAGE;tagSet.Region=process.env.AWS_REGION;tagSet.Environment=process.env.PROJECT;for(let k=0;k<metrics[i].Metric.Datapoints.length;k++){let filteredValues={};for(let key in metrics[i].Metric.Datapoints[k]){filteredValues[key]=metrics[i].Metric.Datapoints[k][key]}delete filteredValues.Timestamp;delete filteredValues.Unit;output.push({source:"cloudwatch",series:metrics[i].Metric.Label,tags:tagSet,timestamp:metrics[i].Metric.Datapoints[k].Timestamp,unit:metrics[i].Metric.Datapoints[k].Unit,values:filteredValues})}}const batchSize=5e3;console.info(`Discovered ${output.length} data points, submitting ${batchSize} at a time`);let batch_success=0;const batches=Math.ceil(output.length/batchSize);for(let i=0;i<output.length;i+=batchSize){console.log(`Submitting points ${i} to ${i+batchSize}`);zlib.gzip(JSON.stringify(output.slice(i,i+batchSize)),(err,buffer)=>{if(err)console.log("Error during compression: ",err);let data={client:"cloudwatch-"+process.env.PROJECT+"-"+process.env.STAGE,check:{type:"metric",status:0,ttl:900,interval:60,name:process.env.AWS_REGION+"-metrics",awsAccountId:process.env.AWSAccountId,stage:process.env.STAGE,region:process.env.AWS_REGION,environment:process.env.PROJECT,issued:date,executed:date,timestamp:date,output:buffer.toString("base64"),handlers:["charon-relay"]}};let params={Message:JSON.stringify(data),TopicArn:"arn:aws:sns:"+process.env.AWS_REGION+":"+process.env.AWSAccountId+":sensu_ingress",MessageAttributes:{pipe:{DataType:"String",StringValue:"results"},type:{DataType:"String",StringValue:"direct"}}};sns.publish(params,(snserr,results)=>{if(snserr){reject(snserr)}else{console.log(`Done submitting ${i} to ${i+batchSize}. Currently ${batch_success} of ${batches} successful batches.`);batch_success++;if(batch_success>=batches){console.info("Successfully saved "+output.length);resolve("Processed "+output.length+" data points. "+results)}}})})}})};
