com.palantir.atlasdb.util.TopNMetricPublicationController Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of atlasdb-client Show documentation
Show all versions of atlasdb-client Show documentation
Palantir open source project
/*
* (c) Copyright 2020 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.atlasdb.util;
import com.codahale.metrics.Gauge;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Suppliers;
import com.palantir.atlasdb.metrics.MetricPublicationFilter;
import com.palantir.common.streams.KeyedStream;
import com.palantir.logsafe.Preconditions;
import com.palantir.logsafe.SafeArg;
import java.time.Duration;
import java.util.Comparator;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;
import java.util.stream.Collectors;
/**
* Given a provided number of metrics, ensures that only the top {@code maxPermittedRank} are published in the steady
* state. If there are ties (e.g. the 9th, 10th, 11th and 12th highest value are equal in a controller configured to
* permit the top 10 metrics), which of the tying metrics are selected is undefined, though it is guaranteed that
* the correct number will be selected so that the total number of metrics published equals the max permitted rank.
*/
public final class TopNMetricPublicationController {
private static final Duration REFRESH_INTERVAL = Duration.ofSeconds(30);
private final Set> gauges;
private final Comparator comparator;
private final int maxPermittedRank;
private final Supplier>> publishableGauges;
@VisibleForTesting
TopNMetricPublicationController(Comparator comparator, int maxPermittedRank, Duration refreshInterval) {
this.comparator = comparator;
this.maxPermittedRank = maxPermittedRank;
this.gauges = ConcurrentHashMap.newKeySet();
this.publishableGauges = Suppliers.memoizeWithExpiration(
this::getEligibleGauges, refreshInterval.toNanos(), TimeUnit.NANOSECONDS);
}
@SuppressWarnings("unchecked") // Guaranteed correct
public static TopNMetricPublicationController create(int maxPermittedRank) {
Preconditions.checkState(
maxPermittedRank > 0,
"maxPermittedRank must be positive",
SafeArg.of("maxPermittedRank", maxPermittedRank));
return new TopNMetricPublicationController(Comparator.naturalOrder(), maxPermittedRank, REFRESH_INTERVAL);
}
public MetricPublicationFilter registerAndCreateFilter(Gauge gauge) {
gauges.add(gauge);
return () -> shouldPublishIndividualGaugeMetric(gauge);
}
private boolean shouldPublishIndividualGaugeMetric(Gauge constituentGauge) {
return publishableGauges.get().contains(constituentGauge);
}
private Set> getEligibleGauges() {
return KeyedStream.of(gauges.stream())
.map(Gauge::getValue)
.filter(Objects::nonNull)
.entries()
.sorted(Comparator.comparing(Map.Entry::getValue, comparator.reversed()))
.limit(maxPermittedRank)
.map(Map.Entry::getKey)
.collect(Collectors.toSet());
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy