skip to Main Content

I am trying to retrieve some Elasticache metrics from CloudWatch using Java SDK 1.x. I have several classes for multiple services, and they all work, except for Elasticache. This class is passed a list of Elasticache nodes, along with start and end times. For each node, I’m attempting to retrieve some metrics from Elasticache with a 30-minute period. However, for some reason, I keep getting values of 0.0 for each metric. I have confirmed that the metrics are not empty in the AWS console. Here’s my code:

public class ElastiCacheCWMetricsRetriever {
    private final AmazonCloudWatch cloudWatchClient;

    public ElastiCacheCWMetricsRetriever(AmazonCloudWatch cloudWatchClient) {
        this.cloudWatchClient = cloudWatchClient;
    }


    public Map<String, Map<String, Object>> getElastiCacheMetrics(List<String> nodeNames, 
        String startTimeStr, String endTimeStr) {
        Map<String, Map<String, Object>> elastiCacheMetricsMap = new HashMap<>();

        try {
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
            Date startTime = dateFormat.parse(startTimeStr);
            Date endTime = dateFormat.parse(endTimeStr);

            for (String nodeName : nodeNames) {
                Map<String, Object> nodeMetrics = new HashMap<>();

                nodeMetrics.put("SwapUsage", getAverageMetricValue("AWS/ElastiCache", 
                    "SwapUsage", "CacheNodeId", nodeName, startTime, endTime));
                Double SwapUsage = getSumMetricValue("AWS/ElastiCache", "SwapUsage", 
                    "CacheNodeId", nodeName, startTime, endTime);
                System.out.println("SwapUsage for " + nodeName + " is " + 
                    String.valueOf(SwapUsage));

                nodeMetrics.put("CurrentConnections", getSumMetricValue("AWS/ElastiCache", 
                    "CurrConnections", "CacheNodeId", nodeName, startTime, endTime));

                nodeMetrics.put("DatabaseMemoryUsagePercentage", 
                getAverageMetricValue("AWS/ElastiCache", "DatabaseMemoryUsagePercentage", 
                    "CacheNodeId", nodeName, startTime, endTime) * 100.0);

                nodeMetrics.put("EngineCPUUtilization", 
                     getAverageMetricValue("AWS/ElastiCache", "EngineCPUUtilization", 
                     "CacheNodeId", nodeName, startTime, endTime) * 100.0);

                Double EngineCPUUtil = getAverageMetricValue("AWS/ElastiCache", 
                    "EngineCPUUtilization", "CacheNodeId", nodeName, startTime, endTime) * 100.0;
                System.out.println("EngineCPUUtilization for " + nodeName + " is " + String.valueOf(EngineCPUUtil));
                elastiCacheMetricsMap.put(nodeName, nodeMetrics);
            }
        } catch (Exception e) {
            System.out.println("Error in Elasticache" + e.getMessage());
        }   
        return elastiCacheMetricsMap;
    }

     private double getAverageMetricValue(String namespace, String metricName, String 
         dimensionName, String dimensionValue, Date startTime, Date endTime) {
         int period = calculatePeriod(startTime, endTime);
         return getMetricValue(namespace, metricName, dimensionName, dimensionValue, startTime, endTime, period, "Average");
     }

    private double getSumMetricValue(String namespace, String metricName, String dimensionName, String dimensionValue, Date startTime, Date endTime) {
        int period = calculatePeriod(startTime, endTime);
        return getMetricValue(namespace, metricName, dimensionName, dimensionValue, startTime, endTime, period, "Sum");
    }

    private double getMetricValue(String namespace, String metricName, String dimensionName, String dimensionValue, Date startTime, Date endTime, int period, String statistic) {
        try {
            GetMetricStatisticsRequest request = new GetMetricStatisticsRequest()
                .withNamespace(namespace)
                .withMetricName(metricName)
                .withDimensions(new Dimension().withName(dimensionName).withValue(dimensionValue))
                .withStartTime(startTime)
                .withEndTime(endTime)
                .withPeriod(period)
                .withStatistics(statistic);

            GetMetricStatisticsResult result = cloudWatchClient.getMetricStatistics(request);
            System.out.println("Result for " + dimensionValue + " is " + result.toString());
            return result.getDatapoints().isEmpty() ? 0 : result.getDatapoints().get(0).getAverage();
        } catch (Exception e) {
            System.out.println("Error in Elasticache" + e.getMessage());
            return 0;
        }
    }


    private int calculatePeriod(Date startTime, Date endTime) {
        long diffInSeconds = (endTime.getTime() - startTime.getTime()) / 1000;
        int periods = (int) Math.ceil(diffInSeconds / 1800);

        return (periods > 0) ? 1800 : 60;
    }
}

I am using System.out.println("SwapUsage for " + nodeName + " is " + String.valueOf(SwapUsage)); for troubleshooting. I am not sure where to look next. Any ideas/suggestions?

EDIT: So I tested this some more and I added this line System.out.println("Result for " + dimensionValue + " is " + result.toString()); inside getMetricValue. The result I am getting is Result for scrsquy-001 is {Label: EngineCPUUtilization,Datapoints: []}. Why is it empty and how can I get this to work?

2

Answers


  1. Chosen as BEST ANSWER

    Ok, so I found out what was wrong. I had a look at AWS metrics in Cloudwatch metrics(not from Elasticache Metrics tab) and it turned out that each node in Elasticache is treated as CacheClusterId, where I thought each node was CacheNodeId. So I had a cluster with 3 nodes and each node has its own CacheClusterId, and under that you have CacheNodeId like 001. In the code above I only had to change CacheNodeId to CacheClusterId and it worked like a charm.


  2. Did you check your IAM?
    Make sure that your AWS IAM user or role, which is used to create the Amazon CloudWatch client, has the necessary permissions to read the Elasticache metrics from CloudWatch. Verify the IAM policies attached to the user or role to ensure it has permission for cloudwatch:GetMetricStatistics.

    From a quick review of your code, I can’t see any obvious errors, but I do notice a potential issue with the "MetricName" in the getSumMetricValue and getAverageMetricValue methods.

    You are specifying metric names like "SwapUsage" and "CurrConnections" in your code, but Elasticache metrics are usually reported with metric names like "SwapUsage:PerNode" and "CurrConnections:PerNode." These are examples, and the actual metric names might have additional suffixes to differentiate between different nodes.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search