diff --git a/pom.xml b/pom.xml index 75ffd7c..b8d6732 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ org.springframework.boot spring-boot-starter-parent - 2.7.0 + 2.7.18 com.orange.lo.sample diff --git a/src/main/java/com/orange/lo/sample/mqtt2eventhub/ConnectorApplication.java b/src/main/java/com/orange/lo/sample/mqtt2eventhub/ConnectorApplication.java index d8ce6a8..1865fef 100644 --- a/src/main/java/com/orange/lo/sample/mqtt2eventhub/ConnectorApplication.java +++ b/src/main/java/com/orange/lo/sample/mqtt2eventhub/ConnectorApplication.java @@ -7,65 +7,13 @@ package com.orange.lo.sample.mqtt2eventhub; -import com.orange.lo.sample.mqtt2eventhub.utils.MetricsProperties; -import io.micrometer.cloudwatch2.CloudWatchConfig; -import io.micrometer.cloudwatch2.CloudWatchMeterRegistry; -import io.micrometer.core.instrument.Clock; -import io.micrometer.core.instrument.MeterRegistry; -import io.micrometer.core.instrument.config.MeterFilter; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.Bean; -import software.amazon.awssdk.auth.credentials.ProfileCredentialsProvider; -import software.amazon.awssdk.regions.providers.AwsProfileRegionProvider; -import software.amazon.awssdk.services.cloudwatch.CloudWatchAsyncClient; - -import java.lang.invoke.MethodHandles; @SpringBootApplication public class ConnectorApplication { - private static final String AWS_SERVICE_PROFILE_NAME = "service-profile"; - private static final Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); - private final MetricsProperties metricsProperties; - - ConnectorApplication(MetricsProperties metricsProperties) { - this.metricsProperties = metricsProperties; - } - public static void main(String[] args) { SpringApplication.run(ConnectorApplication.class, args); } - - @Bean - public MeterRegistry meterRegistry() { - CloudWatchAsyncClient cloudWatchAsyncClient = CloudWatchAsyncClient.builder() - .credentialsProvider(ProfileCredentialsProvider.create(AWS_SERVICE_PROFILE_NAME)) - .region(new AwsProfileRegionProvider(null, AWS_SERVICE_PROFILE_NAME).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 CloudWatchConfig cloudWatchConfig() { - return new CloudWatchConfig() { - - @Override - public String get(String key) { - return null; - } - - @Override - public String namespace() { - return metricsProperties.getNamespace(); - } - }; - } } \ No newline at end of file diff --git a/src/main/java/com/orange/lo/sample/mqtt2eventhub/utils/MeterRegistryConfig.java b/src/main/java/com/orange/lo/sample/mqtt2eventhub/utils/MeterRegistryConfig.java new file mode 100644 index 0000000..3edf721 --- /dev/null +++ b/src/main/java/com/orange/lo/sample/mqtt2eventhub/utils/MeterRegistryConfig.java @@ -0,0 +1,153 @@ +/** + * 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 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 @@ + +