diff --git a/pom.xml b/pom.xml
index 75ffd7c..b8d6732 100644
--- a/pom.xml
+++ b/pom.xml
@@ -4,7 +4,7 @@
+ * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +package com.orange.lo.sample.mqtt2eventhub.utils; + +import io.micrometer.cloudwatch2.CloudWatchConfig; +import io.micrometer.cloudwatch2.CloudWatchMeterRegistry; +import io.micrometer.core.instrument.Clock; +import io.micrometer.core.instrument.Counter; +import io.micrometer.core.instrument.MeterRegistry; +import io.micrometer.core.instrument.config.MeterFilter; +import io.micrometer.core.instrument.step.StepMeterRegistry; +import io.micrometer.core.instrument.step.StepRegistryConfig; +import org.jetbrains.annotations.NotNull; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider; +import software.amazon.awssdk.auth.credentials.InstanceProfileCredentialsProvider; +import software.amazon.awssdk.auth.credentials.ProfileCredentialsProvider; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.regions.providers.AwsProfileRegionProvider; +import software.amazon.awssdk.regions.providers.InstanceProfileRegionProvider; +import software.amazon.awssdk.services.cloudwatch.CloudWatchAsyncClient; + +import java.lang.invoke.MethodHandles; +import java.time.Duration; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.TimeUnit; + +@Configuration +public class MeterRegistryConfig { + + private static final Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); + private static final String AWS_SERVICE_PROFILE_NAME = "service-profile"; + private final MetricsProperties metricsProperties; + + public MeterRegistryConfig(MetricsProperties metricsProperties) { + this.metricsProperties = metricsProperties; + } + + @Bean + public MeterRegistry meterRegistry() { + MeterRegistry meterRegistry; + if (metricsProperties.isSendToCloudwatch()) { + meterRegistry = getCloudWatchMeterRegistry(); + } else { + meterRegistry = stepMeterRegistry(); + } + return meterRegistry; + } + + @NotNull + private CloudWatchMeterRegistry getCloudWatchMeterRegistry() { + CloudWatchAsyncClient cloudWatchAsyncClient = CloudWatchAsyncClient.builder() + .credentialsProvider(getAwsCredentialsProvider()) + .region(getRegion()) + .build(); + + CloudWatchMeterRegistry cloudWatchMeterRegistry = new CloudWatchMeterRegistry(cloudWatchConfig(), Clock.SYSTEM, cloudWatchAsyncClient); + + cloudWatchMeterRegistry.config() + .meterFilter(MeterFilter.deny(id -> !id.getName().startsWith("message"))) + .commonTags(metricsProperties.getDimensionName(), metricsProperties.getDimensionValue()); + return cloudWatchMeterRegistry; + } + + private AwsCredentialsProvider getAwsCredentialsProvider() { + return metricsProperties.isUseServiceProfile() + ? ProfileCredentialsProvider.create(AWS_SERVICE_PROFILE_NAME) + : InstanceProfileCredentialsProvider.create(); + } + + private Region getRegion() { + return metricsProperties.isUseServiceProfile() + ? new AwsProfileRegionProvider(null, AWS_SERVICE_PROFILE_NAME).getRegion() + : new InstanceProfileRegionProvider().getRegion(); + } + + private CloudWatchConfig cloudWatchConfig() { + return new CloudWatchConfig() { + + @Override + public String get(@NotNull String key) { + return null; + } + + @NotNull + @Override + public String namespace() { + return metricsProperties.getNamespace(); + } + }; + } + + private StepMeterRegistry stepMeterRegistry() { + StepMeterRegistry stepMeterRegistry = new StepMeterRegistry(stepRegistryConfig(), Clock.SYSTEM) { + + @NotNull + @Override + protected TimeUnit getBaseTimeUnit() { + return TimeUnit.MILLISECONDS; + } + + @Override + protected void publish() { + getMeters().stream() + .filter(m -> m.getId().getName().startsWith("message") ) + .map(m -> get(m.getId().getName()).counter()) + .forEach(c -> LOG.info("{} = {}", c.getId().getName(), val(c))); + } + + @Override + public void start(@NotNull ThreadFactory threadFactory) { + super.start(Executors.defaultThreadFactory()); + } + }; + stepMeterRegistry.start(Executors.defaultThreadFactory()); + return stepMeterRegistry; + } + + private StepRegistryConfig stepRegistryConfig() { + return new StepRegistryConfig() { + + @NotNull + @Override + public Duration step() { + return Duration.ofMinutes(1); + } + + @NotNull + @Override + public String prefix() { + return ""; + } + + @Override + public String get(@NotNull String key) { + return null; + } + }; + } + + private long val(Counter cnt) { + return Math.round(cnt.count()); + } +} diff --git a/src/main/java/com/orange/lo/sample/mqtt2eventhub/utils/MetricsProperties.java b/src/main/java/com/orange/lo/sample/mqtt2eventhub/utils/MetricsProperties.java index 99639f3..23f1930 100644 --- a/src/main/java/com/orange/lo/sample/mqtt2eventhub/utils/MetricsProperties.java +++ b/src/main/java/com/orange/lo/sample/mqtt2eventhub/utils/MetricsProperties.java @@ -1,3 +1,10 @@ +/** + * Copyright (c) Orange. All Rights Reserved. + *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
package com.orange.lo.sample.mqtt2eventhub.utils;
import org.springframework.boot.context.properties.ConfigurationProperties;
@@ -9,6 +16,8 @@ public class MetricsProperties {
private String namespace;
private String dimensionName;
private String dimensionValue;
+ private boolean sendToCloudwatch;
+ private boolean useServiceProfile;
public String getNamespace() {
return namespace;
@@ -33,4 +42,20 @@ public String getDimensionValue() {
public void setDimensionValue(String dimensionValue) {
this.dimensionValue = dimensionValue;
}
+
+ public boolean isSendToCloudwatch() {
+ return sendToCloudwatch;
+ }
+
+ public void setSendToCloudwatch(boolean sendToCloudwatch) {
+ this.sendToCloudwatch = sendToCloudwatch;
+ }
+
+ public boolean isUseServiceProfile() {
+ return useServiceProfile;
+ }
+
+ public void setUseServiceProfile(boolean useServiceProfile) {
+ this.useServiceProfile = useServiceProfile;
+ }
}
\ No newline at end of file
diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml
index f4a0788..e79c4fd 100644
--- a/src/main/resources/application.yml
+++ b/src/main/resources/application.yml
@@ -21,6 +21,8 @@ azure:
max-send-attempts: 3
metrics:
+ send-to-cloudwatch: false
+ use-service-profile: false
namespace: CCS
dimension-name: connector-id
dimension-value:
diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml
index d626ff1..dd019c5 100644
--- a/src/main/resources/logback.xml
+++ b/src/main/resources/logback.xml
@@ -29,6 +29,8 @@