Skip to content

Commit 437a15f

Browse files
Register database custom metrics using a multi gauge (#86)
1 parent 862e96a commit 437a15f

File tree

4 files changed

+103
-25
lines changed

4 files changed

+103
-25
lines changed

docstore-metrics/src/main/java/org/hypertrace/core/serviceframework/docstore/metrics/DocStoreMetricsRegistry.java

Lines changed: 38 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
import static java.util.Collections.emptyList;
44
import static java.util.concurrent.TimeUnit.MINUTES;
55
import static java.util.concurrent.TimeUnit.SECONDS;
6+
import static java.util.stream.Collectors.toUnmodifiableList;
7+
import static org.hypertrace.core.serviceframework.metrics.PlatformMetricsRegistry.registerResizeableGauge;
68

79
import io.micrometer.common.lang.Nullable;
810
import java.time.Duration;
@@ -11,13 +13,16 @@
1113
import java.util.concurrent.ScheduledExecutorService;
1214
import java.util.concurrent.atomic.AtomicLong;
1315
import lombok.NonNull;
16+
import lombok.extern.slf4j.Slf4j;
1417
import org.hypertrace.core.documentstore.Datastore;
1518
import org.hypertrace.core.documentstore.metric.DocStoreMetric;
1619
import org.hypertrace.core.documentstore.metric.DocStoreMetricProvider;
17-
import org.hypertrace.core.documentstore.model.config.CustomMetricConfig;
20+
import org.hypertrace.core.serviceframework.metrics.Measurement;
1821
import org.hypertrace.core.serviceframework.metrics.PlatformMetricsRegistry;
22+
import org.hypertrace.core.serviceframework.metrics.ResizeableGauge;
1923
import org.hypertrace.core.serviceframework.spi.PlatformServiceLifecycle;
2024

25+
@Slf4j
2126
@SuppressWarnings("unused")
2227
public class DocStoreMetricsRegistry {
2328
private static final long INITIAL_DELAY_SECONDS = MINUTES.toSeconds(5);
@@ -93,11 +98,6 @@ public void monitor() {
9398
monitorCustomMetrics();
9499
}
95100

96-
/** Instantly query the datastore and report the custom metric once */
97-
public void report(final CustomMetricConfig customMetricConfig) {
98-
metricProvider.getCustomMetrics(customMetricConfig).forEach(this::report);
99-
}
100-
101101
/** Stop monitoring the database */
102102
public void shutdown() {
103103
if (executor != null) {
@@ -112,17 +112,40 @@ private void addShutdownHook() {
112112
}
113113

114114
private void monitorCustomMetrics() {
115-
customMetricConfigs.forEach(
116-
reportingConfig ->
117-
executor.scheduleAtFixedRate(
118-
() -> report(reportingConfig.config()),
119-
INITIAL_DELAY_SECONDS,
120-
reportingConfig.reportingInterval().toSeconds(),
121-
SECONDS));
115+
customMetricConfigs.forEach(this::monitorCustomMetric);
122116
}
123117

124-
private void report(final DocStoreMetric metric) {
125-
PlatformMetricsRegistry.registerGauge(metric.name(), metric.labels(), metric.value());
118+
private void monitorCustomMetric(final DocStoreCustomMetricReportingConfig reportingConfig) {
119+
final ResizeableGauge resizeableGauge =
120+
registerResizeableGauge(reportingConfig.config().metricName());
121+
executor.scheduleAtFixedRate(
122+
() -> report(reportingConfig, resizeableGauge),
123+
INITIAL_DELAY_SECONDS,
124+
reportingConfig.reportingInterval().toSeconds(),
125+
SECONDS);
126+
}
127+
128+
private void report(
129+
final DocStoreCustomMetricReportingConfig reportingConfig,
130+
final ResizeableGauge resizeableGauge) {
131+
try {
132+
final List<DocStoreMetric> customMetrics =
133+
metricProvider.getCustomMetrics(reportingConfig.config());
134+
135+
log.debug(
136+
"Reporting custom database metrics {} for configuration {}",
137+
customMetrics,
138+
reportingConfig);
139+
140+
final List<Measurement> measurements =
141+
customMetrics.stream()
142+
.map(metric -> new Measurement(metric.value(), metric.labels()))
143+
.collect(toUnmodifiableList());
144+
145+
resizeableGauge.report(measurements);
146+
} catch (final Exception e) {
147+
log.warn("Unable to report custom database metric for config: {}", reportingConfig, e);
148+
}
126149
}
127150

128151
private class StandardDocStoreMetricsRegistry {
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package org.hypertrace.core.serviceframework.metrics;
2+
3+
import java.util.Map;
4+
5+
public class Measurement {
6+
private final double value;
7+
private final Map<String, String> labels;
8+
9+
public Measurement(final double value, final Map<String, String> labels) {
10+
this.value = value;
11+
this.labels = labels;
12+
}
13+
14+
double value() {
15+
return value;
16+
}
17+
18+
Map<String, String> labels() {
19+
return labels;
20+
}
21+
}

platform-metrics/src/main/java/org/hypertrace/core/serviceframework/metrics/PlatformMetricsRegistry.java

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import io.micrometer.core.instrument.Gauge;
1717
import io.micrometer.core.instrument.ImmutableTag;
1818
import io.micrometer.core.instrument.MeterRegistry;
19+
import io.micrometer.core.instrument.MultiGauge;
1920
import io.micrometer.core.instrument.Tag;
2021
import io.micrometer.core.instrument.Timer;
2122
import io.micrometer.core.instrument.binder.cache.GuavaCacheMetrics;
@@ -508,16 +509,6 @@ public static void monitorExecutorService(
508509
new ExecutorServiceMetrics(executorService, name, toIterable(tags)).bindTo(meterRegistry);
509510
}
510511

511-
private static Iterable<Tag> toIterable(Map<String, String> tags) {
512-
List<Tag> newTags = new ArrayList<>();
513-
514-
if (tags != null) {
515-
tags.forEach((k, v) -> newTags.add(new ImmutableTag(k, v)));
516-
}
517-
518-
return newTags;
519-
}
520-
521512
public static MetricRegistry getMetricRegistry() {
522513
return METRIC_REGISTRY;
523514
}
@@ -542,6 +533,20 @@ public static synchronized void stop() {
542533
isInit = false;
543534
}
544535

536+
public static ResizeableGauge registerResizeableGauge(final String name) {
537+
return new ResizeableGauge(MultiGauge.builder(name).register(meterRegistry));
538+
}
539+
540+
static Iterable<Tag> toIterable(Map<String, String> tags) {
541+
List<Tag> newTags = new ArrayList<>();
542+
543+
if (tags != null) {
544+
tags.forEach((k, v) -> newTags.add(new ImmutableTag(k, v)));
545+
}
546+
547+
return newTags;
548+
}
549+
545550
/*
546551
* This is needed because ConsoleMetricReporter.stop() doesn't call report for the last time
547552
* before closing the scheduled thread
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package org.hypertrace.core.serviceframework.metrics;
2+
3+
import static java.util.stream.Collectors.toUnmodifiableList;
4+
import static org.hypertrace.core.serviceframework.metrics.PlatformMetricsRegistry.toIterable;
5+
6+
import io.micrometer.core.instrument.MultiGauge;
7+
import io.micrometer.core.instrument.MultiGauge.Row;
8+
import io.micrometer.core.instrument.Tags;
9+
import java.util.Collection;
10+
import java.util.List;
11+
12+
public class ResizeableGauge {
13+
private final MultiGauge multiGauge;
14+
15+
ResizeableGauge(final MultiGauge multiGauge) {
16+
this.multiGauge = multiGauge;
17+
}
18+
19+
public void report(final Collection<Measurement> measurements) {
20+
final List<Row<?>> rows =
21+
measurements.stream()
22+
.map(
23+
measurement ->
24+
Row.of(Tags.of(toIterable(measurement.labels())), measurement::value))
25+
.collect(toUnmodifiableList());
26+
27+
multiGauge.register(rows);
28+
}
29+
}

0 commit comments

Comments
 (0)