// Copyright 2016 The Domain Registry Authors. 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 google.registry.monitoring.metrics; import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Ordering; import com.google.common.util.concurrent.Striped; import google.registry.monitoring.metrics.MetricSchema.Kind; import java.util.Map.Entry; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.locks.Lock; import org.joda.time.Instant; /** * A metric which stores {@link Distribution} values. The values are stateful and meant to be * updated incrementally via the {@link EventMetric#record(double, String...)} method. * *
This metric class is generally suitable for recording aggregations of data about a * quantitative aspect of an event. For example, this metric would be suitable for recording the * latency distribution for a request over the network. * *
The {@link MutableDistribution} values tracked by this metric can be reset with {@link
* EventMetric#reset()}.
*/
public final class EventMetric extends AbstractMetric If the metric is undefined for given label values, this method will autovivify the {@link
* Distribution}.
*
* The count of {@code labelValues} must be equal to the underlying metric's count of labels.
*/
public final void record(double sample, String... labelValues) {
MetricsUtils.checkLabelValuesLength(this, labelValues);
recordMultiple(sample, 1, Instant.now(), ImmutableList.copyOf(labelValues));
}
/**
* Adds {@code count} of the given {@code sample} to the {@link Distribution} for the given {@code
* labelValues}.
*
* If the metric is undefined for given label values, this method will autovivify the {@link
* Distribution}.
*
* The count of {@code labelValues} must be equal to the underlying metric's count of labels.
*/
public final void record(double sample, int count, String... labelValues) {
MetricsUtils.checkLabelValuesLength(this, labelValues);
recordMultiple(sample, count, Instant.now(), ImmutableList.copyOf(labelValues));
}
@VisibleForTesting
final void recordMultiple(
double sample, int count, Instant startTimestamp, ImmutableList This is useful if the metric is tracking values that are reset as part of a retrying
* transaction, for example.
*/
public void reset() {
reset(Instant.now());
}
@VisibleForTesting
final void reset(Instant startTime) {
// Lock the entire set of values so that all existing values will have a consistent timestamp
// after this call, without the possibility of interleaving with another reset() call.
for (int i = 0; i < valueLocks.size(); i++) {
valueLocks.getAt(i).lock();
}
try {
for (ImmutableList This is useful if the metric is tracking a value that is reset as part of a retrying
* transaction, for example.
*/
public void reset(String... labelValues) {
MetricsUtils.checkLabelValuesLength(this, labelValues);
reset(Instant.now(), ImmutableList.copyOf(labelValues));
}
@VisibleForTesting
final void reset(Instant startTimestamp, ImmutableList