diff --git a/tritium-registry/build.gradle b/tritium-registry/build.gradle index bf5ddd34e..469a4a070 100644 --- a/tritium-registry/build.gradle +++ b/tritium-registry/build.gradle @@ -4,6 +4,7 @@ dependencies { processor 'com.google.auto.service:auto-service' processor 'org.immutables:value' + compile 'com.google.guava:guava' compile 'com.palantir.safe-logging:safe-logging' compile 'io.dropwizard.metrics:metrics-core' diff --git a/tritium-registry/src/main/java/com/palantir/tritium/metrics/registry/DefaultTaggedMetricRegistry.java b/tritium-registry/src/main/java/com/palantir/tritium/metrics/registry/DefaultTaggedMetricRegistry.java index 1c535e88b..95999c29c 100644 --- a/tritium-registry/src/main/java/com/palantir/tritium/metrics/registry/DefaultTaggedMetricRegistry.java +++ b/tritium-registry/src/main/java/com/palantir/tritium/metrics/registry/DefaultTaggedMetricRegistry.java @@ -24,7 +24,8 @@ import com.codahale.metrics.Metric; import com.codahale.metrics.Timer; import com.google.auto.service.AutoService; -import java.util.Collections; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Maps; import java.util.Map; import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; @@ -36,6 +37,7 @@ public final class DefaultTaggedMetricRegistry implements TaggedMetricRegistry { private static final TaggedMetricRegistry DEFAULT = new DefaultTaggedMetricRegistry(); private final Map registry = new ConcurrentHashMap<>(); + private final Map, TaggedMetricSet> taggedRegistries = new ConcurrentHashMap<>(); public DefaultTaggedMetricRegistry() {} @@ -93,7 +95,17 @@ public Timer timer(MetricName metricName, Supplier timerSupplier) { @Override public Map getMetrics() { - return Collections.unmodifiableMap(registry); + ImmutableMap.Builder result = ImmutableMap.builder() + .putAll(registry); + taggedRegistries.forEach((tag, metrics) -> metrics.getMetrics() + .forEach((metricName, metric) -> result.put( + MetricName.builder() + .from(metricName) + .putSafeTags(tag.getKey(), tag.getValue()) + .build(), + metric))); + + return result.build(); } @Override @@ -101,6 +113,16 @@ public Optional remove(MetricName metricName) { return Optional.ofNullable(registry.remove(metricName)); } + @Override + public void addMetrics(String safeTagName, String safeTagValue, TaggedMetricSet other) { + taggedRegistries.put(Maps.immutableEntry(safeTagName, safeTagValue), other); + } + + @Override + public Optional removeMetrics(String safeTagName, String safeTagValue) { + return Optional.ofNullable(taggedRegistries.remove(Maps.immutableEntry(safeTagName, safeTagValue))); + } + private T getOrAdd(MetricName metricName, Class metricClass, Supplier metricSupplier) { Metric metric = registry.computeIfAbsent(metricName, name -> metricSupplier.get()); if (!metricClass.isInstance(metric)) { diff --git a/tritium-registry/src/main/java/com/palantir/tritium/metrics/registry/DropwizardTaggedMetricSet.java b/tritium-registry/src/main/java/com/palantir/tritium/metrics/registry/DropwizardTaggedMetricSet.java new file mode 100644 index 000000000..adb04939e --- /dev/null +++ b/tritium-registry/src/main/java/com/palantir/tritium/metrics/registry/DropwizardTaggedMetricSet.java @@ -0,0 +1,37 @@ +/* + * (c) Copyright 2018 Palantir Technologies Inc. All rights reserved. + * + * 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 com.palantir.tritium.metrics.registry; + +import static java.util.stream.Collectors.toMap; + +import com.codahale.metrics.Metric; +import com.codahale.metrics.MetricSet; +import java.util.Map; + +public final class DropwizardTaggedMetricSet implements TaggedMetricSet { + private final MetricSet metricSet; + + public DropwizardTaggedMetricSet(MetricSet metricSet) { + this.metricSet = metricSet; + } + + @Override + public Map getMetrics() { + return metricSet.getMetrics().entrySet().stream() + .collect(toMap(entry -> MetricName.builder().safeName(entry.getKey()).build(), Map.Entry::getValue)); + } +} diff --git a/tritium-registry/src/main/java/com/palantir/tritium/metrics/registry/TaggedMetricRegistry.java b/tritium-registry/src/main/java/com/palantir/tritium/metrics/registry/TaggedMetricRegistry.java index 044e9a0f0..241e3405d 100644 --- a/tritium-registry/src/main/java/com/palantir/tritium/metrics/registry/TaggedMetricRegistry.java +++ b/tritium-registry/src/main/java/com/palantir/tritium/metrics/registry/TaggedMetricRegistry.java @@ -22,14 +22,13 @@ import com.codahale.metrics.Meter; import com.codahale.metrics.Metric; import com.codahale.metrics.Timer; -import java.util.Map; import java.util.Optional; import java.util.function.Supplier; /** * Similar to {@link com.codahale.metrics.MetricRegistry} but allows tagging of {@link Metric}s. */ -public interface TaggedMetricRegistry { +public interface TaggedMetricRegistry extends TaggedMetricSet { /** * Returns existing or new timer metric for the specified metric name. @@ -81,13 +80,6 @@ public interface TaggedMetricRegistry { Counter counter(MetricName metricName, Supplier counterSupplier); - /** - * Returns a map of registered metrics. - * - * @return map of registered metrics - */ - Map getMetrics(); - /** * Removes the tagged metric with the specified metric name. * @@ -96,4 +88,24 @@ public interface TaggedMetricRegistry { */ Optional remove(MetricName metricName); + /** + * Adds a set of metrics to this TaggedMetricRegistry's metric set, + * which are to be uniquely identified by the tags provided. + *

+ * So, if I have a metric registry with a single metric called 'foo', and I add it + * with tag (bar, baz), this registry will now contain 'foo', tagged with (bar, baz). + *

+ * If a metric exists with duplicate tags, then calling {@link TaggedMetricSet#getMetrics} + * will be impossible. + * + * @param safeTagName a tag key which should be added to all metrics in the metrics set + * @param safeTagValue a tag value which should be added to all metrics in the metrics set + * @param metrics the metrics which should be added + */ + void addMetrics(String safeTagName, String safeTagValue, TaggedMetricSet metrics); + + /** + * Removes a TaggedMetricsSet added via addMetrics from this metrics set. + */ + Optional removeMetrics(String safeTagName, String safeTagValue); } diff --git a/tritium-registry/src/main/java/com/palantir/tritium/metrics/registry/TaggedMetricSet.java b/tritium-registry/src/main/java/com/palantir/tritium/metrics/registry/TaggedMetricSet.java new file mode 100644 index 000000000..7af6a115a --- /dev/null +++ b/tritium-registry/src/main/java/com/palantir/tritium/metrics/registry/TaggedMetricSet.java @@ -0,0 +1,29 @@ +/* + * (c) Copyright 2018 Palantir Technologies Inc. All rights reserved. + * + * 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 com.palantir.tritium.metrics.registry; + +import com.codahale.metrics.Metric; +import java.util.Map; + +public interface TaggedMetricSet { + /** + * Returns a map of metrics. + * + * @return map of metrics + */ + Map getMetrics(); +} diff --git a/tritium-registry/src/test/java/com/palantir/tritium/metrics/registry/TaggedMetricRegistryTest.java b/tritium-registry/src/test/java/com/palantir/tritium/metrics/registry/TaggedMetricRegistryTest.java index 4bfa522aa..5b3aabd82 100644 --- a/tritium-registry/src/test/java/com/palantir/tritium/metrics/registry/TaggedMetricRegistryTest.java +++ b/tritium-registry/src/test/java/com/palantir/tritium/metrics/registry/TaggedMetricRegistryTest.java @@ -153,4 +153,18 @@ public void testRemoveMetric() { assertThat(registry.remove(METRIC_1).isPresent()).isFalse(); } + + @Test + public void testAddMetricRegistry() { + String name = "name"; + String tagKey = "tagKey"; + String tagValue = "tagValue"; + TaggedMetricRegistry child = new DefaultTaggedMetricRegistry(); + Meter meter = child.meter(MetricName.builder().safeName(name).build()); + registry.addMetrics(tagKey, tagValue, child); + assertThat(registry.getMetrics()) + .containsEntry(MetricName.builder().safeName(name).putSafeTags(tagKey, tagValue).build(), meter); + registry.removeMetrics(tagKey, tagValue); + assertThat(registry.getMetrics()).isEmpty(); + } }