From d25abdb8ff027003e1f100ee9207a98287523423 Mon Sep 17 00:00:00 2001 From: Jiri Tomek Date: Wed, 22 May 2019 17:54:16 +0200 Subject: [PATCH 1/3] Changed from GetMetricStatistics to GetMetricData --- index.js | 214 ++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 141 insertions(+), 73 deletions(-) diff --git a/index.js b/index.js index c7faddf..e386e81 100644 --- a/index.js +++ b/index.js @@ -3,6 +3,9 @@ var AWS = require('aws-sdk') , Q = require('q') , request = require('request'); +var counter = 0; +var metricDataQueriesDict = {}; + //loggly url, token and tag configuration //user need to edit while uploading code via blueprint var logglyConfiguration = { @@ -10,8 +13,8 @@ var logglyConfiguration = { tags: 'CloudwatchMetrics' }; -var encryptedLogglyToken = "your KMS encypted key"; -var encryptedLogglyTokenBuffer = new Buffer(encryptedLogglyToken, "base64"); +var encryptedLogglyToken = "your KMS encrypted key"; +var encryptedLogglyTokenBuffer = Buffer.from(encryptedLogglyToken, "base64"); var kms = new AWS.KMS({ apiVersion: '2014-11-01' @@ -23,24 +26,23 @@ var cloudwatch = new AWS.CloudWatch({ //entry point exports.handler = function (event, context) { - var finalData = []; - var parsedStatics = []; + var parsedStatistics = []; var nowDate = new Date(); var date = nowDate.getTime(); - //time upto which we want to fetch Metrics Statics + //time up to which we want to fetch Metrics Statistics //we keep it one hour var logEndTime = nowDate.toISOString(); - //time from which we want to fetch Metrics Statics + //time from which we want to fetch Metrics Statistics var logStartTime = new Date(date - (05 * 60 * 1000)).toISOString(); //initiate the script here decryptLogglyToken().then(function () { getMetricsListFromAWSCloudwatch().then(function () { - sendRemainingStatics().then(function () { - context.done('all statics are sent to Loggly'); + sendRemainingStatistics().then(function () { + context.done('all statistics are sent to Loggly'); }, function () { context.done(); }); @@ -58,7 +60,7 @@ exports.handler = function (event, context) { var params = { CiphertextBlob: encryptedLogglyTokenBuffer }; - + kms.decrypt(params, function (err, data) { if (err) { console.log(err, err.stack); // an error occurred @@ -113,19 +115,33 @@ exports.handler = function (event, context) { else { var pMetricName, pNamespace, pName, pValue; + var queries = []; for (var i = 0; i < result.Metrics.length; i++) { pNamespace = result.Metrics[i].Namespace; pMetricName = result.Metrics[i].MetricName; for (var j = 0; j < result.Metrics[i].Dimensions.length; j++) { pName = result.Metrics[i].Dimensions[j].Name pValue = result.Metrics[i].Dimensions[j].Value + + if (!pName || !pValue) continue; + + queries.push({metricName: pMetricName, namespace: pNamespace, name: pName, value: pValue}); + if (queries.length == 20) { + var promise = fetchMetricDataFromMetrics(queries); + promisesResult.push(promise); + queries = []; + } } - var promise = fetchMetricStatisticsFromMetrics(pNamespace, pMetricName, pName, pValue); - promisesResult.push(promise) + } + + if (queries.length > 0) { + var promise = fetchMetricDataFromMetrics(queries); + promisesResult.push(promise); + queries = []; } } - if (result.NextToken) { + if (result.NextToken) { getMetricsList(result.NextToken); } else { @@ -142,9 +158,25 @@ exports.handler = function (event, context) { }); } - //Gets statistics for the specified metric. - function fetchMetricStatisticsFromMetrics(namespace, metricName, dName, dValue) { - var MetricStatisticsPromises = []; + function getMetricDataQuery(query, stat, id) { + return { + Id: id, + MetricStat: { + Metric: { + Namespace: query.namespace, + MetricName: query.metricName, + Dimensions: [{ + Name: query.name, + Value: query.value + }] + }, + Period: 60, + Stat: stat + } + }; + } + + function fetchMetricDataFromMetrics(queries) { return Q.Promise(function (resolve, reject) { /*The maximum number of data points returned from a single GetMetricStatistics request is 1,440, @@ -153,65 +185,101 @@ exports.handler = function (event, context) { you can alter the request by narrowing the specified time range or increasing the specified period. Alternatively, you can make multiple requests across adjacent time ranges.*/ + var metricDataQueries = []; + for (var q in queries) { + var id = 'm' + counter; + metricDataQueriesDict[id] = queries[q]; + + metricDataQueries.push(getMetricDataQuery(queries[q], 'Average', id + '_average')); + metricDataQueries.push(getMetricDataQuery(queries[q], 'Minimum', id + '_minimum')); + metricDataQueries.push(getMetricDataQuery(queries[q], 'Maximum', id + '_maximum')); + metricDataQueries.push(getMetricDataQuery(queries[q], 'SampleCount', id + '_samplecount')); + metricDataQueries.push(getMetricDataQuery(queries[q], 'Sum', id + '_sum')); + counter++; + } + var params = { EndTime: logEndTime, //required - MetricName: metricName, //required - Namespace: namespace, //required - Period: 60, //required StartTime: logStartTime, //required - Statistics: [ //required - 'Average', 'Minimum', 'Maximum', 'SampleCount', 'Sum' - ], - Dimensions: [{ - Name: dName, // required - Value: dValue //required - }, - /* more items */ - ], - + MetricDataQueries: metricDataQueries }; - var Promises = []; - try { - cloudwatch.getMetricStatistics(params, function (err, data) { - if (err) console.log(err, err.stack); // an error occurred - else { - for (var a in data.Datapoints) { - var promise = parseStatics(data.Datapoints[a], data.ResponseMetadata, data.Label, dName, dValue, namespace) - Promises.push(promise); + + function fetch(params, nextToken) { + if (nextToken != null) { + params.NextToken = nextToken; + } + + var promises = []; + try { + cloudwatch.getMetricData(params, function (err, data) { + if (err) { + console.log(err, err.stack); // an error occurred } - Q.allSettled(Promises).then(function () { - resolve(); - }, function () { - reject(); - }); - } - }); - } - catch (e) { - console.log(e); + else { + var resultsByStat = {} + for (var a in data.MetricDataResults) { + var metricId = data.MetricDataResults[a].Id; + var parts = metricId.split('_'); + resultsByStat[parts[0]] = resultsByStat[parts[0]] || {}; + resultsByStat[parts[0]][parts[1]] = data.MetricDataResults[a]; + } + + for (var id in resultsByStat) { + for (var i in resultsByStat[id]['average'].Timestamps) { + var timestamp = resultsByStat[id]['average'].Timestamps[i]; + var average = resultsByStat[id]['average'].Values[i]; + var minimum = resultsByStat[id]['minimum'].Values[i]; + var maximum = resultsByStat[id]['maximum'].Values[i]; + var samplecount = resultsByStat[id]['samplecount'].Values[i]; + var sum = resultsByStat[id]['sum'].Values[i]; + + var promise = parseStatistics(timestamp, average, minimum, maximum, samplecount, sum, + metricDataQueriesDict[id].metricName, + metricDataQueriesDict[id].name, + metricDataQueriesDict[id].value, + metricDataQueriesDict[id].namespace) + promises.push(promise); + } + } + Q.allSettled(promises).then(function () { + resolve(); + }, function () { + reject(); + }); + } + + if (data.NextToken) { + fetch(params, data.NextToken); + } + }); + } + catch (e) { + console.log(e); + } } + fetch(params); }); } - //converts the Statics to a valid JSON object with the sufficient infomation required + //converts the Statistics to a valid JSON object with the sufficient infomation required - function parseStatics(metricsStatics, responseMetadata, metricName, dimensionName, dimensionValue, namespace) { + function parseStatistics(timestamp, average, minimum, maximum, samplecount, sum, metricName, dimensionName, + dimensionValue, namespace) { return Q.promise(function (resolve, reject) { var staticdata = { - "timestamp": metricsStatics.Timestamp.toISOString(), - "sampleCount": metricsStatics.SampleCount, - "average": metricsStatics.Average, - "sum": metricsStatics.Sum, - "minimum": metricsStatics.Minimum, - "maximum": metricsStatics.Maximum, - "unit": metricsStatics.Unit, + "timestamp": timestamp.toISOString(), + "sampleCount": samplecount, + "average": average, + "sum": sum, + "minimum": minimum, + "maximum": maximum, "metricName": metricName, "namespace": namespace }; staticdata[firstToLowerCase(dimensionName)] = dimensionValue; - postStaticsToLoggly(staticdata).then(function () { + postStatisticsToLoggly(staticdata).then(function () { resolve(); }, function () { reject(); @@ -220,30 +288,30 @@ exports.handler = function (event, context) { }); } - //uploads the statics to Loggly - //we will hold the statics in an array until they reaches to 200 + //uploads the statistics to Loggly + //we will hold the statistics in an array until they reaches to 200 //then set the count of zero. - function postStaticsToLoggly(event) { + function postStatisticsToLoggly(event) { return Q.promise(function (resolve, reject) { - if (parsedStatics.length == 200) { + if (parsedStatistics.length == 200) { upload().then(function () { resolve(); }, function () { reject(); }); } else { - parsedStatics.push(event); + parsedStatistics.push(event); resolve(); } }); } - //checks if any more statics are left - //after sending Statics in multiples of 100 - function sendRemainingStatics() { + //checks if any more statistics are left + //after sending Statistics in multiples of 100 + function sendRemainingStatistics() { return Q.promise(function (resolve, reject) { - if (parsedStatics.length > 0) { + if (parsedStatistics.length > 0) { upload().then(function () { resolve(); }, function () { @@ -258,19 +326,19 @@ exports.handler = function (event, context) { function upload() { return Q.promise(function (resolve, reject) { - //get all the Statics, stringify them and join them + //get all the Statistics, stringify them and join them //with the new line character which can be sent to Loggly //via bulk endpoint - var finalResult = parsedStatics.map(JSON.stringify).join('\n'); + var finalResult = parsedStatistics.map(JSON.stringify).join('\n'); - //empty the main statics array immediately to hold new statics - parsedStatics.length = 0; + //empty the main statistics array immediately to hold new statistics + parsedStatistics.length = 0; //creating logglyURL at runtime, so that user can change the tag or customer token in the go //by modifying the current script var logglyURL = logglyConfiguration.url + '/' + logglyConfiguration.customerToken + '/tag/' + logglyConfiguration.tags; - //create request options to send Statics + //create request options to send Statistics try { var requestOptions = { uri: logglyURL, @@ -280,10 +348,10 @@ exports.handler = function (event, context) { requestOptions.body = finalResult; - //now send the Statics to Loggly + //now send the Statistics to Loggly request(requestOptions, function (err, response, body) { if (err) { - console.log('Error while uploading Statics to Loggly'); + console.log('Error while uploading Statistics to Loggly'); reject(); } else { resolve(); @@ -301,4 +369,4 @@ exports.handler = function (event, context) { function firstToLowerCase(str) { return str.substr(0, 1).toLowerCase() + str.substr(1); } -} +} \ No newline at end of file From 382d2537d35549816fb3c6b5d7f510b727a955e5 Mon Sep 17 00:00:00 2001 From: Jiri Tomek Date: Thu, 23 May 2019 13:40:24 +0200 Subject: [PATCH 2/3] Updated script to use environment variable to get customer token, updated README --- README.md | 98 +++++++++++++++++++++++++++------------------------- index.js | 15 ++++---- package.json | 8 ++--- 3 files changed, 63 insertions(+), 58 deletions(-) diff --git a/README.md b/README.md index b612337..c422430 100644 --- a/README.md +++ b/README.md @@ -5,56 +5,58 @@ Sends AWS Cloudwatch metrics to Loggly * http://aws.amazon.com/lambda/ * https://www.loggly.com/ -## Get the code and prepare it for the uploading to AWS -* Clone the git repo -```bash -git clone https://github.com/psquickitjayant/cloudwatch-metrics-to-loggly.git -cd cloudwatch-metrics-to-loggly -``` -* Install required npm packages. -``` -npm install -``` +## Getting started with AWS Lambda +Getting started documentation for AWS lambda can be found in [this +article](https://docs.aws.amazon.com/lambda/latest/dg/getting-started.html). There is also [this blog post](http://alestic.com/2014/11/aws-lambda-cli) on how to set things up using the command line tools. -* zip up your code -```bash -zip -r cloudwatchMetrics2Loggly.zip index.js node_modules -``` - -The resulting zip (cloudwatchMetrics2Loggly.zip) is what you will upload to AWS. - -## Setting up AWS -For all of the AWS setup, I used the AWS console following [this -example](http://docs.aws.amazon.com/lambda/latest/dg/getting-started-amazons3-events.html). Below, you will find a high-level -description of how to do this. I also found [this blog post](http://alestic.com/2014/11/aws-lambda-cli) on how to set things up -using the command line tools. - -### Create and upload the cloudwatchMetrics2Loggly function in the AWS Console +## Creating lambda function in AWS +1. Build lambda function code + 1. Clone the Git repository: + `git clone https://github.com/psquickitjayant/cloudwatch-metrics-to-loggly.git` + 1. Go to cloned folder: + `cd cloudwatch-metrics-to-loggly` + 1. Install dependencies: + `npm install` + 1. Create a .zip file for upload to AWS console later: + `zip -r cloudwatchMetrics2Loggly.zip index.js node_modules` 1. Create Role - 1. Sign in to your AWS account and open IAM console https://console.aws.amazon.com/iam/ - 2. In your IAM console create a new Role say, 'cloudwatch-full-access' - 3. Select Role Type as 'AWS Lambda' - 4. Apply policy 'CloudWatchFullAccess' and save. -2. Create KMS Key - 1. Create a KMS key - http://docs.aws.amazon.com/kms/latest/developerguide/create-keys.html - 2. Encrypt the Loggly Customer Token using the AWS CLI - **aws kms encrypt --key-id alias/<your KMS key arn> --plaintext "<your loggly customer token>"** - 3. Copy the base-64 encoded, encrypted token from step 2's CLI output (CiphertextBlob attribute) and replace it with the "your KMS encypted key" in the script at line no 13 -3. Create lambda function - 1. https://console.aws.amazon.com/lambda/home - 2. Click "Create a Lambda function" button. *(Choose "Upload a .ZIP file")* - * **Name:** *cloudwatchMetrics2Loggly* - * Upload lambda function (zip file you made above.) - * **Handler*:** *index.handler* - * Set Role : *cloudwatch-full-access* - * Set Timeout to 2 minutes - 3. Go to your Lamda function and select the "Event sources" tab - * Click on **Add Event Source** - * Event Source Type : *Cloudwatch Events - Schedule* - * Name : Provide any customized name. e.g. cloudwatchMetrics2Loggly Event Source - * Description: Invokes Lambda function in every 5 minutes - * Schedule expression : *rate(5 minutes)* - * Enable Event Source : *Enable Now* - Now click on submit and wait for the events to occur in Loggly + 1. Sign in to your AWS account and open IAM console https://console.aws.amazon.com/iam/ + 2. In your IAM console create a new Role say, `cloudwatch-full-access` + 3. Select Role Type as **AWS Lambda** + 4. Apply policy **CloudWatchFullAccess** and save. +1. Create KMS Key + 1. Create a KMS key - http://docs.aws.amazon.com/kms/latest/developerguide/create-keys.html + 1. Encrypt the Loggly Customer Token using the AWS CLI + `aws kms encrypt --key-id alias/ --plaintext ""` + 1. Copy or keep `CiphertextBlob` attribute for furhter usage in the next step. +1. Create lambda function + 1. Go to https://console.aws.amazon.com/lambda/home + 1. Click **Create a Lambda function** button. + 1. Select **Author from scratch** option + 1. Set **Function name** for example to `cloudwatchMetrics2Loggly` + 1. Set **Runtime** to `Node.js 10.x` + 1. Under **Permissions** click on **Choose or create an execution role** + 1. Select **Use an existing role** and select **cloudwatch-full-access** role created above in step 1 + 1. Click on **Create function** button + 1. Scroll to **Function code** section + 1. Select **Upload a .zip file** in **Code entry type** dropdown + 1. Upload lambda function (zip file `cloudwatchMetrics2Loggly.zip` you made above) + 1. Go to **Environment variables** section + 1. Define new environment variable **kmsEncryptedCustomerToken** and set it to `CiphertextBlob` value from step 3 above (Create KMS Key) + 1. Scroll to **Basic settings** section + 1. Set **Memory (MB)** to **512 MB** + 1. Set Timeout to **2** minutes + 1. Scroll up to **Designer** section (expand if it's collapsed) + 1. Click on **CloudWatch Events** in **Add triggers** section to add the trigger item + 1. Click on added **CloudWatch Events** trigger and scroll down to trigger settings + 1. Select **Create a new rule** in **Rule** dropdown + 1. **Name:** Provide any customized name. e.g. cloudwatchMetrics2Loggly Event Source + 1. **Description:** Invokes Lambda function in every 5 minutes + 1. **Schedule expression:** rate(5 minutes) + 1. Make sure the checkbox **Enable trigger** is checked + 1. Click on **Add** + 1. Click on **Save** to save the whole lambda function. + 1. Wait for the events to occur in Loggly **NOTE**: Always use latest version of **AWSCLI**. Some features like KMS may not work on older versions of AWSCLI. To upgrade, use the command given below diff --git a/index.js b/index.js index e386e81..0228833 100644 --- a/index.js +++ b/index.js @@ -13,9 +13,6 @@ var logglyConfiguration = { tags: 'CloudwatchMetrics' }; -var encryptedLogglyToken = "your KMS encrypted key"; -var encryptedLogglyTokenBuffer = Buffer.from(encryptedLogglyToken, "base64"); - var kms = new AWS.KMS({ apiVersion: '2014-11-01' }); @@ -42,21 +39,27 @@ exports.handler = function (event, context) { decryptLogglyToken().then(function () { getMetricsListFromAWSCloudwatch().then(function () { sendRemainingStatistics().then(function () { - context.done('all statistics are sent to Loggly'); + context.done(); }, function () { context.done(); }); }, function () { context.done(); }); - }, function () { - context.done(); + }, function (reason) { + context.done(reason); }); //decrypts your Loggly Token from your KMS key function decryptLogglyToken() { return Q.Promise(function (resolve, reject) { + if (!process.env.kmsEncryptedCustomerToken) { + reject("Environment variable 'kmsEncryptedCustomerToken' is not defined. Define 'kmsEncryptedCustomerToken' " + + "environment variable and set it to KMS encrypted customer token for Loggly."); + } + + var encryptedLogglyTokenBuffer = Buffer.from(process.env.kmsEncryptedCustomerToken, "base64"); var params = { CiphertextBlob: encryptedLogglyTokenBuffer }; diff --git a/package.json b/package.json index fe73be4..2d61ece 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cloudwatch-metrics-to-loggly", - "version": "1.0.0", + "version": "2.0.0", "description": "A NodeJS library to send Cloudwatch Metrics to Loggly", "main": "index.js", "scripts": { @@ -8,7 +8,7 @@ }, "repository": { "type": "git", - "url": "https://github.com/psquickitjayant/cloudwatch-metrics-to-loggly.git" + "url": "https://github.com/loggly/cloudwatch-metrics-to-loggly.git" }, "keywords": [ "Loggly", @@ -18,9 +18,9 @@ "author": "psquickitjayant", "license": "MIT", "bugs": { - "url": "https://github.com/psquickitjayant/cloudwatch-metrics-to-loggly/issues" + "url": "https://github.com/loggly/cloudwatch-metrics-to-loggly/issues" }, - "homepage": "https://github.com/psquickitjayant/cloudwatch-metrics-to-loggly", + "homepage": "https://github.com/loggly/cloudwatch-metrics-to-loggly", "dependencies": { "aws-sdk": "^2.2.25", "q": "^1.4.1", From e16d192aa23c079efcb816fa0d865746c1c5bcc7 Mon Sep 17 00:00:00 2001 From: Jiri Tomek Date: Thu, 23 May 2019 13:43:40 +0200 Subject: [PATCH 3/3] Updated readme --- README.md | 76 +++++++++++++++++++++++++++---------------------------- 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/README.md b/README.md index c422430..611c40c 100644 --- a/README.md +++ b/README.md @@ -11,52 +11,52 @@ article](https://docs.aws.amazon.com/lambda/latest/dg/getting-started.html). The ## Creating lambda function in AWS 1. Build lambda function code - 1. Clone the Git repository: + * Clone the Git repository: `git clone https://github.com/psquickitjayant/cloudwatch-metrics-to-loggly.git` - 1. Go to cloned folder: + * Go to cloned folder: `cd cloudwatch-metrics-to-loggly` - 1. Install dependencies: + * Install dependencies: `npm install` - 1. Create a .zip file for upload to AWS console later: + * Create a .zip file for upload to AWS console later: `zip -r cloudwatchMetrics2Loggly.zip index.js node_modules` 1. Create Role - 1. Sign in to your AWS account and open IAM console https://console.aws.amazon.com/iam/ - 2. In your IAM console create a new Role say, `cloudwatch-full-access` - 3. Select Role Type as **AWS Lambda** - 4. Apply policy **CloudWatchFullAccess** and save. + * Sign in to your AWS account and open IAM console https://console.aws.amazon.com/iam/ + * In your IAM console create a new Role say, `cloudwatch-full-access` + * Select Role Type as **AWS Lambda** + * Apply policy **CloudWatchFullAccess** and save. 1. Create KMS Key - 1. Create a KMS key - http://docs.aws.amazon.com/kms/latest/developerguide/create-keys.html - 1. Encrypt the Loggly Customer Token using the AWS CLI + * Create a KMS key - http://docs.aws.amazon.com/kms/latest/developerguide/create-keys.html + * Encrypt the Loggly Customer Token using the AWS CLI `aws kms encrypt --key-id alias/ --plaintext ""` - 1. Copy or keep `CiphertextBlob` attribute for furhter usage in the next step. + * Copy or keep `CiphertextBlob` attribute for furhter usage in the next step. 1. Create lambda function - 1. Go to https://console.aws.amazon.com/lambda/home - 1. Click **Create a Lambda function** button. - 1. Select **Author from scratch** option - 1. Set **Function name** for example to `cloudwatchMetrics2Loggly` - 1. Set **Runtime** to `Node.js 10.x` - 1. Under **Permissions** click on **Choose or create an execution role** - 1. Select **Use an existing role** and select **cloudwatch-full-access** role created above in step 1 - 1. Click on **Create function** button - 1. Scroll to **Function code** section - 1. Select **Upload a .zip file** in **Code entry type** dropdown - 1. Upload lambda function (zip file `cloudwatchMetrics2Loggly.zip` you made above) - 1. Go to **Environment variables** section - 1. Define new environment variable **kmsEncryptedCustomerToken** and set it to `CiphertextBlob` value from step 3 above (Create KMS Key) - 1. Scroll to **Basic settings** section - 1. Set **Memory (MB)** to **512 MB** - 1. Set Timeout to **2** minutes - 1. Scroll up to **Designer** section (expand if it's collapsed) - 1. Click on **CloudWatch Events** in **Add triggers** section to add the trigger item - 1. Click on added **CloudWatch Events** trigger and scroll down to trigger settings - 1. Select **Create a new rule** in **Rule** dropdown - 1. **Name:** Provide any customized name. e.g. cloudwatchMetrics2Loggly Event Source - 1. **Description:** Invokes Lambda function in every 5 minutes - 1. **Schedule expression:** rate(5 minutes) - 1. Make sure the checkbox **Enable trigger** is checked - 1. Click on **Add** - 1. Click on **Save** to save the whole lambda function. - 1. Wait for the events to occur in Loggly + * Go to https://console.aws.amazon.com/lambda/home + * Click **Create a Lambda function** button. + * Select **Author from scratch** option + * Set **Function name** for example to `cloudwatchMetrics2Loggly` + * Set **Runtime** to `Node.js 10.x` + * Under **Permissions** click on **Choose or create an execution role** + * Select **Use an existing role** and select **cloudwatch-full-access** role created above in step 1 + * Click on **Create function** button + * Scroll to **Function code** section + * Select **Upload a .zip file** in **Code entry type** dropdown + * Upload lambda function (zip file `cloudwatchMetrics2Loggly.zip` you made above) + * Go to **Environment variables** section + * Define new environment variable **kmsEncryptedCustomerToken** and set it to `CiphertextBlob` value from step 3 above (Create KMS Key) + * Scroll to **Basic settings** section + * Set **Memory (MB)** to **512 MB** + * Set Timeout to **2** minutes + * Scroll up to **Designer** section (expand if it's collapsed) + * Click on **CloudWatch Events** in **Add triggers** section to add the trigger item + * Click on added **CloudWatch Events** trigger and scroll down to trigger settings + * Select **Create a new rule** in **Rule** dropdown + * **Name:** Provide any customized name. e.g. cloudwatchMetrics2Loggly Event Source + * **Description:** Invokes Lambda function in every 5 minutes + * **Schedule expression:** rate(5 minutes) + * Make sure the checkbox **Enable trigger** is checked + * Click on **Add** + * Click on **Save** to save the whole lambda function. + * Wait for the events to occur in Loggly **NOTE**: Always use latest version of **AWSCLI**. Some features like KMS may not work on older versions of AWSCLI. To upgrade, use the command given below