Skip to content
This repository has been archived by the owner on Jan 5, 2022. It is now read-only.

Commit

Permalink
DynamoDB custom metrics generator.
Browse files Browse the repository at this point in the history
  • Loading branch information
rafalwrzeszcz committed Jul 29, 2019
1 parent 6230015 commit c12ff99
Show file tree
Hide file tree
Showing 15 changed files with 775 additions and 0 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ resource.

**CloudFormation** custom resource handler for setting log retention for **CloudWatch** log groups.

## [Lambda-Metrics DynamoDb](https://rafalwrzeszcz-wrzasqpl.github.io/pl.wrzasq.lambda/lambda-metrics/lambda-metrics-dynamodb/)

**CloudWatch** custom metrics for **DynamoDb**.

# Resources

- [GitHub page with API documentation](https://rafalwrzeszcz-wrzasqpl.github.io/pl.wrzasq.lambda)
Expand Down
104 changes: 104 additions & 0 deletions lambda-metrics/lambda-metrics-dynamodb/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
# This file is part of the pl.wrzasq.lambda.
#
# @license http://mit-license.org/ The MIT license
# @copyright 2019 © by Rafał Wrzeszcz - Wrzasq.pl.
-->
<project
xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd
">
<modelVersion>4.0.0</modelVersion>

<!-- core project settings -->
<artifactId>lambda-metrics-dynamodb</artifactId>
<packaging>jar</packaging>
<parent>
<groupId>pl.wrzasq.lambda</groupId>
<artifactId>lambda-metrics</artifactId>
<version>1.0.31-SNAPSHOT</version>
<relativePath>../</relativePath>
</parent>

<!-- project meta info -->
<name>WrzasqPl CloudWatch DynamoDb metrics</name>
<url>https://rafalwrzeszcz-wrzasqpl.github.io/pl.wrzasq.lambda/lambda-metrics/lambda-metrics-dynamodb/</url>
<description>DynamoDb additional CloudWatch metrics.</description>
<inceptionYear>2019</inceptionYear>

<!-- plugins configuration -->
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<configuration>
<usedDependencies>
<usedDependency>com.amazonaws:aws-xray-recorder-sdk-aws-sdk</usedDependency>
<usedDependency>com.amazonaws:aws-xray-recorder-sdk-aws-sdk-instrumentor</usedDependency>
<usedDependency>io.symphonia:lambda-logging</usedDependency>
</usedDependencies>
</configuration>
</plugin>

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
</plugin>
</plugins>
</build>

<!-- project dependencies -->
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>lambda-json</artifactId>
<version>${project.version}</version>
</dependency>

<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk-cloudwatch</artifactId>
<version>1.11.588</version>
</dependency>

<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk-dynamodb</artifactId>
<version>1.11.588</version>
</dependency>

<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-xray-recorder-sdk-aws-sdk</artifactId>
<version>2.2.1</version>
</dependency>

<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-xray-recorder-sdk-aws-sdk-instrumentor</artifactId>
<version>2.2.1</version>
</dependency>

<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.9.1</version>
</dependency>

<dependency>
<groupId>io.symphonia</groupId>
<artifactId>lambda-logging</artifactId>
<version>1.0.3</version>
</dependency>

<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.26</version>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
^/\*$
^ \* This file is part of the pl\.wrzasq\.lambda\.$
^ \*$
^ \* @license http://mit-license\.org/ The MIT license$
^ \* @copyright \d{4}[0-9, -]* © by Rafał Wrzeszcz - Wrzasq\.pl\.$
^ \*/$

^package pl\.wrzasq\.lambda\.metrics\.dynamodb(\..+)?;$
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/*
* This file is part of the pl.wrzasq.lambda.
*
* @license http://mit-license.org/ The MIT license
* @copyright 2019 © by Rafał Wrzeszcz - Wrzasq.pl.
*/

package pl.wrzasq.lambda.metrics.dynamodb;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import com.amazonaws.services.cloudwatch.AmazonCloudWatchClientBuilder;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.AllArgsConstructor;
import pl.wrzasq.lambda.json.ObjectMapperFactory;
import pl.wrzasq.lambda.metrics.dynamodb.model.TableMetricRequest;
import pl.wrzasq.lambda.metrics.dynamodb.service.CloudWatchDynamoDbMetricGenerator;

/**
* CloudWatch Events request handler.
*
* <p>Required environment variables:</p>
*
* <dl>
* <dt><tt>METRICS_NAMESPACE</tt></dt>
* <dd>Namespace to use for CloudWatch metrics.</dd>
* </dl>
*
* <p>Recommended memory: 256MB.</p>
*/
@AllArgsConstructor
public class Handler {
/**
* Metrics namespace to use.
*/
private static final String METRICS_NAMESPACE = System.getenv("METRICS_NAMESPACE");

/**
* JSON handler.
*/
private ObjectMapper objectMapper;

/**
* DynamoDB metrics generator.
*/
private CloudWatchDynamoDbMetricGenerator metricGenerator;

/**
* Default constructure.
*/
public Handler() {
this(
ObjectMapperFactory.createObjectMapper(),
new CloudWatchDynamoDbMetricGenerator(
AmazonDynamoDBClientBuilder.standard().build(),
AmazonCloudWatchClientBuilder.standard().build(),
Handler.METRICS_NAMESPACE
)
);
}

/**
* Handles invocation.
*
* @param inputStream Request input.
* @param outputStream Output stream.
* @throws IOException When JSON loading/dumping fails.
*/
public void handle(InputStream inputStream, OutputStream outputStream) throws IOException {
try {
TableMetricRequest request = this.objectMapper.readValue(inputStream, TableMetricRequest.class);

this.metricGenerator.generateMetrics(request.getTableName());
} finally {
outputStream.close();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
* This file is part of the pl.wrzasq.lambda.
*
* @license http://mit-license.org/ The MIT license
* @copyright 2019 © by Rafał Wrzeszcz - Wrzasq.pl.
*/

package pl.wrzasq.lambda.metrics.dynamodb.model;

import lombok.Data;

/**
* Request specifying subject table.
*/
@Data
public class TableMetricRequest {
/**
* DynamoDb table name.
*/
private String tableName;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
/*
* This file is part of the pl.wrzasq.lambda.
*
* @license http://mit-license.org/ The MIT license
* @copyright 2019 © by Rafał Wrzeszcz - Wrzasq.pl.
*/

package pl.wrzasq.lambda.metrics.dynamodb.service;

import com.amazonaws.services.cloudwatch.AmazonCloudWatch;
import com.amazonaws.services.cloudwatch.model.Dimension;
import com.amazonaws.services.cloudwatch.model.MetricDatum;
import com.amazonaws.services.cloudwatch.model.PutMetricDataRequest;
import com.amazonaws.services.cloudwatch.model.StandardUnit;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
import com.amazonaws.services.dynamodbv2.model.TableDescription;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* CloudWatch metrics handler.
*/
public class CloudWatchDynamoDbMetricGenerator {
/**
* Logger.
*/
private Logger logger = LoggerFactory.getLogger(CloudWatchDynamoDbMetricGenerator.class);

/**
* AWS DynamoDB client.
*/
private AmazonDynamoDB dynamoDb;

/**
* AWS CloudWatch client.
*/
private AmazonCloudWatch cloudWatch;

/**
* Metrics namespace to use.
*/
private String namespace;

/**
* Initializes object.
*
* @param dynamoDb DynamoDB client.
* @param cloudWatch CloudWatch client.
* @param namespace Metrics namespace.
*/
public CloudWatchDynamoDbMetricGenerator(AmazonDynamoDB dynamoDb, AmazonCloudWatch cloudWatch, String namespace) {
this.dynamoDb = dynamoDb;
this.cloudWatch = cloudWatch;
this.namespace = namespace;
}

/**
* Table metrics generator.
*
* @param tableName Table name.
*/
public void generateMetrics(String tableName) {
this.logger.info("Generating metrics for table: {}.", tableName);

TableDescription table = this.dynamoDb.describeTable(tableName).getTable();

this.putSingleMetric(tableName, "ItemCount", table.getItemCount(), StandardUnit.None);
this.putSingleMetric(tableName, "TableSizeBytes", table.getTableSizeBytes(), StandardUnit.Bytes);
}

/**
* Saves single metric value in CloudWatch.
*
* @param tableName DynamoDB table name.
* @param metricName Metric name.
* @param value Metric value.
* @param unit Metric unit.
*/
private void putSingleMetric(String tableName, String metricName, double value, StandardUnit unit) {
this.cloudWatch.putMetricData(
new PutMetricDataRequest()
.withNamespace(this.namespace)
.withMetricData(
new MetricDatum()
.withMetricName(metricName)
.withValue(value)
.withUnit(unit)
.withDimensions(
new Dimension()
.withName("TableName")
.withValue(tableName)
)
)
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
# This file is part of the pl.wrzasq.lambda.
#
# @license http://mit-license.org/ The MIT license
# @copyright 2019 © by Rafał Wrzeszcz - Wrzasq.pl.
-->
<configuration scan="true">
<!-- stdout output -->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n%ex{full}</pattern>
</encoder>
</appender>

<!-- our logger instances -->
<logger name="com.amazonaws">
<level value="INFO"/>
<appender-ref ref="CONSOLE"/>
</logger>
<logger name="com.sunrun.cfnresponse">
<level value="INFO"/>
<appender-ref ref="CONSOLE"/>
</logger>
<logger name="pl.wrzasq">
<level value="INFO"/>
<appender-ref ref="CONSOLE"/>
</logger>
</configuration>

0 comments on commit c12ff99

Please sign in to comment.