diff --git a/implementations/micrometer-registry-cloudwatch/build.gradle b/implementations/micrometer-registry-cloudwatch/build.gradle new file mode 100644 index 0000000000..10c2ed64fd --- /dev/null +++ b/implementations/micrometer-registry-cloudwatch/build.gradle @@ -0,0 +1,10 @@ +apply plugin: 'org.junit.platform.gradle.plugin' +apply plugin: 'nebula.optional-base' + +dependencies { + compile project(':micrometer-core') + compile 'org.slf4j:slf4j-api:latest.release' + compile 'com.amazonaws:aws-java-sdk-cloudwatch:latest.release' + + testCompile project(':micrometer-test') +} \ No newline at end of file diff --git a/implementations/micrometer-registry-cloudwatch/src/main/java/io/micrometer/cloudwatch/CloudWatchConfig.java b/implementations/micrometer-registry-cloudwatch/src/main/java/io/micrometer/cloudwatch/CloudWatchConfig.java new file mode 100644 index 0000000000..2293ed08ce --- /dev/null +++ b/implementations/micrometer-registry-cloudwatch/src/main/java/io/micrometer/cloudwatch/CloudWatchConfig.java @@ -0,0 +1,56 @@ +/** + * Copyright 2017 Pivotal Software, Inc. + *
+ * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *
+ * http://www.apache.org/licenses/LICENSE-2.0 + *
+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.micrometer.cloudwatch; + +import io.micrometer.core.instrument.step.StepRegistryConfig; + +/** + * Configuration for CloudWatch exporting. + * + * @author Dawid Kublik + */ +public interface CloudWatchConfig extends StepRegistryConfig { + + int MAX_BATCH_SIZE = 20; + + /** + * Accept configuration defaults + */ + CloudWatchConfig DEFAULT = k -> null; + + @Override + default String prefix() { + return "cloudwatch"; + } + + default String namespace() { + String v = get(prefix() + ".namespace"); + if(v == null) + throw new IllegalStateException(prefix() + ".namespace must be set to report metrics to CloudWatch"); + return v; + } + + @Override + default int batchSize() { + String v = get(prefix() + ".batchSize"); + int vInt = v == null ? MAX_BATCH_SIZE : Integer.parseInt(v); + if(vInt > MAX_BATCH_SIZE) + throw new IllegalStateException(prefix() + ".batchSize must be <= " + MAX_BATCH_SIZE); + + return vInt; + } + +} diff --git a/implementations/micrometer-registry-cloudwatch/src/main/java/io/micrometer/cloudwatch/CloudWatchMeterRegistry.java b/implementations/micrometer-registry-cloudwatch/src/main/java/io/micrometer/cloudwatch/CloudWatchMeterRegistry.java new file mode 100644 index 0000000000..a16b8b59ca --- /dev/null +++ b/implementations/micrometer-registry-cloudwatch/src/main/java/io/micrometer/cloudwatch/CloudWatchMeterRegistry.java @@ -0,0 +1,213 @@ +/** + * Copyright 2017 Pivotal Software, Inc. + *
+ * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *
+ * http://www.apache.org/licenses/LICENSE-2.0 + *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.micrometer.cloudwatch;
+
+import com.amazonaws.handlers.AsyncHandler;
+import com.amazonaws.services.cloudwatch.AmazonCloudWatchAsync;
+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.PutMetricDataResult;
+import com.amazonaws.services.cloudwatch.model.StandardUnit;
+import io.micrometer.core.instrument.Clock;
+import io.micrometer.core.instrument.DistributionSummary;
+import io.micrometer.core.instrument.FunctionTimer;
+import io.micrometer.core.instrument.HistogramSnapshot;
+import io.micrometer.core.instrument.Meter;
+import io.micrometer.core.instrument.Tag;
+import io.micrometer.core.instrument.Timer;
+import io.micrometer.core.instrument.ValueAtPercentile;
+import io.micrometer.core.instrument.config.NamingConvention;
+import io.micrometer.core.instrument.histogram.HistogramConfig;
+import io.micrometer.core.instrument.step.StepMeterRegistry;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.text.DecimalFormat;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Stream;
+
+import static java.util.stream.Collectors.toList;
+import static java.util.stream.StreamSupport.stream;
+
+/**
+ * @author Dawid Kublik
+ */
+public class CloudWatchMeterRegistry extends StepMeterRegistry {
+ private final CloudWatchConfig config;
+ private final AmazonCloudWatchAsync amazonCloudWatchAsync;
+ private final DecimalFormat percentileFormat = new DecimalFormat("#.####");
+ private final Logger logger = LoggerFactory.getLogger(CloudWatchMeterRegistry.class);
+ private final Map
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.micrometer.cloudwatch;
+
+import com.amazonaws.services.cloudwatch.model.MetricDatum;
+
+import java.math.RoundingMode;
+import java.util.AbstractList;
+import java.util.List;
+
+/**
+ * Modified from {@link io.micrometer.core.instrument.util.MeterPartition}
+ */
+public class MetricDatumPartition extends AbstractList
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.micrometer.cloudwatch;
+
+import io.micrometer.core.instrument.MockClock;
+import io.micrometer.core.instrument.MeterRegistry;
+import io.micrometer.core.tck.MeterRegistryCompatibilityKit;
+
+import java.time.Duration;
+
+class CloudWatchMeterRegistryCompatibilityTest extends MeterRegistryCompatibilityKit {
+ @Override
+ public MeterRegistry registry() {
+ return new CloudWatchMeterRegistry(new CloudWatchConfig() {
+ @Override
+ public String get(String k) {
+ return null;
+ }
+
+ @Override
+ public boolean enabled() {
+ return false;
+ }
+
+ @Override
+ public String namespace() {
+ return "DOESNOTMATTER";
+ }
+
+ @Override
+ public Duration step() {
+ return Duration.ofMillis(800);
+ }
+
+ }, new MockClock(), null);
+ }
+}
diff --git a/settings.gradle b/settings.gradle
index 1db9ca98c8..e555bed99b 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -5,7 +5,7 @@ include 'micrometer-spring-legacy'
include 'micrometer-samples'
include 'micrometer-test'
-['atlas', 'prometheus', 'datadog', 'ganglia', 'graphite', 'jmx', 'influx', 'statsd'].each { sys ->
+['atlas', 'prometheus', 'datadog', 'ganglia', 'graphite', 'jmx', 'influx', 'statsd', 'cloudwatch'].each { sys ->
include "micrometer-registry-$sys"
project(":micrometer-registry-$sys").projectDir = new File(rootProject.projectDir, "implementations/micrometer-registry-$sys")
}
> {
+ private final List
> partition(List