Enable/disable AWS SDK metrics via dynamic configuration

This commit is contained in:
Jon Chambers 2024-12-18 10:49:50 -05:00 committed by ravi-signal
parent 85a1550485
commit 4839a5ba70
5 changed files with 37 additions and 11 deletions

View File

@ -66,7 +66,7 @@ public class DynamicConfiguration {
@JsonProperty @JsonProperty
@Valid @Valid
DynamicMetricsConfiguration metricsConfiguration = new DynamicMetricsConfiguration(false); DynamicMetricsConfiguration metricsConfiguration = new DynamicMetricsConfiguration(false, false);
@JsonProperty @JsonProperty
@Valid @Valid

View File

@ -6,8 +6,10 @@
package org.whispersystems.textsecuregcm.configuration.dynamic; package org.whispersystems.textsecuregcm.configuration.dynamic;
/** /**
* @param enableLettuceRemoteTag - whether the `remote` tag should be added. Note: although this is dynamic, meters are * @param enableLettuceRemoteTag whether the `remote` tag should be added. Note: although this is dynamic, meters are
* cached after creation, so changes will only affect servers launched after the change. * cached after creation, so changes will only affect servers launched after the change.
* @param enableAwsSdkMetrics whether to record AWS SDK metrics. Note: although this is dynamic, meters are cached after
* creation, so changes will only affect servers launched after the change.
*/ */
public record DynamicMetricsConfiguration(boolean enableLettuceRemoteTag) { public record DynamicMetricsConfiguration(boolean enableLettuceRemoteTag, boolean enableAwsSdkMetrics) {
} }

View File

@ -85,6 +85,8 @@ public class MetricsUtil {
.percentiles(.75, .95, .99, .999) .percentiles(.75, .95, .99, .999)
.build(); .build();
final String awsSdkMetricNamePrefix = MetricsUtil.name(MicrometerAwsSdkMetricPublisher.class);
return config return config
.meterFilter(new MeterFilter() { .meterFilter(new MeterFilter() {
@Override @Override
@ -108,7 +110,9 @@ public class MetricsUtil {
return MeterFilter.super.map(id); return MeterFilter.super.map(id);
} }
}) })
.meterFilter(MeterFilter.denyNameStartsWith(MessageMetrics.DELIVERY_LATENCY_TIMER_NAME + ".percentile")); .meterFilter(MeterFilter.denyNameStartsWith(MessageMetrics.DELIVERY_LATENCY_TIMER_NAME + ".percentile"))
.meterFilter(MeterFilter.deny(id -> !dynamicConfigurationManager.getConfiguration().getMetricsConfiguration().enableAwsSdkMetrics()
&& id.getName().startsWith(awsSdkMetricNamePrefix)));
} }
public static void registerSystemResourceMetrics(final Environment environment) { public static void registerSystemResourceMetrics(final Environment environment) {

View File

@ -8,6 +8,7 @@ import java.time.Duration;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import software.amazon.awssdk.metrics.MetricCollection; import software.amazon.awssdk.metrics.MetricCollection;
@ -102,13 +103,13 @@ public class MicrometerAwsSdkMetricPublisher implements MetricPublisher {
@Override @Override
public void publish(final MetricCollection metricCollection) { public void publish(final MetricCollection metricCollection) {
/* if (METRIC_COLLECTION_TYPE_API_CALL.equals(metricCollection.name())) { if (METRIC_COLLECTION_TYPE_API_CALL.equals(metricCollection.name())) {
try { try {
recordMetricsExecutorService.submit(() -> recordApiCallMetrics(metricCollection)); recordMetricsExecutorService.submit(() -> recordApiCallMetrics(metricCollection));
} catch (final RejectedExecutionException ignored) { } catch (final RejectedExecutionException ignored) {
// This can happen if clients make new calls to an upstream service while the server is shutting down // This can happen if clients make new calls to an upstream service while the server is shutting down
} }
} */ }
} }
private void recordApiCallMetrics(final MetricCollection apiCallMetricCollection) { private void recordApiCallMetrics(final MetricCollection apiCallMetricCollection) {

View File

@ -36,21 +36,21 @@ class MetricsUtilTest {
@ParameterizedTest @ParameterizedTest
@ValueSource(booleans = {true, false}) @ValueSource(booleans = {true, false})
void lettuceTagRejection(final boolean enableLettuceRemoteTag) { void lettuceTagRejection(final boolean enableLettuceRemoteTag) {
DynamicConfiguration dynamicConfiguration = mock(DynamicConfiguration.class); final DynamicConfiguration dynamicConfiguration = mock(DynamicConfiguration.class);
DynamicMetricsConfiguration metricsConfiguration = new DynamicMetricsConfiguration(enableLettuceRemoteTag); final DynamicMetricsConfiguration metricsConfiguration = new DynamicMetricsConfiguration(enableLettuceRemoteTag, false);
when(dynamicConfiguration.getMetricsConfiguration()).thenReturn(metricsConfiguration); when(dynamicConfiguration.getMetricsConfiguration()).thenReturn(metricsConfiguration);
DynamicConfigurationManager<DynamicConfiguration> dynamicConfigurationManager = @SuppressWarnings("unchecked") final DynamicConfigurationManager<DynamicConfiguration> dynamicConfigurationManager =
mock(DynamicConfigurationManager.class); mock(DynamicConfigurationManager.class);
when(dynamicConfigurationManager.getConfiguration()).thenReturn(dynamicConfiguration); when(dynamicConfigurationManager.getConfiguration()).thenReturn(dynamicConfiguration);
MeterRegistry registry = new SimpleMeterRegistry(); final MeterRegistry registry = new SimpleMeterRegistry();
MetricsUtil.configureMeterFilters(registry.config(), dynamicConfigurationManager); MetricsUtil.configureMeterFilters(registry.config(), dynamicConfigurationManager);
registry.counter("lettuce.command.completion.max", "command", "hello", "remote", "world", "allowed", "!").increment(); registry.counter("lettuce.command.completion.max", "command", "hello", "remote", "world", "allowed", "!").increment();
final List<Meter> meters = registry.getMeters(); final List<Meter> meters = registry.getMeters();
assertThat(meters).hasSize(1); assertThat(meters).hasSize(1);
Meter meter = meters.get(0); final Meter meter = meters.getFirst();
assertThat(meter.getId().getName()).isEqualTo("chat.lettuce.command.completion.max"); assertThat(meter.getId().getName()).isEqualTo("chat.lettuce.command.completion.max");
assertThat(meter.getId().getTag("command")).isNull(); assertThat(meter.getId().getTag("command")).isNull();
AbstractStringAssert<?> remoteTag = assertThat(meter.getId().getTag("remote")); AbstractStringAssert<?> remoteTag = assertThat(meter.getId().getTag("remote"));
@ -62,4 +62,23 @@ class MetricsUtilTest {
} }
assertThat(meter.getId().getTag("allowed")).isNotNull(); assertThat(meter.getId().getTag("allowed")).isNotNull();
} }
@ParameterizedTest
@ValueSource(booleans = {true, false})
void awsSdkMetricRejection(final boolean enableAwsSdkMetrics) {
@SuppressWarnings("unchecked") final DynamicConfigurationManager<DynamicConfiguration> dynamicConfigurationManager =
mock(DynamicConfigurationManager.class);
final DynamicConfiguration dynamicConfiguration = mock(DynamicConfiguration.class);
final DynamicMetricsConfiguration metricsConfiguration = new DynamicMetricsConfiguration(false, enableAwsSdkMetrics);
when(dynamicConfigurationManager.getConfiguration()).thenReturn(dynamicConfiguration);
when(dynamicConfiguration.getMetricsConfiguration()).thenReturn(metricsConfiguration);
final MeterRegistry registry = new SimpleMeterRegistry();
MetricsUtil.configureMeterFilters(registry.config(), dynamicConfigurationManager);
registry.counter("chat.MicrometerAwsSdkMetricPublisher.days_since_last_incident").increment();
assertThat(registry.getMeters()).hasSize(enableAwsSdkMetrics ? 1 : 0);
}
} }