package pro.panopticon.client.awscloudwatch;

import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.services.cloudwatch.AmazonCloudWatch;
import com.amazonaws.services.cloudwatch.AmazonCloudWatchClientBuilder;
import com.amazonaws.services.cloudwatch.model.MetricDatum;
import com.amazonaws.services.cloudwatch.model.PutMetricDataRequest;
import com.amazonaws.services.cloudwatch.model.StandardUnit;
import com.google.common.collect.Lists;

import java.util.Date;
import java.util.List;

import static java.util.stream.Collectors.toList;

public class CloudwatchClient {

    private final AmazonCloudWatch amazonCloudWatch;

    public CloudwatchClient(HasCloudwatchConfig cloudwatchConfig) {
        amazonCloudWatch = AmazonCloudWatchClientBuilder.standard()
                .withCredentials(new AWSStaticCredentialsProvider(cloudwatchConfig))
                .withRegion(cloudwatchConfig.getRegion())
                .build();
    }

    public void sendStatistics(String namespace, List<CloudwatchStatistic> statistics) {
        if (statistics == null || statistics.isEmpty()) {
            return;
        }
        Lists.partition(statistics, 15).parallelStream().forEach(l -> postToCloudwatch(namespace, l));
    }

    private void postToCloudwatch(String namespace, List<CloudwatchStatistic> statistics) {
        List<MetricDatum> metricDatumList = statistics.stream()
                .map(CloudwatchStatistic::toMetricsDatum)
                .collect(toList());

        PutMetricDataRequest request = new PutMetricDataRequest();
        request.setNamespace(namespace);
        request.setMetricData(metricDatumList);

        amazonCloudWatch.putMetricData(request);
    }

    public static class CloudwatchStatistic {
        private String key;
        private Double value;
        private StandardUnit unit;
        private Date date;

        public CloudwatchStatistic(String key, Double value, StandardUnit unit, java.util.Date date) {
            this.key = key;
            this.value = value;
            this.unit = unit;
            this.date = date;
        }

        public CloudwatchStatistic(String key, Double value, StandardUnit unit) {
            this(key, value, unit, new Date());
        }

        public CloudwatchStatistic(String key, Double value) {
            this(key, value, StandardUnit.Count, new Date());
        }

        public MetricDatum toMetricsDatum() {
            MetricDatum metricDatum = new MetricDatum();
            metricDatum.setMetricName(key);
            metricDatum.setTimestamp(date);
            metricDatum.setUnit(unit);
            metricDatum.setValue(value);
            return metricDatum;
        }
    }
}

@@ -455,16 +455,73 @@
 t.Lists;
+%0Aimport org.slf4j.Logger;%0Aimport org.slf4j.LoggerFactory;
 %0A%0Aimport
@@ -645,16 +645,90 @@
 ient %7B%0A%0A
+    private final Logger LOG = LoggerFactory.getLogger(this.getClass());%0A%0A
     priv
@@ -1266,107 +1266,439 @@
   %7D%0A
-        Lists.partition(statistics, 15).parallelStream().forEach(l -%3E postToCloudwatch(namespace, l
+%0A        long before = System.currentTimeMillis();%0A%0A        List%3CList%3CCloudwatchStatistic%3E%3E partitions = Lists.partition(statistics, 15);%0A%0A        partitions.parallelStream()%0A                .forEach(l -%3E postToCloudwatch(namespace, l));%0A%0A        long duration = System.currentTimeMillis() - before;%0A%0A        LOG.info(String.format(%22Sent %25d partitions to CloudWatch for namespace %25s in %25dms%22, partitions.size(), namespace, duration
 ));%0A

Add better logging