diff --git a/java/google/registry/config/RegistryConfig.java b/java/google/registry/config/RegistryConfig.java index 8f664ee11..e1751f952 100644 --- a/java/google/registry/config/RegistryConfig.java +++ b/java/google/registry/config/RegistryConfig.java @@ -846,7 +846,7 @@ public final class RegistryConfig { * Maximum QPS for the Google Cloud Monitoring V3 (aka Stackdriver) API. The QPS limit can be * adjusted by contacting Cloud Support. * - * @see google.registry.monitoring.metrics.stackdriver.StackdriverWriter + * @see com.google.monitoring.metrics.stackdriver.StackdriverWriter */ @Provides @Config("stackdriverMaxQps") @@ -858,7 +858,7 @@ public final class RegistryConfig { * Maximum number of points that can be sent to Stackdriver in a single {@code * TimeSeries.Create} API call. * - * @see google.registry.monitoring.metrics.stackdriver.StackdriverWriter + * @see com.google.monitoring.metrics.stackdriver.StackdriverWriter */ @Provides @Config("stackdriverMaxPointsPerRequest") @@ -867,10 +867,10 @@ public final class RegistryConfig { } /** - * The reporting interval for {@link google.registry.monitoring.metrics.Metric} instances to be - * sent to a {@link google.registry.monitoring.metrics.MetricWriter}. + * The reporting interval for {@link com.google.monitoring.metrics.Metric} instances to be sent + * to a {@link com.google.monitoring.metrics.MetricWriter}. * - * @see google.registry.monitoring.metrics.MetricReporter + * @see com.google.monitoring.metrics.MetricReporter */ @Provides @Config("metricsWriteInterval") diff --git a/java/google/registry/dns/BUILD b/java/google/registry/dns/BUILD index df9ce81c3..b98d9df43 100644 --- a/java/google/registry/dns/BUILD +++ b/java/google/registry/dns/BUILD @@ -23,7 +23,6 @@ java_library( "//java/google/registry/config", "//java/google/registry/dns/writer", "//java/google/registry/model", - "//java/google/registry/monitoring/metrics", "//java/google/registry/request", "//java/google/registry/request/auth", "//java/google/registry/request/lock", @@ -34,6 +33,7 @@ java_library( "@com_google_code_findbugs_jsr305", "@com_google_dagger", "@com_google_guava", + "@com_google_monitoring_client_metrics", "@javax_servlet_api", "@joda_time", ], diff --git a/java/google/registry/dns/DnsMetrics.java b/java/google/registry/dns/DnsMetrics.java index 391053cf4..b4c05756e 100644 --- a/java/google/registry/dns/DnsMetrics.java +++ b/java/google/registry/dns/DnsMetrics.java @@ -17,14 +17,14 @@ package google.registry.dns; import static google.registry.request.RequestParameters.PARAM_TLD; import com.google.common.collect.ImmutableSet; +import com.google.monitoring.metrics.DistributionFitter; +import com.google.monitoring.metrics.EventMetric; +import com.google.monitoring.metrics.ExponentialFitter; +import com.google.monitoring.metrics.FibonacciFitter; +import com.google.monitoring.metrics.IncrementableMetric; +import com.google.monitoring.metrics.LabelDescriptor; +import com.google.monitoring.metrics.MetricRegistryImpl; import google.registry.config.RegistryEnvironment; -import google.registry.monitoring.metrics.DistributionFitter; -import google.registry.monitoring.metrics.EventMetric; -import google.registry.monitoring.metrics.ExponentialFitter; -import google.registry.monitoring.metrics.FibonacciFitter; -import google.registry.monitoring.metrics.IncrementableMetric; -import google.registry.monitoring.metrics.LabelDescriptor; -import google.registry.monitoring.metrics.MetricRegistryImpl; import google.registry.request.Parameter; import javax.inject.Inject; import org.joda.time.Duration; diff --git a/java/google/registry/flows/BUILD b/java/google/registry/flows/BUILD index 5b567ef0a..c188d40f0 100644 --- a/java/google/registry/flows/BUILD +++ b/java/google/registry/flows/BUILD @@ -26,7 +26,6 @@ java_library( "//java/google/registry/config", "//java/google/registry/dns", "//java/google/registry/model", - "//java/google/registry/monitoring/metrics", "//java/google/registry/monitoring/whitebox", "//java/google/registry/pricing", "//java/google/registry/request", @@ -41,6 +40,7 @@ java_library( "@com_google_code_findbugs_jsr305", "@com_google_dagger", "@com_google_guava", + "@com_google_monitoring_client_metrics", "@com_googlecode_json_simple", "@io_bazel_rules_closure//closure/templates", "@javax_servlet_api", diff --git a/java/google/registry/flows/EppMetrics.java b/java/google/registry/flows/EppMetrics.java index f81434d67..5665c6632 100644 --- a/java/google/registry/flows/EppMetrics.java +++ b/java/google/registry/flows/EppMetrics.java @@ -14,13 +14,13 @@ package google.registry.flows; -import static google.registry.monitoring.metrics.EventMetric.DEFAULT_FITTER; +import static com.google.monitoring.metrics.EventMetric.DEFAULT_FITTER; import com.google.common.collect.ImmutableSet; -import google.registry.monitoring.metrics.EventMetric; -import google.registry.monitoring.metrics.IncrementableMetric; -import google.registry.monitoring.metrics.LabelDescriptor; -import google.registry.monitoring.metrics.MetricRegistryImpl; +import com.google.monitoring.metrics.EventMetric; +import com.google.monitoring.metrics.IncrementableMetric; +import com.google.monitoring.metrics.LabelDescriptor; +import com.google.monitoring.metrics.MetricRegistryImpl; import google.registry.monitoring.whitebox.EppMetric; import javax.inject.Inject; diff --git a/java/google/registry/flows/async/AsyncFlowMetrics.java b/java/google/registry/flows/async/AsyncFlowMetrics.java index 57b33fd24..ba00ab668 100644 --- a/java/google/registry/flows/async/AsyncFlowMetrics.java +++ b/java/google/registry/flows/async/AsyncFlowMetrics.java @@ -15,19 +15,19 @@ package google.registry.flows.async; import static com.google.appengine.api.taskqueue.QueueConstants.maxLeaseCount; +import static com.google.monitoring.metrics.EventMetric.DEFAULT_FITTER; import static google.registry.flows.async.AsyncFlowMetrics.OperationType.CONTACT_AND_HOST_DELETE; import static google.registry.flows.async.AsyncFlowMetrics.OperationType.DNS_REFRESH; -import static google.registry.monitoring.metrics.EventMetric.DEFAULT_FITTER; import static google.registry.util.FormattingLogger.getLoggerForCallerClass; import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.ImmutableSet; -import google.registry.monitoring.metrics.DistributionFitter; -import google.registry.monitoring.metrics.EventMetric; -import google.registry.monitoring.metrics.FibonacciFitter; -import google.registry.monitoring.metrics.IncrementableMetric; -import google.registry.monitoring.metrics.LabelDescriptor; -import google.registry.monitoring.metrics.MetricRegistryImpl; +import com.google.monitoring.metrics.DistributionFitter; +import com.google.monitoring.metrics.EventMetric; +import com.google.monitoring.metrics.FibonacciFitter; +import com.google.monitoring.metrics.IncrementableMetric; +import com.google.monitoring.metrics.LabelDescriptor; +import com.google.monitoring.metrics.MetricRegistryImpl; import google.registry.util.Clock; import google.registry.util.FormattingLogger; import google.registry.util.NonFinalForTesting; diff --git a/java/google/registry/model/BUILD b/java/google/registry/model/BUILD index aa92f47b6..5f8434e48 100644 --- a/java/google/registry/model/BUILD +++ b/java/google/registry/model/BUILD @@ -14,7 +14,6 @@ java_library( visibility = ["//visibility:public"], deps = [ "//java/google/registry/config", - "//java/google/registry/monitoring/metrics", "//java/google/registry/util", "//java/google/registry/xml", "//third_party/objectify:objectify-v4_1", @@ -23,6 +22,7 @@ java_library( "@com_google_code_findbugs_jsr305", "@com_google_dagger", "@com_google_guava", + "@com_google_monitoring_client_metrics", "@com_google_re2j", "@javax_servlet_api", "@joda_time", diff --git a/java/google/registry/model/registry/label/DomainLabelMetrics.java b/java/google/registry/model/registry/label/DomainLabelMetrics.java index 518d8bc40..b92f10eca 100644 --- a/java/google/registry/model/registry/label/DomainLabelMetrics.java +++ b/java/google/registry/model/registry/label/DomainLabelMetrics.java @@ -17,10 +17,10 @@ package google.registry.model.registry.label; import com.google.auto.value.AutoValue; import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.ImmutableSet; -import google.registry.monitoring.metrics.EventMetric; -import google.registry.monitoring.metrics.IncrementableMetric; -import google.registry.monitoring.metrics.LabelDescriptor; -import google.registry.monitoring.metrics.MetricRegistryImpl; +import com.google.monitoring.metrics.EventMetric; +import com.google.monitoring.metrics.IncrementableMetric; +import com.google.monitoring.metrics.LabelDescriptor; +import com.google.monitoring.metrics.MetricRegistryImpl; /** Instrumentation for reserved lists. */ class DomainLabelMetrics { diff --git a/java/google/registry/model/server/LockMetrics.java b/java/google/registry/model/server/LockMetrics.java index ee772fd0e..2f26411e1 100644 --- a/java/google/registry/model/server/LockMetrics.java +++ b/java/google/registry/model/server/LockMetrics.java @@ -15,13 +15,13 @@ package google.registry.model.server; import com.google.common.collect.ImmutableSet; +import com.google.monitoring.metrics.DistributionFitter; +import com.google.monitoring.metrics.EventMetric; +import com.google.monitoring.metrics.ExponentialFitter; +import com.google.monitoring.metrics.IncrementableMetric; +import com.google.monitoring.metrics.LabelDescriptor; +import com.google.monitoring.metrics.MetricRegistryImpl; import google.registry.model.server.Lock.LockState; -import google.registry.monitoring.metrics.DistributionFitter; -import google.registry.monitoring.metrics.EventMetric; -import google.registry.monitoring.metrics.ExponentialFitter; -import google.registry.monitoring.metrics.IncrementableMetric; -import google.registry.monitoring.metrics.LabelDescriptor; -import google.registry.monitoring.metrics.MetricRegistryImpl; import javax.annotation.Nullable; import org.joda.time.Duration; diff --git a/java/google/registry/module/backend/BUILD b/java/google/registry/module/backend/BUILD index f25c6dccc..6f5f9df62 100644 --- a/java/google/registry/module/backend/BUILD +++ b/java/google/registry/module/backend/BUILD @@ -27,7 +27,6 @@ java_library( "//java/google/registry/keyring/kms", "//java/google/registry/mapreduce", "//java/google/registry/model", - "//java/google/registry/monitoring/metrics", "//java/google/registry/monitoring/whitebox", "//java/google/registry/rde", "//java/google/registry/rde/imports", @@ -41,6 +40,7 @@ java_library( "@com_google_code_findbugs_jsr305", "@com_google_dagger", "@com_google_guava", + "@com_google_monitoring_client_metrics", "@javax_servlet_api", "@joda_time", "@org_bouncycastle_bcpkix_jdk15on", diff --git a/java/google/registry/module/backend/BackendComponent.java b/java/google/registry/module/backend/BackendComponent.java index 636f58015..5259df12f 100644 --- a/java/google/registry/module/backend/BackendComponent.java +++ b/java/google/registry/module/backend/BackendComponent.java @@ -14,6 +14,7 @@ package google.registry.module.backend; +import com.google.monitoring.metrics.MetricReporter; import dagger.Component; import dagger.Lazy; import google.registry.bigquery.BigqueryModule; @@ -27,7 +28,6 @@ import google.registry.groups.GroupssettingsModule; import google.registry.keyring.api.KeyModule; import google.registry.keyring.kms.KmsModule; import google.registry.module.backend.BackendRequestComponent.BackendRequestComponentModule; -import google.registry.monitoring.metrics.MetricReporter; import google.registry.monitoring.whitebox.StackdriverModule; import google.registry.rde.JSchModule; import google.registry.request.Modules.AppIdentityCredentialModule; diff --git a/java/google/registry/module/backend/BackendServlet.java b/java/google/registry/module/backend/BackendServlet.java index 822435968..6d9c7ec79 100644 --- a/java/google/registry/module/backend/BackendServlet.java +++ b/java/google/registry/module/backend/BackendServlet.java @@ -15,8 +15,8 @@ package google.registry.module.backend; import com.google.appengine.api.LifecycleManager; +import com.google.monitoring.metrics.MetricReporter; import dagger.Lazy; -import google.registry.monitoring.metrics.MetricReporter; import google.registry.util.FormattingLogger; import java.io.IOException; import java.security.Security; diff --git a/java/google/registry/module/frontend/BUILD b/java/google/registry/module/frontend/BUILD index dd6bfd7ed..6dd190579 100644 --- a/java/google/registry/module/frontend/BUILD +++ b/java/google/registry/module/frontend/BUILD @@ -14,7 +14,6 @@ java_library( "//java/google/registry/flows", "//java/google/registry/keyring/api", "//java/google/registry/keyring/kms", - "//java/google/registry/monitoring/metrics", "//java/google/registry/monitoring/whitebox", "//java/google/registry/rdap", "//java/google/registry/request", @@ -28,6 +27,7 @@ java_library( "@com_google_code_findbugs_jsr305", "@com_google_dagger", "@com_google_guava", + "@com_google_monitoring_client_metrics", "@javax_servlet_api", "@org_bouncycastle_bcpkix_jdk15on", ], diff --git a/java/google/registry/module/frontend/FrontendComponent.java b/java/google/registry/module/frontend/FrontendComponent.java index 928c257e0..9835b4c4a 100644 --- a/java/google/registry/module/frontend/FrontendComponent.java +++ b/java/google/registry/module/frontend/FrontendComponent.java @@ -14,6 +14,7 @@ package google.registry.module.frontend; +import com.google.monitoring.metrics.MetricReporter; import dagger.Component; import dagger.Lazy; import google.registry.braintree.BraintreeModule; @@ -23,7 +24,6 @@ import google.registry.flows.custom.CustomLogicFactoryModule; import google.registry.keyring.api.KeyModule; import google.registry.keyring.kms.KmsModule; import google.registry.module.frontend.FrontendRequestComponent.FrontendRequestComponentModule; -import google.registry.monitoring.metrics.MetricReporter; import google.registry.monitoring.whitebox.StackdriverModule; import google.registry.request.Modules.AppIdentityCredentialModule; import google.registry.request.Modules.GoogleCredentialModule; diff --git a/java/google/registry/module/frontend/FrontendServlet.java b/java/google/registry/module/frontend/FrontendServlet.java index 0668ac6a1..bea84c67d 100644 --- a/java/google/registry/module/frontend/FrontendServlet.java +++ b/java/google/registry/module/frontend/FrontendServlet.java @@ -15,8 +15,8 @@ package google.registry.module.frontend; import com.google.appengine.api.LifecycleManager; +import com.google.monitoring.metrics.MetricReporter; import dagger.Lazy; -import google.registry.monitoring.metrics.MetricReporter; import google.registry.util.FormattingLogger; import java.io.IOException; import java.security.Security; diff --git a/java/google/registry/monitoring/metrics/AbstractMetric.java b/java/google/registry/monitoring/metrics/AbstractMetric.java deleted file mode 100644 index 68a0ee30f..000000000 --- a/java/google/registry/monitoring/metrics/AbstractMetric.java +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright 2017 The Nomulus 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.base.MoreObjects; -import com.google.common.collect.ImmutableSet; -import google.registry.monitoring.metrics.MetricSchema.Kind; - -abstract class AbstractMetric implements Metric { - - private final Class valueClass; - private final MetricSchema metricSchema; - - AbstractMetric( - String name, - String description, - String valueDisplayName, - Kind kind, - ImmutableSet labels, - Class valueClass) { - this.metricSchema = MetricSchema.create(name, description, valueDisplayName, kind, labels); - this.valueClass = valueClass; - } - - /** Returns the schema of this metric. */ - @Override - public final MetricSchema getMetricSchema() { - return metricSchema; - } - - /** - * Returns the type for the value of this metric, which would otherwise be erased at compile-time. - * This is useful for implementors of {@link MetricWriter}. - */ - @Override - public final Class getValueClass() { - return valueClass; - } - - @Override - public final String toString() { - return MoreObjects.toStringHelper(this) - .add("valueClass", valueClass) - .add("schema", metricSchema) - .toString(); - } -} diff --git a/java/google/registry/monitoring/metrics/BUILD b/java/google/registry/monitoring/metrics/BUILD deleted file mode 100644 index 6891e0d8b..000000000 --- a/java/google/registry/monitoring/metrics/BUILD +++ /dev/null @@ -1,19 +0,0 @@ -package( - default_visibility = ["//visibility:public"], -) - -licenses(["notice"]) # Apache 2.0 - -java_library( - name = "metrics", - srcs = glob(["*.java"]), - deps = [ - "@com_google_auto_value", - "@com_google_code_findbugs_jsr305", - "@com_google_dagger", - "@com_google_errorprone_error_prone_annotations", - "@com_google_guava", - "@com_google_re2j", - "@joda_time", - ], -) diff --git a/java/google/registry/monitoring/metrics/Counter.java b/java/google/registry/monitoring/metrics/Counter.java deleted file mode 100644 index 88bb38f77..000000000 --- a/java/google/registry/monitoring/metrics/Counter.java +++ /dev/null @@ -1,217 +0,0 @@ -// Copyright 2017 The Nomulus 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 static com.google.common.base.Preconditions.checkArgument; -import static google.registry.monitoring.metrics.MetricsUtils.DEFAULT_CONCURRENCY_LEVEL; -import static google.registry.monitoring.metrics.MetricsUtils.newConcurrentHashMap; - -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.AtomicLongMap; -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 javax.annotation.concurrent.ThreadSafe; -import org.joda.time.Instant; - -/** - * A metric which stores Long values. It is stateful and can be changed in increments. - * - *

This metric is generally suitable for counters, such as requests served or errors generated. - * - *

The start of the {@link MetricPoint#interval()} of values of instances of this metric will be - * set to the time that the metric was first set or last {@link #reset()}. - */ -@ThreadSafe -public final class Counter extends AbstractMetric - implements SettableMetric, IncrementableMetric { - - /** - * A map of the {@link Counter} values, with a list of label values as the keys. - * - *

This should be modified in a critical section with {@code valueStartTimestamps} so that the - * values are in sync. - */ - private final AtomicLongMap> values = AtomicLongMap.create(); - - /** - * A map of the {@link Instant} that each value was created, with a list of label values as the - * keys. The start timestamp (as part of the {@link MetricPoint#interval()} can be used by - * implementations of {@link MetricWriter} to encode resets of monotonic counters. - */ - private final ConcurrentHashMap, Instant> valueStartTimestamps = - newConcurrentHashMap(DEFAULT_CONCURRENCY_LEVEL); - - /** - * A fine-grained lock to ensure that {@code values} and {@code valueStartTimestamps} are modified - * and read in a critical section. The initialization parameter is the concurrency level, set to - * match the default concurrency level of {@link ConcurrentHashMap}. - * - * @see Striped - */ - private final Striped valueLocks = Striped.lock(DEFAULT_CONCURRENCY_LEVEL); - - /** - * Constructs a new Counter. - * - *

Note that the order of the labels is significant. - */ - Counter( - String name, - String description, - String valueDisplayName, - ImmutableSet labels) { - super(name, description, valueDisplayName, Kind.CUMULATIVE, labels, Long.class); - } - - @VisibleForTesting - void incrementBy(long offset, Instant startTimestamp, ImmutableList labelValues) { - Lock lock = valueLocks.get(labelValues); - lock.lock(); - - try { - values.addAndGet(labelValues, offset); - valueStartTimestamps.putIfAbsent(labelValues, startTimestamp); - } finally { - lock.unlock(); - } - } - - @Override - public final void incrementBy(long offset, String... labelValues) { - MetricsUtils.checkLabelValuesLength(this, labelValues); - checkArgument(offset >= 0, "The offset provided must be non-negative"); - - incrementBy(offset, Instant.now(), ImmutableList.copyOf(labelValues)); - } - - @Override - public final void increment(String... labelValues) { - MetricsUtils.checkLabelValuesLength(this, labelValues); - - incrementBy(1L, Instant.now(), ImmutableList.copyOf(labelValues)); - } - - /** - * Returns a snapshot of the metric's values. The timestamp of each {@link MetricPoint} will be - * the last modification time for that tuple of label values. - */ - @Override - public final ImmutableList> getTimestampedValues() { - return getTimestampedValues(Instant.now()); - } - - @Override - public final int getCardinality() { - return values.size(); - } - - @VisibleForTesting - final ImmutableList> getTimestampedValues(Instant endTimestamp) { - ImmutableList.Builder> timestampedValues = new ImmutableList.Builder<>(); - for (Entry, Long> entry : values.asMap().entrySet()) { - ImmutableList labelValues = entry.getKey(); - valueLocks.get(labelValues).lock(); - - Instant startTimestamp; - try { - startTimestamp = valueStartTimestamps.get(labelValues); - } finally { - valueLocks.get(labelValues).unlock(); - } - - // There is an opportunity for endTimestamp to be less than startTimestamp if - // one of the modification methods is called on a value before the lock for that value is - // acquired but after getTimestampedValues has been invoked. Just set endTimestamp equal to - // startTimestamp if that happens. - endTimestamp = Ordering.natural().max(startTimestamp, endTimestamp); - - timestampedValues.add( - MetricPoint.create(this, labelValues, startTimestamp, endTimestamp, entry.getValue())); - - } - return timestampedValues.build(); - } - - @VisibleForTesting - final void set(Long value, Instant startTimestamp, ImmutableList labelValues) { - Lock lock = valueLocks.get(labelValues); - lock.lock(); - - try { - this.values.put(labelValues, value); - valueStartTimestamps.putIfAbsent(labelValues, startTimestamp); - } finally { - lock.unlock(); - } - } - - @Override - public final void set(Long value, String... labelValues) { - MetricsUtils.checkLabelValuesLength(this, labelValues); - - set(value, Instant.now(), ImmutableList.copyOf(labelValues)); - } - - @VisibleForTesting - final void reset(Instant startTimestamp) { - // 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 labelValues : values.asMap().keySet()) { - this.values.put(labelValues, 0); - this.valueStartTimestamps.put(labelValues, startTimestamp); - } - } finally { - for (int i = 0; i < valueLocks.size(); i++) { - valueLocks.getAt(i).unlock(); - } - } - } - - @Override - public final void reset() { - reset(Instant.now()); - } - - @VisibleForTesting - final void reset(Instant startTimestamp, ImmutableList labelValues) { - Lock lock = valueLocks.get(labelValues); - lock.lock(); - - try { - this.values.put(labelValues, 0); - this.valueStartTimestamps.put(labelValues, startTimestamp); - } finally { - lock.unlock(); - } - } - - @Override - public final void reset(String... labelValues) { - MetricsUtils.checkLabelValuesLength(this, labelValues); - - reset(Instant.now(), ImmutableList.copyOf(labelValues)); - } -} diff --git a/java/google/registry/monitoring/metrics/CustomFitter.java b/java/google/registry/monitoring/metrics/CustomFitter.java deleted file mode 100644 index 353e5afd6..000000000 --- a/java/google/registry/monitoring/metrics/CustomFitter.java +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright 2017 The Nomulus 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 static com.google.common.base.Preconditions.checkArgument; -import static google.registry.monitoring.metrics.MetricsUtils.checkDouble; - -import com.google.auto.value.AutoValue; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.ImmutableSortedSet; -import com.google.common.collect.Ordering; - -/** - * Models a {@link DistributionFitter} with arbitrary sized intervals. - * - *

If only only one boundary is provided, then the fitter will consist of an overflow and - * underflow interval separated by that boundary. - */ -@AutoValue -public abstract class CustomFitter implements DistributionFitter { - - /** - * Create a new {@link CustomFitter} with the given interval boundaries. - * - * @param boundaries is a sorted list of interval boundaries - * @throws IllegalArgumentException if {@code boundaries} is empty or not sorted in ascending - * order, or if a value in the set is infinite, {@code NaN}, or {@code -0.0}. - */ - public static CustomFitter create(ImmutableSet boundaries) { - checkArgument(boundaries.size() > 0, "boundaries must not be empty"); - checkArgument(Ordering.natural().isOrdered(boundaries), "boundaries must be sorted"); - for (Double d : boundaries) { - checkDouble(d); - } - - return new AutoValue_CustomFitter(ImmutableSortedSet.copyOf(boundaries)); - } - - @Override - public abstract ImmutableSortedSet boundaries(); -} diff --git a/java/google/registry/monitoring/metrics/Distribution.java b/java/google/registry/monitoring/metrics/Distribution.java deleted file mode 100644 index be8b8a118..000000000 --- a/java/google/registry/monitoring/metrics/Distribution.java +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright 2017 The Nomulus 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.collect.ImmutableRangeMap; - -/** - * Models a distribution of double-precision floating point sample data, and provides summary - * statistics of the distribution. This class also models the probability density function (PDF) of - * the distribution with a histogram. - * - *

The summary statistics provided are the mean and sumOfSquaredDeviation of the distribution. - * - *

The histogram fitting function is provided via a {@link DistributionFitter} implementation. - * - * @see DistributionFitter - */ -public interface Distribution { - - /** Returns the mean of this distribution. */ - double mean(); - - /** Returns the sum of squared deviations from the mean of this distribution. */ - double sumOfSquaredDeviation(); - - /** Returns the count of samples in this distribution. */ - long count(); - - /** Returns a histogram of the distribution's values. */ - ImmutableRangeMap intervalCounts(); - - /** Returns the {@link DistributionFitter} of this distribution. */ - DistributionFitter distributionFitter(); -} diff --git a/java/google/registry/monitoring/metrics/DistributionFitter.java b/java/google/registry/monitoring/metrics/DistributionFitter.java deleted file mode 100644 index e88ea94b5..000000000 --- a/java/google/registry/monitoring/metrics/DistributionFitter.java +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2017 The Nomulus 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.collect.ImmutableSortedSet; - -/** - * A companion interface to {@link Distribution} which fits samples to a histogram in order to - * estimate the probability density function (PDF) of the {@link Distribution}. - * - *

The fitter models the histogram with a set of finite boundaries. The closed-open interval - * [a,b) between two consecutive boundaries represents the domain of permissible values in that - * interval. The values less than the first boundary are in the underflow interval of (-inf, a) and - * values greater or equal to the last boundary in the array are in the overflow interval of [a, - * inf). - */ -public interface DistributionFitter { - - /** Returns a sorted set of the boundaries modeled by this {@link DistributionFitter}. */ - ImmutableSortedSet boundaries(); -} diff --git a/java/google/registry/monitoring/metrics/EventMetric.java b/java/google/registry/monitoring/metrics/EventMetric.java deleted file mode 100644 index b3dab9a31..000000000 --- a/java/google/registry/monitoring/metrics/EventMetric.java +++ /dev/null @@ -1,219 +0,0 @@ -// Copyright 2017 The Nomulus 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 static google.registry.monitoring.metrics.MetricsUtils.DEFAULT_CONCURRENCY_LEVEL; -import static google.registry.monitoring.metrics.MetricsUtils.newConcurrentHashMap; - -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 class EventMetric extends AbstractMetric { - - /** - * Default {@link DistributionFitter} suitable for latency measurements. - * - *

The finite range of this fitter is from 1 to 4^16 (4294967296). - */ - public static final DistributionFitter DEFAULT_FITTER = ExponentialFitter.create(16, 4.0, 1.0); - - private final ConcurrentHashMap, Instant> valueStartTimestamps = - newConcurrentHashMap(DEFAULT_CONCURRENCY_LEVEL); - private final ConcurrentHashMap, MutableDistribution> values = - newConcurrentHashMap(DEFAULT_CONCURRENCY_LEVEL); - - private final DistributionFitter distributionFitter; - - /** - * A fine-grained lock to ensure that {@code values} and {@code valueStartTimestamps} are modified - * and read in a critical section. The initialization parameter is the concurrency level, set to - * match the default concurrency level of {@link ConcurrentHashMap}. - * - * @see Striped - */ - private final Striped valueLocks = Striped.lock(DEFAULT_CONCURRENCY_LEVEL); - - EventMetric( - String name, - String description, - String valueDisplayName, - DistributionFitter distributionFitter, - ImmutableSet labels) { - super(name, description, valueDisplayName, Kind.CUMULATIVE, labels, Distribution.class); - - this.distributionFitter = distributionFitter; - } - - @Override - public final int getCardinality() { - return values.size(); - } - - @Override - public final ImmutableList> getTimestampedValues() { - return getTimestampedValues(Instant.now()); - } - - @VisibleForTesting - ImmutableList> getTimestampedValues(Instant endTimestamp) { - ImmutableList.Builder> timestampedValues = - new ImmutableList.Builder<>(); - - for (Entry, MutableDistribution> entry : values.entrySet()) { - ImmutableList labelValues = entry.getKey(); - Lock lock = valueLocks.get(labelValues); - lock.lock(); - - Instant startTimestamp; - ImmutableDistribution distribution; - try { - startTimestamp = valueStartTimestamps.get(labelValues); - distribution = ImmutableDistribution.copyOf(entry.getValue()); - } finally { - lock.unlock(); - } - - // There is an opportunity for endTimestamp to be less than startTimestamp if - // one of the modification methods is called on a value before the lock for that value is - // acquired but after getTimestampedValues has been invoked. Just set endTimestamp equal to - // startTimestamp if that happens. - endTimestamp = Ordering.natural().max(startTimestamp, endTimestamp); - - timestampedValues.add( - MetricPoint.create(this, labelValues, startTimestamp, endTimestamp, distribution)); - } - - return timestampedValues.build(); - } - - /** - * Adds 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 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 void record(double sample, int count, String... labelValues) { - MetricsUtils.checkLabelValuesLength(this, labelValues); - - recordMultiple(sample, count, Instant.now(), ImmutableList.copyOf(labelValues)); - } - - @VisibleForTesting - void recordMultiple( - double sample, int count, Instant startTimestamp, ImmutableList labelValues) { - Lock lock = valueLocks.get(labelValues); - lock.lock(); - - try { - values.computeIfAbsent(labelValues, k -> new MutableDistribution(distributionFitter)); - - values.get(labelValues).add(sample, count); - valueStartTimestamps.putIfAbsent(labelValues, startTimestamp); - } finally { - lock.unlock(); - } - } - - /** - * Atomically resets the value and start timestamp of the metric for all label values. - * - *

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 labelValues : values.keySet()) { - this.values.put(labelValues, new MutableDistribution(distributionFitter)); - this.valueStartTimestamps.put(labelValues, startTime); - } - } finally { - for (int i = 0; i < valueLocks.size(); i++) { - valueLocks.getAt(i).unlock(); - } - } - } - - /** - * Resets the value and start timestamp of the metric for the given label values. - * - *

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 labelValues) { - Lock lock = valueLocks.get(labelValues); - lock.lock(); - - try { - this.values.put(labelValues, new MutableDistribution(distributionFitter)); - this.valueStartTimestamps.put(labelValues, startTimestamp); - } finally { - lock.unlock(); - } - } -} diff --git a/java/google/registry/monitoring/metrics/ExponentialFitter.java b/java/google/registry/monitoring/metrics/ExponentialFitter.java deleted file mode 100644 index 70b62cfbe..000000000 --- a/java/google/registry/monitoring/metrics/ExponentialFitter.java +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright 2017 The Nomulus 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 static com.google.common.base.Preconditions.checkArgument; -import static google.registry.monitoring.metrics.MetricsUtils.checkDouble; - -import com.google.auto.value.AutoValue; -import com.google.common.collect.ImmutableSortedSet; - -/** - * Models a {@link DistributionFitter} with intervals of exponentially increasing size. - * - *

The interval boundaries are defined by {@code scale * Math.pow(base, i)} for {@code i} in - * {@code [0, numFiniteIntervals]}. - * - *

For example, an {@link ExponentialFitter} with {@code numFiniteIntervals=3, base=4.0, - * scale=1.5} represents a histogram with intervals {@code (-inf, 1.5), [1.5, 6), [6, 24), [24, 96), - * [96, +inf)}. - */ -@AutoValue -public abstract class ExponentialFitter implements DistributionFitter { - - /** - * Create a new {@link ExponentialFitter}. - * - * @param numFiniteIntervals the number of intervals, excluding the underflow and overflow - * intervals - * @param base the base of the exponent - * @param scale a multiplicative factor for the exponential function - * @throws IllegalArgumentException if {@code numFiniteIntervals <= 0}, {@code width <= 0} or - * {@code base <= 1} - */ - public static ExponentialFitter create(int numFiniteIntervals, double base, double scale) { - checkArgument(numFiniteIntervals > 0, "numFiniteIntervals must be greater than 0"); - checkArgument(scale != 0, "scale must not be 0"); - checkArgument(base > 1, "base must be greater than 1"); - checkDouble(base); - checkDouble(scale); - - ImmutableSortedSet.Builder boundaries = ImmutableSortedSet.naturalOrder(); - - for (int i = 0; i < numFiniteIntervals + 1; i++) { - boundaries.add(scale * Math.pow(base, i)); - } - - return new AutoValue_ExponentialFitter(base, scale, boundaries.build()); - } - - public abstract double base(); - - public abstract double scale(); - - @Override - public abstract ImmutableSortedSet boundaries(); -} diff --git a/java/google/registry/monitoring/metrics/FibonacciFitter.java b/java/google/registry/monitoring/metrics/FibonacciFitter.java deleted file mode 100644 index f7d6a36ab..000000000 --- a/java/google/registry/monitoring/metrics/FibonacciFitter.java +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright 2017 The Nomulus 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 static com.google.common.base.Preconditions.checkArgument; - -import com.google.common.collect.ImmutableSortedSet; - -/** - * Utility method to create a {@link CustomFitter} with intervals using the Fibonacci sequence. - * - *

A Fibonacci fitter is useful in situations where you want more precision on the low end than - * an {@link ExponentialFitter} with exponent base 2 would provide without the hassle of dealing - * with non-integer boundaries, such as would be created by an exponential fitter with a base of - * less than 2. Fibonacci fitters are ideal for integer metrics that are bounded across a certain - * range, e.g. integers between 1 and 1,000. - * - *

The interval boundaries are chosen as {@code (-inf, 0), [0, 1), [1, 2), [2, 3), [3, 5), [5, - * 8), [8, 13)}, etc., up to {@code [fibonacciFloor(maxBucketSize), inf)}. - */ -public final class FibonacciFitter { - - /** - * Returns a new {@link CustomFitter} with bounds corresponding to the Fibonacci sequence. - * - * @param maxBucketSize the maximum bucket size to create (rounded down to the nearest Fibonacci - * number) - * @throws IllegalArgumentException if {@code maxBucketSize <= 0} - */ - public static CustomFitter create(long maxBucketSize) { - checkArgument(maxBucketSize > 0, "maxBucketSize must be greater than 0"); - - ImmutableSortedSet.Builder boundaries = ImmutableSortedSet.naturalOrder(); - boundaries.add(Double.valueOf(0)); - long i = 1; - long j = 2; - long k = 3; - while (i <= maxBucketSize) { - boundaries.add(Double.valueOf(i)); - i = j; - j = k; - k = i + j; - } - - return CustomFitter.create(boundaries.build()); - } - - private FibonacciFitter() {} -} diff --git a/java/google/registry/monitoring/metrics/ImmutableDistribution.java b/java/google/registry/monitoring/metrics/ImmutableDistribution.java deleted file mode 100644 index bcd211ced..000000000 --- a/java/google/registry/monitoring/metrics/ImmutableDistribution.java +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright 2017 The Nomulus 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 static com.google.common.base.Preconditions.checkArgument; -import static google.registry.monitoring.metrics.MetricsUtils.checkDouble; - -import com.google.auto.value.AutoValue; -import com.google.common.annotations.VisibleForTesting; -import com.google.common.collect.ImmutableRangeMap; -import javax.annotation.concurrent.ThreadSafe; - -/** - * An immutable {@link Distribution}. Instances of this class can used to create {@link MetricPoint} - * instances, and should be used when exporting values to a {@link MetricWriter}. - * - * @see MutableDistribution - */ -@ThreadSafe -@AutoValue -public abstract class ImmutableDistribution implements Distribution { - - public static ImmutableDistribution copyOf(Distribution distribution) { - return new AutoValue_ImmutableDistribution( - distribution.mean(), - distribution.sumOfSquaredDeviation(), - distribution.count(), - distribution.intervalCounts(), - distribution.distributionFitter()); - } - - @VisibleForTesting - static ImmutableDistribution create( - double mean, - double sumOfSquaredDeviation, - long count, - ImmutableRangeMap intervalCounts, - DistributionFitter distributionFitter) { - checkDouble(mean); - checkDouble(sumOfSquaredDeviation); - checkArgument(count >= 0); - - return new AutoValue_ImmutableDistribution( - mean, sumOfSquaredDeviation, count, intervalCounts, distributionFitter); - } - - @Override - public abstract double mean(); - - @Override - public abstract double sumOfSquaredDeviation(); - - @Override - public abstract long count(); - - @Override - public abstract ImmutableRangeMap intervalCounts(); - - @Override - public abstract DistributionFitter distributionFitter(); -} diff --git a/java/google/registry/monitoring/metrics/IncrementableMetric.java b/java/google/registry/monitoring/metrics/IncrementableMetric.java deleted file mode 100644 index b9bd5aec4..000000000 --- a/java/google/registry/monitoring/metrics/IncrementableMetric.java +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright 2017 The Nomulus 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; - -/** - * A {@link Metric} which can be incremented. - * - *

This is a view into a {@link Counter} to provide compile-time checking to disallow arbitrarily - * setting the metric, which is useful for metrics which should be monotonically increasing. - */ -public interface IncrementableMetric extends Metric { - - /** - * Increments a metric by 1 for the given label values. - * - *

Use this method rather than {@link IncrementableMetric#incrementBy(long, String...)} if the - * increment value is 1, as it will be slightly more performant. - * - *

If the metric is undefined for given label values, it will be incremented from zero. - * - *

The metric's timestamp will be updated to the current time for the given label values. - * - *

The count of {@code labelValues} must be equal to the underlying metric's count of labels. - */ - void increment(String... labelValues); - - /** - * Increments a metric by the given non-negative offset for the given label values. - * - *

If the metric is undefined for given label values, it will be incremented from zero. - * - *

The metric's timestamp will be updated to the current time for the given label values. - * - *

The count of {@code labelValues} must be equal to the underlying metric's count of labels. - * - * @throws IllegalArgumentException if the offset is negative. - */ - void incrementBy(long offset, String... labelValues); - - /** - * Resets the value and start timestamp of the metric for the given label values. - * - *

This is useful if the counter is tracking a value that is reset as part of a retrying - * transaction, for example. - */ - void reset(String... labelValues); - - /** - * Atomically resets the value and start timestamp of the metric for all label values. - * - *

This is useful if the counter is tracking values that are reset as part of a retrying - * transaction, for example. - */ - void reset(); -} diff --git a/java/google/registry/monitoring/metrics/LabelDescriptor.java b/java/google/registry/monitoring/metrics/LabelDescriptor.java deleted file mode 100644 index 7fb50356a..000000000 --- a/java/google/registry/monitoring/metrics/LabelDescriptor.java +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright 2017 The Nomulus 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 static com.google.common.base.Preconditions.checkArgument; - -import com.google.auto.value.AutoValue; -import com.google.re2j.Pattern; - -/** - * Definition of a metric label. - * - *

If a metric is created with labels, corresponding label values must be provided when setting - * values on the metric. - */ -@AutoValue -public abstract class LabelDescriptor { - - private static final Pattern ALLOWED_LABEL_PATTERN = Pattern.compile("\\w+"); - - LabelDescriptor() {} - - /** - * Returns a new {@link LabelDescriptor}. - * - * @param name identifier for label - * @param description human-readable description of label - * @throws IllegalArgumentException if {@code name} isn't {@code \w+} or {@code description} is - * blank - */ - public static LabelDescriptor create(String name, String description) { - checkArgument(!name.isEmpty(), "Name must not be empty"); - checkArgument(!description.isEmpty(), "Description must not be empty"); - checkArgument( - ALLOWED_LABEL_PATTERN.matches(name), - "Label name must match the regex %s", - ALLOWED_LABEL_PATTERN); - - return new AutoValue_LabelDescriptor(name, description); - } - - public abstract String name(); - - public abstract String description(); -} diff --git a/java/google/registry/monitoring/metrics/LinearFitter.java b/java/google/registry/monitoring/metrics/LinearFitter.java deleted file mode 100644 index 509bb4487..000000000 --- a/java/google/registry/monitoring/metrics/LinearFitter.java +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright 2017 The Nomulus 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 static com.google.common.base.Preconditions.checkArgument; -import static google.registry.monitoring.metrics.MetricsUtils.checkDouble; - -import com.google.auto.value.AutoValue; -import com.google.common.collect.ImmutableSortedSet; - -/** - * Models a {@link DistributionFitter} with equally sized intervals. - * - *

The interval boundaries are defined by {@code width * i + offset} for {@code i} in {@code [0, - * numFiniteIntervals}. - * - *

For example, a {@link LinearFitter} with {@code numFiniteIntervals=2, width=10, offset=5} - * represents a histogram with intervals {@code (-inf, 5), [5, 15), [15, 25), [25, +inf)}. - */ -@AutoValue -public abstract class LinearFitter implements DistributionFitter { - - /** - * Create a new {@link LinearFitter}. - * - * @param numFiniteIntervals the number of intervals, excluding the underflow and overflow - * intervals - * @param width the width of each interval - * @param offset the start value of the first interval - * @throws IllegalArgumentException if {@code numFiniteIntervals <= 0} or {@code width <= 0} - */ - public static LinearFitter create(int numFiniteIntervals, double width, double offset) { - checkArgument(numFiniteIntervals > 0, "numFiniteIntervals must be greater than 0"); - checkArgument(width > 0, "width must be greater than 0"); - checkDouble(offset); - - ImmutableSortedSet.Builder boundaries = ImmutableSortedSet.naturalOrder(); - - for (int i = 0; i < numFiniteIntervals + 1; i++) { - boundaries.add(width * i + offset); - } - - return new AutoValue_LinearFitter(width, offset, boundaries.build()); - } - - public abstract double width(); - - public abstract double offset(); - - @Override - public abstract ImmutableSortedSet boundaries(); -} diff --git a/java/google/registry/monitoring/metrics/Metric.java b/java/google/registry/monitoring/metrics/Metric.java deleted file mode 100644 index b3eeac96f..000000000 --- a/java/google/registry/monitoring/metrics/Metric.java +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2017 The Nomulus 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.collect.ImmutableList; - -/** - * A Metric which stores timestamped values. - * - *

This is a read-only view. - */ -public interface Metric { - - /** - * Returns the latest {@link MetricPoint} instances for every label-value combination tracked for - * this metric. - */ - ImmutableList> getTimestampedValues(); - - /** Returns the count of values being stored with this metric. */ - int getCardinality(); - - /** Returns the schema of this metric. */ - MetricSchema getMetricSchema(); - - /** - * Returns the type for the value of this metric, which would otherwise be erased at compile-time. - * This is useful for implementors of {@link MetricWriter}. - */ - Class getValueClass(); -} diff --git a/java/google/registry/monitoring/metrics/MetricExporter.java b/java/google/registry/monitoring/metrics/MetricExporter.java deleted file mode 100644 index 7a714a9c4..000000000 --- a/java/google/registry/monitoring/metrics/MetricExporter.java +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright 2017 The Nomulus 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 static com.google.common.util.concurrent.MoreExecutors.directExecutor; - -import com.google.common.collect.ImmutableList; -import com.google.common.util.concurrent.AbstractExecutionThreadService; -import java.io.IOException; -import java.util.Optional; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.Executor; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.ThreadFactory; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * Background service to asynchronously push bundles of {@link MetricPoint} instances to a {@link - * MetricWriter}. - */ -class MetricExporter extends AbstractExecutionThreadService { - - private static final Logger logger = Logger.getLogger(MetricReporter.class.getName()); - - private final BlockingQueue>>> writeQueue; - private final MetricWriter writer; - private final ThreadFactory threadFactory; - - MetricExporter( - BlockingQueue>>> writeQueue, - MetricWriter writer, - ThreadFactory threadFactory) { - this.writeQueue = writeQueue; - this.writer = writer; - this.threadFactory = threadFactory; - } - - @Override - protected void run() throws Exception { - logger.info("Started up MetricExporter"); - while (isRunning()) { - Optional>> batch = writeQueue.take(); - logger.info("Got a batch of points from the writeQueue"); - if (batch.isPresent()) { - logger.info("Batch contains data, writing to MetricWriter"); - try { - for (MetricPoint point : batch.get()) { - writer.write(point); - } - writer.flush(); - } catch (IOException exception) { - logger.log( - Level.SEVERE, "Threw an exception while writing or flushing metrics", exception); - } - } else { - logger.info("Received a poison pill, stopping now"); - // An absent optional indicates that the Reporter wants this service to shut down. - return; - } - } - } - - @Override - protected Executor executor() { - final ExecutorService executor = Executors.newSingleThreadExecutor(threadFactory); - // Make sure the ExecutorService terminates when this service does. - addListener( - new Listener() { - @Override - public void terminated(State from) { - executor.shutdown(); - } - - @Override - public void failed(State from, Throwable failure) { - executor.shutdown(); - } - }, - directExecutor()); - return executor; - } -} diff --git a/java/google/registry/monitoring/metrics/MetricMetrics.java b/java/google/registry/monitoring/metrics/MetricMetrics.java deleted file mode 100644 index 17a768533..000000000 --- a/java/google/registry/monitoring/metrics/MetricMetrics.java +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright 2017 The Nomulus 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.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; -import java.util.HashMap; - -/** Static store of metrics internal to this client library. */ -final class MetricMetrics { - - /** A counter representing the total number of push intervals since the start of the process. */ - static final IncrementableMetric pushIntervals = - MetricRegistryImpl.getDefault() - .newIncrementableMetric( - "/metrics/push_intervals", - "Count of push intervals.", - "Push Intervals", - ImmutableSet.of()); - private static final ImmutableSet LABELS = - ImmutableSet.of( - LabelDescriptor.create("kind", "Metric Kind"), - LabelDescriptor.create("valueType", "Metric Value Type")); - - /** - * A counter representing the total number of points pushed. Has {@link MetricSchema.Kind} and - * Metric value classes as LABELS. - */ - static final IncrementableMetric pushedPoints = - MetricRegistryImpl.getDefault() - .newIncrementableMetric( - "/metrics/points_pushed", - "Count of points pushed to Monitoring API.", - "Points Pushed", - LABELS); - - /** A gauge representing a snapshot of the number of active timeseries being reported. */ - @SuppressWarnings("unused") - private static final Metric timeseriesCount = - MetricRegistryImpl.getDefault() - .newGauge( - "/metrics/timeseries_count", - "Count of Timeseries being pushed to Monitoring API", - "Timeseries Count", - LABELS, - () -> { - HashMap, Long> timeseriesCount = new HashMap<>(); - - for (Metric metric : MetricRegistryImpl.getDefault().getRegisteredMetrics()) { - ImmutableList key = - ImmutableList.of( - metric.getMetricSchema().kind().toString(), - metric.getValueClass().toString()); - - int cardinality = metric.getCardinality(); - if (!timeseriesCount.containsKey(key)) { - timeseriesCount.put(key, (long) cardinality); - } else { - timeseriesCount.put(key, timeseriesCount.get(key) + cardinality); - } - } - - return ImmutableMap.copyOf(timeseriesCount); - }, - Long.class); - - private MetricMetrics() {} -} diff --git a/java/google/registry/monitoring/metrics/MetricPoint.java b/java/google/registry/monitoring/metrics/MetricPoint.java deleted file mode 100644 index faf454f71..000000000 --- a/java/google/registry/monitoring/metrics/MetricPoint.java +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright 2017 The Nomulus 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.auto.value.AutoValue; -import com.google.common.annotations.VisibleForTesting; -import com.google.common.collect.ImmutableList; -import org.joda.time.Instant; -import org.joda.time.Interval; - -/** - * Value type class to store a snapshot of a {@link Metric} value for a given label value tuple and - * time {@link Interval}. - */ -@AutoValue -public abstract class MetricPoint implements Comparable> { - - /** - * Returns a new {@link MetricPoint} representing a value at a specific {@link Instant}. - * - *

Callers should insure that the count of {@code labelValues} matches the count of labels for - * the given metric. - */ - @VisibleForTesting - public static MetricPoint create( - Metric metric, ImmutableList labelValues, Instant timestamp, V value) { - MetricsUtils.checkLabelValuesLength(metric, labelValues); - - return new AutoValue_MetricPoint<>( - metric, labelValues, new Interval(timestamp, timestamp), value); - } - - /** - * Returns a new {@link MetricPoint} representing a value over an {@link Interval} from {@code - * startTime} to {@code endTime}. - * - *

Callers should insure that the count of {@code labelValues} matches the count of labels for - * the given metric. - */ - @VisibleForTesting - public static MetricPoint create( - Metric metric, - ImmutableList labelValues, - Instant startTime, - Instant endTime, - V value) { - MetricsUtils.checkLabelValuesLength(metric, labelValues); - - return new AutoValue_MetricPoint<>( - metric, labelValues, new Interval(startTime, endTime), value); - } - - public abstract Metric metric(); - - public abstract ImmutableList labelValues(); - - public abstract Interval interval(); - - public abstract V value(); - - @Override - public int compareTo(MetricPoint other) { - int minLength = Math.min(this.labelValues().size(), other.labelValues().size()); - for (int index = 0; index < minLength; index++) { - int comparisonResult = - this.labelValues().get(index).compareTo(other.labelValues().get(index)); - if (comparisonResult != 0) { - return comparisonResult; - } - } - return Integer.compare(this.labelValues().size(), other.labelValues().size()); - } -} diff --git a/java/google/registry/monitoring/metrics/MetricRegistry.java b/java/google/registry/monitoring/metrics/MetricRegistry.java deleted file mode 100644 index 5b4641b2d..000000000 --- a/java/google/registry/monitoring/metrics/MetricRegistry.java +++ /dev/null @@ -1,140 +0,0 @@ -// Copyright 2017 The Nomulus 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.base.Supplier; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; - -/** An interface to create and keep track of metrics. */ -public interface MetricRegistry { - - /** - * Returns a new Gauge metric. - * - *

The metric's values are computed at sample time via the supplied callback function. The - * metric will be registered at the time of creation and collected for subsequent write intervals. - * - *

Since the metric's values are computed by a pre-defined callback function, this method only - * returns a read-only {@link Metric} view. - * - * @param name name of the metric. Should be in the form of '/foo/bar'. - * @param description human readable description of the metric. Must not be empty. - * @param valueDisplayName human readable description of the metric's value type. Must not be - * empty. - * @param labels list of the metric's labels. The labels (if there are any) must be of type - * STRING. - * @param metricCallback {@link Supplier} to compute the on-demand values of the metric. The - * function should be lightweight to compute and must be thread-safe. The map keys, which are - * lists of strings, must match in quantity and order with the provided labels. - * @param valueClass type hint to allow for compile-time encoding. Must match . - * @param value type of the metric. Must be one of {@link Boolean}, {@link Double}, {@link - * Long}, or {@link String}. - * @throws IllegalStateException if a metric of the same name is already registered. - */ - Metric newGauge( - String name, - String description, - String valueDisplayName, - ImmutableSet labels, - Supplier, V>> metricCallback, - Class valueClass); - - /** - * Returns a new {@link SettableMetric}. - * - *

The metric's value is stateful and can be set to different values over time. - * - *

The metric is thread-safe. - * - *

The metric will be registered at the time of creation and collected for subsequent write - * intervals. - * - * @param name name of the metric. Should be in the form of '/foo/bar'. - * @param description human readable description of the metric. - * @param valueDisplayName human readable description of the metric's value type. - * @param labels list of the metric's labels. The labels (if there are any) must be of type - * STRING. - * @param valueClass type hint to allow for compile-time encoding. Must match . - * @param value type of the metric. Must be one of {@link Boolean}, {@link Double}, {@link - * Long}, or {@link String}. - * @throws IllegalStateException if a metric of the same name is already registered. - */ - SettableMetric newSettableMetric( - String name, - String description, - String valueDisplayName, - ImmutableSet labels, - Class valueClass); - - /** - * Returns a new {@link IncrementableMetric}. - * - *

The metric's values are {@link Long}, and can be incremented, and decremented. The metric is - * thread-safe. The metric will be registered at the time of creation and collected for subsequent - * write intervals. - * - *

This metric type is generally intended for monotonically increasing values, although the - * metric can in fact be incremented by negative numbers. - * - * @param name name of the metric. Should be in the form of '/foo/bar'. - * @param description human readable description of the metric. - * @param valueDisplayName human readable description of the metric's value type. - * @param labels list of the metric's labels. The labels (if there are any) must be of type - * STRING. - * @throws IllegalStateException if a metric of the same name is already registered. - */ - IncrementableMetric newIncrementableMetric( - String name, - String description, - String valueDisplayName, - ImmutableSet labels); - - /** - * Returns a new {@link EventMetric}. - * - *

This metric type is intended for recording aspects of an "event" -- things like latency or - * payload size. - * - *

The metric's values are {@link Distribution} instances which are updated via {@link - * EventMetric#record(double, String...)}. - * - *

The metric is thread-safe. The metric will be registered at the time of creation and - * collected for subsequent write intervals. - * - * @param name name of the metric. Should be in the form of '/foo/bar'. - * @param description human readable description of the metric. - * @param valueDisplayName human readable description of the metric's value type. - * @param labels list of the metric's labels. - * @param distributionFitter fit to apply to the underlying {@link Distribution} instances of this - * metric. - * @throws IllegalStateException if a metric of the same name is already registered. - */ - EventMetric newEventMetric( - String name, - String description, - String valueDisplayName, - ImmutableSet labels, - DistributionFitter distributionFitter); - - /** - * Fetches a snapshot of the currently registered metrics - * - *

Users who wish to manually sample and write metrics without relying on the scheduled {@link - * MetricReporter} can use this method to gather the list of metrics to report. - */ - ImmutableList> getRegisteredMetrics(); -} diff --git a/java/google/registry/monitoring/metrics/MetricRegistryImpl.java b/java/google/registry/monitoring/metrics/MetricRegistryImpl.java deleted file mode 100644 index d490a1ecc..000000000 --- a/java/google/registry/monitoring/metrics/MetricRegistryImpl.java +++ /dev/null @@ -1,163 +0,0 @@ -// Copyright 2017 The Nomulus 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 static com.google.common.base.Preconditions.checkState; - -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Supplier; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; -import com.google.errorprone.annotations.CanIgnoreReturnValue; -import java.util.concurrent.ConcurrentHashMap; -import java.util.logging.Logger; -import javax.annotation.concurrent.ThreadSafe; - -/** A singleton registry of {@link Metric}s. */ -@ThreadSafe -public final class MetricRegistryImpl implements MetricRegistry { - - private static final Logger logger = Logger.getLogger(MetricRegistryImpl.class.getName()); - private static final MetricRegistryImpl INSTANCE = new MetricRegistryImpl(); - - /** The canonical registry for metrics. The map key is the metric name. */ - private final ConcurrentHashMap> registeredMetrics = new ConcurrentHashMap<>(); - - /** - * Production code must use {@link #getDefault}, since this returns the {@link MetricRegistry} - * that {@link MetricReporter} uses. Test code that does not use {@link MetricReporter} can use - * this constructor to get an isolated instance of the registry. - */ - @VisibleForTesting - public MetricRegistryImpl() {} - - public static MetricRegistryImpl getDefault() { - return INSTANCE; - } - - /** - * Creates a new event metric. - * - *

Note that the order of the labels is significant. - */ - @Override - public EventMetric newEventMetric( - String name, - String description, - String valueDisplayName, - ImmutableSet labels, - DistributionFitter distributionFitter) { - EventMetric metric = - new EventMetric(name, description, valueDisplayName, distributionFitter, labels); - registerMetric(name, metric); - logger.info("Registered new event metric: " + name); - - return metric; - } - - /** - * Creates a new gauge metric. - * - *

Note that the order of the labels is significant. - */ - @Override - @CanIgnoreReturnValue - public Metric newGauge( - String name, - String description, - String valueDisplayName, - ImmutableSet labels, - Supplier, V>> metricCallback, - Class valueClass) { - VirtualMetric metric = - new VirtualMetric<>( - name, description, valueDisplayName, labels, metricCallback, valueClass); - registerMetric(name, metric); - logger.info("Registered new callback metric: " + name); - - return metric; - } - - /** - * Creates a new settable metric. - * - *

Note that the order of the labels is significant. - */ - @Override - public SettableMetric newSettableMetric( - String name, - String description, - String valueDisplayName, - ImmutableSet labels, - Class valueClass) { - StoredMetric metric = - new StoredMetric<>(name, description, valueDisplayName, labels, valueClass); - registerMetric(name, metric); - logger.info("Registered new stored metric: " + name); - - return metric; - } - - /** - * Creates a new incrementable metric. - * - *

Note that the order of the labels is significant. - */ - @Override - public IncrementableMetric newIncrementableMetric( - String name, - String description, - String valueDisplayName, - ImmutableSet labels) { - Counter metric = new Counter(name, description, valueDisplayName, labels); - registerMetric(name, metric); - logger.info("Registered new counter: " + name); - - return metric; - } - - @Override - public ImmutableList> getRegisteredMetrics() { - return ImmutableList.copyOf(registeredMetrics.values()); - } - - /** - * Unregisters a metric. - * - *

This is a no-op if the metric is not already registered. - * - *

{@link MetricWriter} implementations should not send unregistered metrics on subsequent - * write intervals. - */ - @VisibleForTesting - public void unregisterMetric(String name) { - registeredMetrics.remove(name); - logger.info("Unregistered metric: " + name); - } - - @VisibleForTesting - public void unregisterAllMetrics() { - registeredMetrics.clear(); - } - - /** Registers a metric. */ - @VisibleForTesting - void registerMetric(String name, Metric metric) { - Metric previousMetric = registeredMetrics.putIfAbsent(name, metric); - - checkState(previousMetric == null, "Duplicate metric of same name: %s", name); - } -} diff --git a/java/google/registry/monitoring/metrics/MetricReporter.java b/java/google/registry/monitoring/metrics/MetricReporter.java deleted file mode 100644 index 58dcec00e..000000000 --- a/java/google/registry/monitoring/metrics/MetricReporter.java +++ /dev/null @@ -1,184 +0,0 @@ -// Copyright 2017 The Nomulus 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 static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.util.concurrent.MoreExecutors.directExecutor; - -import com.google.common.annotations.VisibleForTesting; -import com.google.common.collect.ImmutableList; -import com.google.common.util.concurrent.AbstractScheduledService; -import java.util.Optional; -import java.util.concurrent.ArrayBlockingQueue; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * Engine to write metrics to a {@link MetricWriter} on a regular periodic basis. - * - *

In the Producer/Consumer pattern, this class is the Producer and {@link MetricExporter} is the - * consumer. - */ -public class MetricReporter extends AbstractScheduledService { - - private static final Logger logger = Logger.getLogger(MetricReporter.class.getName()); - - private final long writeInterval; - private final MetricRegistry metricRegistry; - private final BlockingQueue>>> writeQueue; - private MetricExporter metricExporter; - private final MetricWriter metricWriter; - private final ThreadFactory threadFactory; - - /** - * Returns a new MetricReporter. - * - * @param metricWriter {@link MetricWriter} implementation to write metrics to. - * @param writeInterval time period between metric writes, in seconds. - * @param threadFactory factory to use when creating background threads. - */ - public MetricReporter( - MetricWriter metricWriter, long writeInterval, ThreadFactory threadFactory) { - this( - metricWriter, - writeInterval, - threadFactory, - MetricRegistryImpl.getDefault(), - new ArrayBlockingQueue<>(1000)); - } - - @VisibleForTesting - MetricReporter( - MetricWriter metricWriter, - long writeInterval, - ThreadFactory threadFactory, - MetricRegistry metricRegistry, - BlockingQueue>>> writeQueue) { - checkArgument(writeInterval > 0, "writeInterval must be greater than zero"); - - this.metricWriter = metricWriter; - this.writeInterval = writeInterval; - this.threadFactory = threadFactory; - this.metricRegistry = metricRegistry; - this.writeQueue = writeQueue; - this.metricExporter = new MetricExporter(writeQueue, metricWriter, threadFactory); - } - - @Override - protected void runOneIteration() { - logger.info("Running background metric push"); - - if (metricExporter.state() == State.FAILED) { - startMetricExporter(); - } - - ImmutableList.Builder> points = new ImmutableList.Builder<>(); - - /* - TODO(shikhman): Right now timestamps are recorded for each datapoint, which may use more storage - on the backend than if one timestamp were recorded for a batch. This should be configurable. - */ - for (Metric metric : metricRegistry.getRegisteredMetrics()) { - points.addAll(metric.getTimestampedValues()); - logger.fine(String.format("Enqueued metric %s", metric)); - MetricMetrics.pushedPoints.increment( - metric.getMetricSchema().kind().name(), metric.getValueClass().toString()); - } - - if (!writeQueue.offer(Optional.of(points.build()))) { - logger.severe("writeQueue full, dropped a reporting interval of points"); - } - - MetricMetrics.pushIntervals.increment(); - } - - @Override - protected void shutDown() { - // Make sure to run one iteration on shutdown so that short-lived programs still report at - // least once. - runOneIteration(); - - // Offer a poision pill to inform the exporter to stop. - writeQueue.offer(Optional.empty()); - try { - metricExporter.awaitTerminated(10, TimeUnit.SECONDS); - logger.info("Shut down MetricExporter"); - } catch (IllegalStateException exception) { - logger.log( - Level.SEVERE, - "Failed to shut down MetricExporter because it was FAILED", - metricExporter.failureCause()); - } catch (TimeoutException exception) { - logger.log(Level.SEVERE, "Failed to shut down MetricExporter within the timeout", exception); - } - } - - @Override - protected void startUp() { - startMetricExporter(); - } - - @Override - protected Scheduler scheduler() { - // Start writing after waiting for one writeInterval. - return Scheduler.newFixedDelaySchedule(writeInterval, writeInterval, TimeUnit.SECONDS); - } - - @Override - protected ScheduledExecutorService executor() { - final ScheduledExecutorService executor = - Executors.newSingleThreadScheduledExecutor(threadFactory); - // Make sure the ExecutorService terminates when this service does. - addListener( - new Listener() { - @Override - public void terminated(State from) { - executor.shutdown(); - } - - @Override - public void failed(State from, Throwable failure) { - executor.shutdown(); - } - }, - directExecutor()); - return executor; - } - - private void startMetricExporter() { - switch (metricExporter.state()) { - case NEW: - metricExporter.startAsync(); - break; - case FAILED: - logger.log( - Level.SEVERE, - "MetricExporter died unexpectedly, restarting", - metricExporter.failureCause()); - this.metricExporter = new MetricExporter(writeQueue, metricWriter, threadFactory); - this.metricExporter.startAsync(); - break; - default: - throw new IllegalStateException( - "MetricExporter not FAILED or NEW, should not be calling startMetricExporter"); - } - } -} diff --git a/java/google/registry/monitoring/metrics/MetricSchema.java b/java/google/registry/monitoring/metrics/MetricSchema.java deleted file mode 100644 index 5a732a023..000000000 --- a/java/google/registry/monitoring/metrics/MetricSchema.java +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright 2017 The Nomulus 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 static com.google.common.base.Preconditions.checkArgument; - -import com.google.auto.value.AutoValue; -import com.google.common.annotations.VisibleForTesting; -import com.google.common.collect.ImmutableSet; - -/** The description of a metric's schema. */ -@AutoValue -public abstract class MetricSchema { - - MetricSchema() {} - - /** - * Returns an instance of {@link MetricSchema}. - * - * @param name must have a URL-like hierarchical name, for example "/cpu/utilization". - * @param description a human readable description of the metric. Must not be blank. - * @param valueDisplayName a human readable description of the metric's value. Must not be blank. - * @param kind the kind of metric. - * @param labels an ordered set of mandatory metric labels. For example, a metric may track error - * code as a label. If labels are set, corresponding label values must be provided when values - * are set. The set of labels may be empty. - */ - @VisibleForTesting - public static MetricSchema create( - String name, - String description, - String valueDisplayName, - Kind kind, - ImmutableSet labels) { - checkArgument(!name.isEmpty(), "Name must not be blank"); - checkArgument(!description.isEmpty(), "Description must not be blank"); - checkArgument(!valueDisplayName.isEmpty(), "Value Display Name must not be empty"); - checkArgument(name.startsWith("/"), "Name must be URL-like and start with a '/'"); - // TODO(b/30916431): strengthen metric name validation. - - return new AutoValue_MetricSchema(name, description, valueDisplayName, kind, labels); - } - - public abstract String name(); - - public abstract String description(); - - public abstract String valueDisplayName(); - - public abstract Kind kind(); - - public abstract ImmutableSet labels(); - - /** - * The kind of metric. CUMULATIVE metrics have values relative to an initial value, and GAUGE - * metrics have values which are standalone. - */ - public enum Kind { - CUMULATIVE, - GAUGE, - } -} diff --git a/java/google/registry/monitoring/metrics/MetricWriter.java b/java/google/registry/monitoring/metrics/MetricWriter.java deleted file mode 100644 index 374b06ae7..000000000 --- a/java/google/registry/monitoring/metrics/MetricWriter.java +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2017 The Nomulus 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 java.io.Flushable; -import java.io.IOException; - -/** An interface for exporting Metrics. */ -public interface MetricWriter extends Flushable { - - /** - * Writes a {@link MetricPoint} to the writer's destination. - * - *

The write may be asynchronous. - * - * @throws IOException if the provided metric cannot be represented by the writer or if the metric - * cannot be flushed. - */ - void write(MetricPoint metricPoint) throws IOException; - - /** Forces the writer to synchronously write all buffered metric values. */ - @Override - void flush() throws IOException; -} diff --git a/java/google/registry/monitoring/metrics/MetricsUtils.java b/java/google/registry/monitoring/metrics/MetricsUtils.java deleted file mode 100644 index 1c3b27a41..000000000 --- a/java/google/registry/monitoring/metrics/MetricsUtils.java +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright 2017 The Nomulus 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 static com.google.common.base.Preconditions.checkArgument; - -import com.google.common.collect.ImmutableList; -import java.util.concurrent.ConcurrentHashMap; - -/** Static helper methods for the Metrics library. */ -final class MetricsUtils { - - private static final Double NEGATIVE_ZERO = -0.0; - private static final String LABEL_SIZE_ERROR = - "The count of labelValues must be equal to the underlying Metric's count of labels."; - - /** - * The below constants replicate the default initial capacity, load factor, and concurrency level - * for {@link ConcurrentHashMap} as of Java SE 7. They are recorded here so that a {@link - * com.google.common.util.concurrent.Striped} object can be constructed with a concurrency level - * matching the default concurrency level of a {@link ConcurrentHashMap}. - */ - private static final int HASHMAP_INITIAL_CAPACITY = 16; - private static final float HASHMAP_LOAD_FACTOR = 0.75f; - static final int DEFAULT_CONCURRENCY_LEVEL = 16; - - private MetricsUtils() {} - - /** - * Check that the given {@code labelValues} match in count with the count of {@link - * LabelDescriptor} instances on the given {@code metric} - * - * @throws IllegalArgumentException if there is a count mismatch. - */ - static void checkLabelValuesLength(Metric metric, String[] labelValues) { - checkArgument(labelValues.length == metric.getMetricSchema().labels().size(), LABEL_SIZE_ERROR); - } - - /** - * Check that the given {@code labelValues} match in count with the count of {@link - * LabelDescriptor} instances on the given {@code metric} - * - * @throws IllegalArgumentException if there is a count mismatch. - */ - static void checkLabelValuesLength(Metric metric, ImmutableList labelValues) { - checkArgument(labelValues.size() == metric.getMetricSchema().labels().size(), LABEL_SIZE_ERROR); - } - - /** Check that the given double is not infinite, {@code NaN}, or {@code -0.0}. */ - static void checkDouble(double value) { - checkArgument( - !Double.isInfinite(value) && !Double.isNaN(value) && !NEGATIVE_ZERO.equals(value), - "value must be finite, not NaN, and not -0.0"); - } - - static ConcurrentHashMap newConcurrentHashMap(int concurrencyLevel) { - return new ConcurrentHashMap<>(HASHMAP_INITIAL_CAPACITY, HASHMAP_LOAD_FACTOR, concurrencyLevel); - } -} diff --git a/java/google/registry/monitoring/metrics/MutableDistribution.java b/java/google/registry/monitoring/metrics/MutableDistribution.java deleted file mode 100644 index 932fd684e..000000000 --- a/java/google/registry/monitoring/metrics/MutableDistribution.java +++ /dev/null @@ -1,117 +0,0 @@ -// Copyright 2017 The Nomulus 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 static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; -import static google.registry.monitoring.metrics.MetricsUtils.checkDouble; - -import com.google.common.collect.ImmutableRangeMap; -import com.google.common.collect.ImmutableSortedSet; -import com.google.common.collect.Ordering; -import com.google.common.collect.Range; -import com.google.common.collect.TreeRangeMap; -import com.google.common.primitives.Doubles; -import java.util.Map; -import javax.annotation.concurrent.NotThreadSafe; - -/** - * A mutable {@link Distribution}. Instances of this class should not be used to construct - * {@link MetricPoint} instances as {@link MetricPoint} instances are supposed to represent - * immutable values. - * - * @see ImmutableDistribution - */ -@NotThreadSafe -public final class MutableDistribution implements Distribution { - - private final TreeRangeMap intervalCounts; - private final DistributionFitter distributionFitter; - private double sumOfSquaredDeviation = 0.0; - private double mean = 0.0; - private long count = 0; - - /** Constructs an empty Distribution with the specified {@link DistributionFitter}. */ - public MutableDistribution(DistributionFitter distributionFitter) { - this.distributionFitter = checkNotNull(distributionFitter); - ImmutableSortedSet boundaries = distributionFitter.boundaries(); - - checkArgument(boundaries.size() > 0); - checkArgument(Ordering.natural().isOrdered(boundaries)); - - this.intervalCounts = TreeRangeMap.create(); - - double[] boundariesArray = Doubles.toArray(distributionFitter.boundaries()); - - // Add underflow and overflow intervals - this.intervalCounts.put(Range.lessThan(boundariesArray[0]), 0L); - this.intervalCounts.put(Range.atLeast(boundariesArray[boundariesArray.length - 1]), 0L); - - // Add finite intervals - for (int i = 1; i < boundariesArray.length; i++) { - this.intervalCounts.put(Range.closedOpen(boundariesArray[i - 1], boundariesArray[i]), 0L); - } - } - - public void add(double value) { - add(value, 1L); - } - - public void add(double value, long numSamples) { - checkArgument(numSamples >= 0, "numSamples must be non-negative"); - checkDouble(value); - - // having numSamples = 0 works as expected (does nothing) even if we let it continue, but we - // can short-circuit it by returning early. - if (numSamples == 0) { - return; - } - - Map.Entry, Long> entry = intervalCounts.getEntry(value); - intervalCounts.put(entry.getKey(), entry.getValue() + numSamples); - this.count += numSamples; - - // Update mean and sumOfSquaredDeviation using Welford's method - // See Knuth, "The Art of Computer Programming", Vol. 2, page 232, 3rd edition - double delta = value - mean; - mean += delta * numSamples / count; - sumOfSquaredDeviation += delta * (value - mean) * numSamples; - } - - @Override - public double mean() { - return mean; - } - - @Override - public double sumOfSquaredDeviation() { - return sumOfSquaredDeviation; - } - - @Override - public long count() { - return count; - } - - @Override - public ImmutableRangeMap intervalCounts() { - return ImmutableRangeMap.copyOf(intervalCounts); - } - - @Override - public DistributionFitter distributionFitter() { - return distributionFitter; - } -} diff --git a/java/google/registry/monitoring/metrics/SettableMetric.java b/java/google/registry/monitoring/metrics/SettableMetric.java deleted file mode 100644 index 4bd6e2b82..000000000 --- a/java/google/registry/monitoring/metrics/SettableMetric.java +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2017 The Nomulus 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; - -/** A {@link Metric} which can be set to different values over time. */ -public interface SettableMetric extends Metric { - - /** - * Sets the metric's value for a given set of label values. The count of labelValues must equal to - * the underlying metric's count of labels. - */ - void set(V value, String... labelValues); -} diff --git a/java/google/registry/monitoring/metrics/StoredMetric.java b/java/google/registry/monitoring/metrics/StoredMetric.java deleted file mode 100644 index a531e5cdc..000000000 --- a/java/google/registry/monitoring/metrics/StoredMetric.java +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright 2017 The Nomulus 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.ImmutableList.Builder; -import com.google.common.collect.ImmutableSet; -import google.registry.monitoring.metrics.MetricSchema.Kind; -import java.util.Map.Entry; -import java.util.concurrent.ConcurrentHashMap; -import javax.annotation.concurrent.ThreadSafe; -import org.joda.time.Instant; - -/** - * A metric which is stateful. - * - *

The values are stored and set over time. This metric is generally suitable for state - * indicators, such as indicating that a server is in a RUNNING state or in a STOPPED state. - * - *

See {@link Counter} for a subclass which is suitable for stateful incremental values. - * - *

The {@link MetricPoint#interval()} of values of instances of this metric will always have a - * start time equal to the end time, since the metric value represents a point-in-time snapshot with - * no relationship to prior values. - */ -@ThreadSafe -public class StoredMetric extends AbstractMetric implements SettableMetric { - - private final ConcurrentHashMap, V> values = new ConcurrentHashMap<>(); - - StoredMetric( - String name, - String description, - String valueDisplayName, - ImmutableSet labels, - Class valueClass) { - super(name, description, valueDisplayName, Kind.GAUGE, labels, valueClass); - } - - @VisibleForTesting - final void set(V value, ImmutableList labelValues) { - this.values.put(labelValues, value); - } - - @Override - public final void set(V value, String... labelValues) { - MetricsUtils.checkLabelValuesLength(this, labelValues); - - set(value, ImmutableList.copyOf(labelValues)); - } - - /** - * Returns a snapshot of the metric's values. The timestamp of each MetricPoint will be the last - * modification time for that tuple of label values. - */ - @Override - public final ImmutableList> getTimestampedValues() { - return getTimestampedValues(Instant.now()); - } - - @Override - public final int getCardinality() { - return values.size(); - } - - @VisibleForTesting - final ImmutableList> getTimestampedValues(Instant timestamp) { - ImmutableList.Builder> timestampedValues = new Builder<>(); - for (Entry, V> entry : values.entrySet()) { - timestampedValues.add( - MetricPoint.create(this, entry.getKey(), timestamp, timestamp, entry.getValue())); - } - - return timestampedValues.build(); - } -} diff --git a/java/google/registry/monitoring/metrics/VirtualMetric.java b/java/google/registry/monitoring/metrics/VirtualMetric.java deleted file mode 100644 index 80b4f6ea7..000000000 --- a/java/google/registry/monitoring/metrics/VirtualMetric.java +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright 2017 The Nomulus 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.base.Supplier; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; -import google.registry.monitoring.metrics.MetricSchema.Kind; -import java.util.Map.Entry; -import javax.annotation.concurrent.ThreadSafe; -import org.joda.time.Instant; - -/** - * A metric whose value is computed at sample-time. - * - *

This pattern works well for gauge-like metrics, such as CPU usage, memory usage, and file - * descriptor counts. - * - *

The {@link MetricPoint#interval()} of values of instances of this metric will always have a - * start time equal to the end time, since the metric value represents a point-in-time snapshot with - * no relationship to prior values. - */ -@ThreadSafe -public final class VirtualMetric extends AbstractMetric { - - private final Supplier, V>> valuesSupplier; - - /** - * Local cache of the count of values so that we don't have to evaluate the callback function to - * get the metric's cardinality. - */ - private volatile int cardinality; - - VirtualMetric( - String name, - String description, - String valueDisplayName, - ImmutableSet labels, - Supplier, V>> valuesSupplier, - Class valueClass) { - super(name, description, valueDisplayName, Kind.GAUGE, labels, valueClass); - - this.valuesSupplier = valuesSupplier; - } - - /** - * Returns a snapshot of the metric's values. This will evaluate the stored callback function. The - * timestamp for each MetricPoint will be the current time. - */ - @Override - public ImmutableList> getTimestampedValues() { - return getTimestampedValues(Instant.now()); - } - - /** - * Returns the cached value of the cardinality of this metric. The cardinality is computed when - * the metric is evaluated. If the metric has never been evaluated, the cardinality is zero. - */ - @Override - public int getCardinality() { - return cardinality; - } - - @VisibleForTesting - ImmutableList> getTimestampedValues(Instant timestamp) { - ImmutableMap, V> values = valuesSupplier.get(); - - ImmutableList.Builder> metricPoints = new ImmutableList.Builder<>(); - for (Entry, V> entry : values.entrySet()) { - metricPoints.add( - MetricPoint.create(this, entry.getKey(), timestamp, timestamp, entry.getValue())); - } - - cardinality = values.size(); - return metricPoints.build(); - } -} diff --git a/java/google/registry/monitoring/metrics/contrib/AbstractMetricSubject.java b/java/google/registry/monitoring/metrics/contrib/AbstractMetricSubject.java deleted file mode 100644 index 6a39fdb9d..000000000 --- a/java/google/registry/monitoring/metrics/contrib/AbstractMetricSubject.java +++ /dev/null @@ -1,213 +0,0 @@ -// Copyright 2017 The Nomulus 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.contrib; - -import static com.google.common.base.Preconditions.checkNotNull; -import static com.google.common.collect.ImmutableList.toImmutableList; - -import com.google.common.base.Joiner; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.Ordering; -import com.google.common.truth.FailureMetadata; -import com.google.common.truth.Subject; -import google.registry.monitoring.metrics.Metric; -import google.registry.monitoring.metrics.MetricPoint; -import java.util.HashSet; -import java.util.Set; -import javax.annotation.Nullable; - -/** - * Base truth subject for asserting things about {@link Metric} instances. - * - *

For use with the Google Truth framework. - */ -abstract class AbstractMetricSubject> - extends Subject> { - - /** And chainer to allow fluent assertions. */ - public static class And> { - - private final S subject; - - And(S subject) { - this.subject = subject; - } - - public S and() { - return subject; - } - } - - @SuppressWarnings("unchecked") - And andChainer() { - return new And<>((S) this); - } - - /** - * List of label value tuples about which an assertion has been made so far. - * - *

Used to track what tuples have been seen, in order to support hasNoOtherValues() assertions. - */ - protected final Set> expectedNondefaultLabelTuples = new HashSet<>(); - - /** Converts a metric point to a nice string representation for use in error messages. */ - protected String convertMetricPoint(MetricPoint metricPoint) { - return String.format( - "%s => %s", - Joiner.on(':').join(metricPoint.labelValues()), - getMessageRepresentation(metricPoint.value())); - } - - protected AbstractMetricSubject(FailureMetadata metadata, Metric actual) { - super(metadata, checkNotNull(actual)); - } - - /** - * Returns the string representation of the subject. - * - *

For metrics, it makes sense to use the metric name, as given in the schema. - */ - @Override - public String actualCustomStringRepresentation() { - return actual().getMetricSchema().name(); - } - - /** - * Asserts that the metric has a given value for the specified label values. - * - * @param value the value which the metric should have - * @param labels the labels for which the value is being asserted; the number and order of labels - * should match the definition of the metric - */ - public And hasValueForLabels(T value, String... labels) { - MetricPoint metricPoint = findMetricPointForLabels(ImmutableList.copyOf(labels)); - if (metricPoint == null) { - failWithBadResults( - "has a value for labels", - Joiner.on(':').join(labels), - "has labeled values", - Ordering.>natural() - .sortedCopy(actual().getTimestampedValues()) - .stream() - .map(this::convertMetricPoint) - .collect(toImmutableList())); - } - if (!metricPoint.value().equals(value)) { - failWithBadResults( - String.format("has a value of %s for labels", getMessageRepresentation(value)), - Joiner.on(':').join(labels), - "has a value of", - getMessageRepresentation(metricPoint.value())); - } - expectedNondefaultLabelTuples.add(ImmutableList.copyOf(labels)); - return andChainer(); - } - - /** - * Asserts that the metric has any (non-default) value for the specified label values. - * - * @param labels the labels for which the value is being asserted; the number and order of labels - * should match the definition of the metric - */ - public And hasAnyValueForLabels(String... labels) { - MetricPoint metricPoint = findMetricPointForLabels(ImmutableList.copyOf(labels)); - if (metricPoint == null) { - failWithBadResults( - "has a value for labels", - Joiner.on(':').join(labels), - "has labeled values", - Ordering.>natural() - .sortedCopy(actual().getTimestampedValues()) - .stream() - .map(this::convertMetricPoint) - .collect(toImmutableList())); - } - if (hasDefaultValue(metricPoint)) { - failWithBadResults( - "has a non-default value for labels", - Joiner.on(':').join(labels), - "has a value of", - getMessageRepresentation(metricPoint.value())); - } - expectedNondefaultLabelTuples.add(ImmutableList.copyOf(labels)); - return andChainer(); - } - - /** Asserts that the metric does not have a (non-default) value for the specified label values. */ - protected And doesNotHaveAnyValueForLabels(String... labels) { - MetricPoint metricPoint = findMetricPointForLabels(ImmutableList.copyOf(labels)); - if (metricPoint != null) { - failWithBadResults( - "has no value for labels", - Joiner.on(':').join(labels), - "has a value of", - getMessageRepresentation(metricPoint.value())); - } - return andChainer(); - } - - /** - * Asserts that the metric has no (non-default) values other than those about which an assertion - * has already been made. - */ - public And hasNoOtherValues() { - for (MetricPoint metricPoint : actual().getTimestampedValues()) { - if (!expectedNondefaultLabelTuples.contains(metricPoint.labelValues())) { - if (!hasDefaultValue(metricPoint)) { - failWithBadResults( - "has", - "no other nondefault values", - "has labeled values", - Ordering.>natural() - .sortedCopy(actual().getTimestampedValues()) - .stream() - .map(this::convertMetricPoint) - .collect(toImmutableList())); - } - return andChainer(); - } - } - return andChainer(); - } - - private @Nullable MetricPoint findMetricPointForLabels(ImmutableList labels) { - if (actual().getMetricSchema().labels().size() != labels.size()) { - return null; - } - for (MetricPoint metricPoint : actual().getTimestampedValues()) { - if (metricPoint.labelValues().equals(labels)) { - return metricPoint; - } - } - return null; - } - - /** - * Returns a string representation of a metric point value, for use in error messages. - * - *

Subclass can override this method if the string needs extra processing. - */ - protected String getMessageRepresentation(T value) { - return String.valueOf(value); - } - - /** - * Returns true if the metric point has a non-default value. - * - *

This should be overridden by subclasses. E.g. for incrementable metrics, the method should - * return true if the value is not zero, and so on. - */ - protected abstract boolean hasDefaultValue(MetricPoint metricPoint); -} diff --git a/java/google/registry/monitoring/metrics/contrib/BUILD b/java/google/registry/monitoring/metrics/contrib/BUILD deleted file mode 100644 index 0a10857cd..000000000 --- a/java/google/registry/monitoring/metrics/contrib/BUILD +++ /dev/null @@ -1,18 +0,0 @@ -package( - default_testonly = 1, - default_visibility = ["//visibility:public"], -) - -licenses(["notice"]) # Apache 2.0 - -java_library( - name = "contrib", - srcs = glob(["*.java"]), - deps = [ - "//java/google/registry/monitoring/metrics", - "@com_google_code_findbugs_jsr305", - "@com_google_guava", - "@com_google_truth", - "@com_google_truth_extensions_truth_java8_extension", - ], -) diff --git a/java/google/registry/monitoring/metrics/contrib/DistributionMetricSubject.java b/java/google/registry/monitoring/metrics/contrib/DistributionMetricSubject.java deleted file mode 100644 index 635d64539..000000000 --- a/java/google/registry/monitoring/metrics/contrib/DistributionMetricSubject.java +++ /dev/null @@ -1,125 +0,0 @@ -// Copyright 2017 The Nomulus 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.contrib; - -import static com.google.common.truth.Truth.assertAbout; - -import com.google.common.base.Joiner; -import com.google.common.collect.BoundType; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Range; -import com.google.common.truth.FailureMetadata; -import google.registry.monitoring.metrics.Distribution; -import google.registry.monitoring.metrics.ImmutableDistribution; -import google.registry.monitoring.metrics.Metric; -import google.registry.monitoring.metrics.MetricPoint; -import google.registry.monitoring.metrics.MutableDistribution; -import java.util.Map; -import javax.annotation.Nullable; - -/** - * Truth subject for the {@link Metric} class. - * - *

For use with the Google Truth framework. Usage: - * - *

  assertThat(myDistributionMetric)
- *       .hasAnyValueForLabels("label1", "label2", "label3")
- *       .and()
- *       .hasNoOtherValues();
- *   assertThat(myDistributionMetric)
- *       .doesNotHaveAnyValueForLabels("label1", "label2");
- *   assertThat(myDistributionMetric)
- *       .hasDataSetForLabels(ImmutableSet.of(data1, data2, data3), "label1", "label2");
- * 
- * - *

The assertions treat an empty distribution as no value at all. This is not how the data is - * actually stored; event metrics do in fact have an empty distribution after they are reset. But - * it's difficult to write assertions about expected metric data when any number of empty - * distributions can also be present, so they are screened out for convenience. - */ -public final class DistributionMetricSubject - extends AbstractMetricSubject { - - /** {@link Subject.Factory} for assertions about {@link Metric} objects. */ - /** Static assertThat({@link Metric}) shortcut method. */ - public static DistributionMetricSubject assertThat(@Nullable Metric metric) { - return assertAbout(DistributionMetricSubject::new).that(metric); - } - - private DistributionMetricSubject(FailureMetadata metadata, Metric actual) { - super(metadata, actual); - } - - /** - * Returns an indication to {@link AbstractMetricSubject#hasNoOtherValues} on whether a {@link - * MetricPoint} has a non-empty distribution. - */ - @Override - protected boolean hasDefaultValue(MetricPoint metricPoint) { - return metricPoint.value().count() == 0; - } - - /** Returns an appropriate string representation of a metric value for use in error messages. */ - @Override - protected String getMessageRepresentation(Distribution distribution) { - StringBuilder sb = new StringBuilder("{"); - boolean first = true; - for (Map.Entry, Long> entry : - distribution.intervalCounts().asMapOfRanges().entrySet()) { - if (entry.getValue() != 0L) { - if (first) { - first = false; - } else { - sb.append(','); - } - if (entry.getKey().hasLowerBound()) { - sb.append((entry.getKey().lowerBoundType() == BoundType.CLOSED) ? '[' : '('); - sb.append(entry.getKey().lowerEndpoint()); - } - sb.append(".."); - if (entry.getKey().hasUpperBound()) { - sb.append(entry.getKey().upperEndpoint()); - sb.append((entry.getKey().upperBoundType() == BoundType.CLOSED) ? ']' : ')'); - } - sb.append('='); - sb.append(entry.getValue()); - } - } - sb.append('}'); - return sb.toString(); - } - - /** - * Asserts that the distribution for the given label can be constructed from the given data set. - * - *

Note that this only tests that the distribution has the same binned histogram, along with - * the same mean, and sum of squared deviation as it would if it had recorded the specified data - * points. It could have in fact collected different data points that resulted in the same - * distribution, but that information is lost to us and cannot be tested. - */ - public And hasDataSetForLabels( - ImmutableSet dataSet, String... labels) { - ImmutableList> metricPoints = actual().getTimestampedValues(); - if (metricPoints.isEmpty()) { - failWithBadResults( - "has a distribution for labels", Joiner.on(':').join(labels), "has", "no values"); - } - MutableDistribution targetDistribution = - new MutableDistribution(metricPoints.get(0).value().distributionFitter()); - dataSet.forEach(data -> targetDistribution.add(data.doubleValue())); - return hasValueForLabels(ImmutableDistribution.copyOf(targetDistribution), labels); - } -} diff --git a/java/google/registry/monitoring/metrics/contrib/LongMetricSubject.java b/java/google/registry/monitoring/metrics/contrib/LongMetricSubject.java deleted file mode 100644 index fa0a82182..000000000 --- a/java/google/registry/monitoring/metrics/contrib/LongMetricSubject.java +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright 2017 The Nomulus 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.contrib; - -import static com.google.common.truth.Truth.assertAbout; - -import com.google.common.truth.FailureMetadata; -import com.google.common.truth.Subject; -import google.registry.monitoring.metrics.Metric; -import google.registry.monitoring.metrics.MetricPoint; -import javax.annotation.Nullable; - -/** - * Truth subject for the {@link Metric} class. - * - *

For use with the Google Truth framework. Usage: - * - *

  assertThat(myLongMetric)
- *       .hasValueForLabels(5, "label1", "label2", "label3")
- *       .and()
- *       .hasAnyValueForLabels("label1", "label2", "label4")
- *       .and()
- *       .hasNoOtherValues();
- *   assertThat(myLongMetric)
- *       .doesNotHaveAnyValueForLabels("label1", "label2");
- * 
- * - *

The assertions treat a value of 0 as no value at all. This is not how the data is actually - * stored; zero is a valid value for incrementable metrics, and they do in fact have a value of zero - * after they are reset. But it's difficult to write assertions about expected metric data when any - * number of zero values can also be present, so they are screened out for convenience. - */ -public final class LongMetricSubject extends AbstractMetricSubject { - - /** - * Static assertThat({@link Metric}) shortcut method. - * - * @see Subject.Factory for assertions about {@link Metric} objects. - */ - public static LongMetricSubject assertThat(@Nullable Metric metric) { - return assertAbout(LongMetricSubject::new).that(metric); - } - - private LongMetricSubject(FailureMetadata metadata, Metric actual) { - super(metadata, actual); - } - - /** - * Asserts that the metric has a given value for the specified label values. This is a convenience - * method that takes a long instead of a Long, for ease of use. - */ - public And hasValueForLabels(long value, String... labels) { - return hasValueForLabels(Long.valueOf(value), labels); - } - - /** - * Returns an indication to {@link AbstractMetricSubject#hasNoOtherValues} on whether a {@link - * MetricPoint} has a non-zero value. - */ - @Override - protected boolean hasDefaultValue(MetricPoint metricPoint) { - return metricPoint.value() == 0L; - } -} diff --git a/java/google/registry/monitoring/metrics/package-info.java b/java/google/registry/monitoring/metrics/package-info.java deleted file mode 100644 index 599872b25..000000000 --- a/java/google/registry/monitoring/metrics/package-info.java +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2017 The Nomulus 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. - -@javax.annotation.ParametersAreNonnullByDefault -package google.registry.monitoring.metrics; diff --git a/java/google/registry/monitoring/metrics/stackdriver/BUILD b/java/google/registry/monitoring/metrics/stackdriver/BUILD deleted file mode 100644 index dca3fbe57..000000000 --- a/java/google/registry/monitoring/metrics/stackdriver/BUILD +++ /dev/null @@ -1,24 +0,0 @@ -package( - default_visibility = ["//visibility:public"], -) - -licenses(["notice"]) # Apache 2.0 - -java_library( - name = "stackdriver", - srcs = glob(["*.java"]), - deps = [ - "//java/google/registry/monitoring/metrics", - "@com_google_api_client", - "@com_google_apis_google_api_services_monitoring", - "@com_google_appengine_api_1_0_sdk", - "@com_google_auto_value", - "@com_google_code_findbugs_jsr305", - "@com_google_dagger", - "@com_google_errorprone_error_prone_annotations", - "@com_google_guava", - "@com_google_http_client", - "@com_google_re2j", - "@joda_time", - ], -) diff --git a/java/google/registry/monitoring/metrics/stackdriver/StackdriverWriter.java b/java/google/registry/monitoring/metrics/stackdriver/StackdriverWriter.java deleted file mode 100644 index 8bc7275e2..000000000 --- a/java/google/registry/monitoring/metrics/stackdriver/StackdriverWriter.java +++ /dev/null @@ -1,405 +0,0 @@ -// Copyright 2017 The Nomulus 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.stackdriver; - -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; -import static com.google.common.base.Preconditions.checkState; - -import com.google.api.client.googleapis.json.GoogleJsonResponseException; -import com.google.api.services.monitoring.v3.Monitoring; -import com.google.api.services.monitoring.v3.model.BucketOptions; -import com.google.api.services.monitoring.v3.model.CreateTimeSeriesRequest; -import com.google.api.services.monitoring.v3.model.Distribution; -import com.google.api.services.monitoring.v3.model.Explicit; -import com.google.api.services.monitoring.v3.model.Exponential; -import com.google.api.services.monitoring.v3.model.LabelDescriptor; -import com.google.api.services.monitoring.v3.model.Linear; -import com.google.api.services.monitoring.v3.model.Metric; -import com.google.api.services.monitoring.v3.model.MetricDescriptor; -import com.google.api.services.monitoring.v3.model.MonitoredResource; -import com.google.api.services.monitoring.v3.model.Point; -import com.google.api.services.monitoring.v3.model.TimeInterval; -import com.google.api.services.monitoring.v3.model.TimeSeries; -import com.google.api.services.monitoring.v3.model.TypedValue; -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Joiner; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; -import com.google.common.util.concurrent.RateLimiter; -import google.registry.monitoring.metrics.CustomFitter; -import google.registry.monitoring.metrics.DistributionFitter; -import google.registry.monitoring.metrics.ExponentialFitter; -import google.registry.monitoring.metrics.IncrementableMetric; -import google.registry.monitoring.metrics.LinearFitter; -import google.registry.monitoring.metrics.MetricPoint; -import google.registry.monitoring.metrics.MetricRegistryImpl; -import google.registry.monitoring.metrics.MetricSchema.Kind; -import google.registry.monitoring.metrics.MetricWriter; -import java.io.IOException; -import java.util.ArrayDeque; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Queue; -import java.util.logging.Logger; -import javax.annotation.concurrent.NotThreadSafe; -import org.joda.time.DateTime; -import org.joda.time.Interval; -import org.joda.time.format.DateTimeFormatter; -import org.joda.time.format.ISODateTimeFormat; - -/** - * Metrics writer for Google Cloud Monitoring V3 - * - *

This class communicates with the API via HTTP. In order to increase throughput and minimize - * CPU, it buffers points to be written until it has {@code maxPointsPerRequest} points buffered or - * until {@link #flush()} is called. - * - * @see Introduction to the Stackdriver - * Monitoring API - */ -// TODO(shikhman): add retry logic -@NotThreadSafe -public class StackdriverWriter implements MetricWriter { - - /** - * A counter representing the total number of points pushed. Has {@link Kind} and metric value - * types as labels. - */ - private static final IncrementableMetric pushedPoints = - MetricRegistryImpl.getDefault() - .newIncrementableMetric( - "/metrics/stackdriver/points_pushed", - "Count of points pushed to Stackdriver Monitoring API.", - "Points Pushed", - ImmutableSet.of( - google.registry.monitoring.metrics.LabelDescriptor.create("kind", "Metric Kind"), - google.registry.monitoring.metrics.LabelDescriptor.create( - "valueType", "Metric Value Type"))); - private static final String METRIC_DOMAIN = "custom.googleapis.com"; - private static final String LABEL_VALUE_TYPE = "STRING"; - private static final DateTimeFormatter DATETIME_FORMATTER = ISODateTimeFormat.dateTime(); - private static final Logger logger = Logger.getLogger(StackdriverWriter.class.getName()); - // A map of native type to the equivalent Stackdriver metric type. - private static final ImmutableMap, String> ENCODED_METRIC_TYPES = - new ImmutableMap.Builder, String>() - .put(Long.class, "INT64") - .put(Double.class, "DOUBLE") - .put(Boolean.class, "BOOL") - .put(String.class, "STRING") - .put(google.registry.monitoring.metrics.Distribution.class, "DISTRIBUTION") - .build(); - // A map of native kind to the equivalent Stackdriver metric kind. - private static final ImmutableMap ENCODED_METRIC_KINDS = - new ImmutableMap.Builder() - .put(Kind.GAUGE.name(), "GAUGE") - .put(Kind.CUMULATIVE.name(), "CUMULATIVE") - .build(); - private static final String FLUSH_OVERFLOW_ERROR = "Cannot flush more than 200 points at a time"; - private static final String METRIC_KIND_ERROR = - "Unrecognized metric kind, must be one of " - + Joiner.on(",").join(ENCODED_METRIC_KINDS.keySet()); - private static final String METRIC_TYPE_ERROR = - "Unrecognized metric type, must be one of " - + Joiner.on(" ").join(ENCODED_METRIC_TYPES.keySet()); - private static final String METRIC_LABEL_COUNT_ERROR = - "Metric label value count does not match its MetricDescriptor's label count"; - - private final MonitoredResource monitoredResource; - private final Queue timeSeriesBuffer; - /** - * A local cache of MetricDescriptors. A metric's metadata (name, kind, type, label definitions) - * must be registered before points for the metric can be pushed. - */ - private final HashMap, MetricDescriptor> - registeredDescriptors = new HashMap<>(); - private final String projectResource; - private final Monitoring monitoringClient; - private final int maxPointsPerRequest; - private final RateLimiter rateLimiter; - - /** - * Constructs a {@link StackdriverWriter}. - * - *

The monitoringClient must have read and write permissions to the Cloud Monitoring API v3 on - * the provided project. - */ - public StackdriverWriter( - Monitoring monitoringClient, - String project, - MonitoredResource monitoredResource, - int maxQps, - int maxPointsPerRequest) { - this.monitoringClient = checkNotNull(monitoringClient); - this.projectResource = "projects/" + checkNotNull(project); - this.monitoredResource = monitoredResource; - this.maxPointsPerRequest = maxPointsPerRequest; - this.timeSeriesBuffer = new ArrayDeque<>(maxPointsPerRequest); - this.rateLimiter = RateLimiter.create(maxQps); - } - - @VisibleForTesting - static ImmutableList encodeLabelDescriptors( - ImmutableSet labelDescriptors) { - List stackDriverLabelDescriptors = new ArrayList<>(labelDescriptors.size()); - - for (google.registry.monitoring.metrics.LabelDescriptor labelDescriptor : labelDescriptors) { - stackDriverLabelDescriptors.add( - new LabelDescriptor() - .setKey(labelDescriptor.name()) - .setDescription(labelDescriptor.description()) - .setValueType(LABEL_VALUE_TYPE)); - } - - return ImmutableList.copyOf(stackDriverLabelDescriptors); - } - - @VisibleForTesting - static MetricDescriptor encodeMetricDescriptor( - google.registry.monitoring.metrics.Metric metric) { - return new MetricDescriptor() - .setType(METRIC_DOMAIN + metric.getMetricSchema().name()) - .setDescription(metric.getMetricSchema().description()) - .setDisplayName(metric.getMetricSchema().valueDisplayName()) - .setValueType(ENCODED_METRIC_TYPES.get(metric.getValueClass())) - .setLabels(encodeLabelDescriptors(metric.getMetricSchema().labels())) - .setMetricKind(ENCODED_METRIC_KINDS.get(metric.getMetricSchema().kind().name())); - } - - /** Encodes and writes a metric point to Stackdriver. The point may be buffered. */ - @Override - public void write(google.registry.monitoring.metrics.MetricPoint point) - throws IOException { - checkNotNull(point); - - TimeSeries timeSeries = getEncodedTimeSeries(point); - timeSeriesBuffer.add(timeSeries); - - logger.fine(String.format("Enqueued metric %s for writing", timeSeries.getMetric().getType())); - if (timeSeriesBuffer.size() == maxPointsPerRequest) { - flush(); - } - } - - /** Flushes all buffered metric points to Stackdriver. This call is blocking. */ - @Override - public void flush() throws IOException { - checkState(timeSeriesBuffer.size() <= 200, FLUSH_OVERFLOW_ERROR); - - // Return early; Stackdriver throws errors if we attempt to send empty requests. - if (timeSeriesBuffer.isEmpty()) { - logger.fine("Attempted to flush with no pending points, doing nothing"); - return; - } - - ImmutableList timeSeriesList = ImmutableList.copyOf(timeSeriesBuffer); - timeSeriesBuffer.clear(); - - CreateTimeSeriesRequest request = new CreateTimeSeriesRequest().setTimeSeries(timeSeriesList); - - rateLimiter.acquire(); - monitoringClient.projects().timeSeries().create(projectResource, request).execute(); - - for (TimeSeries timeSeries : timeSeriesList) { - pushedPoints.increment(timeSeries.getMetricKind(), timeSeries.getValueType()); - } - logger.info(String.format("Flushed %d metrics to Stackdriver", timeSeriesList.size())); - } - - /** - * Registers a metric's {@link MetricDescriptor} with the Monitoring API. - * - * @param metric the metric to be registered. - * @see Stackdriver MetricDescriptor API - */ - @VisibleForTesting - MetricDescriptor registerMetric(final google.registry.monitoring.metrics.Metric metric) - throws IOException { - if (registeredDescriptors.containsKey(metric)) { - logger.fine( - String.format("Using existing metric descriptor %s", metric.getMetricSchema().name())); - return registeredDescriptors.get(metric); - } - - MetricDescriptor descriptor = encodeMetricDescriptor(metric); - - rateLimiter.acquire(); - // We try to create a descriptor, but it may have been created already, so we re-fetch it on - // failure - try { - descriptor = - monitoringClient - .projects() - .metricDescriptors() - .create(projectResource, descriptor) - .execute(); - logger.info(String.format("Registered new metric descriptor %s", descriptor.getType())); - } catch (GoogleJsonResponseException jsonException) { - // Not the error we were expecting, just give up - if (!"ALREADY_EXISTS".equals(jsonException.getStatusMessage())) { - throw jsonException; - } - - descriptor = - monitoringClient - .projects() - .metricDescriptors() - .get(projectResource + "/metricDescriptors/" + descriptor.getType()) - .execute(); - - logger.info( - String.format("Fetched existing metric descriptor %s", metric.getMetricSchema().name())); - } - - registeredDescriptors.put(metric, descriptor); - - return descriptor; - } - - private static TimeInterval encodeTimeInterval(Interval nativeInterval, Kind metricKind) { - - TimeInterval encodedInterval = - new TimeInterval().setStartTime(DATETIME_FORMATTER.print(nativeInterval.getStart())); - - DateTime endTimestamp = - nativeInterval.toDurationMillis() == 0 && metricKind != Kind.GAUGE - ? nativeInterval.getEnd().plusMillis(1) - : nativeInterval.getEnd(); - - return encodedInterval.setEndTime(DATETIME_FORMATTER.print(endTimestamp)); - } - - private static BucketOptions encodeBucketOptions(DistributionFitter fitter) { - BucketOptions bucketOptions = new BucketOptions(); - - if (fitter instanceof LinearFitter) { - LinearFitter linearFitter = (LinearFitter) fitter; - - bucketOptions.setLinearBuckets( - new Linear() - .setNumFiniteBuckets(linearFitter.boundaries().size() - 1) - .setWidth(linearFitter.width()) - .setOffset(linearFitter.offset())); - } else if (fitter instanceof ExponentialFitter) { - ExponentialFitter exponentialFitter = (ExponentialFitter) fitter; - - bucketOptions.setExponentialBuckets( - new Exponential() - .setNumFiniteBuckets(exponentialFitter.boundaries().size() - 1) - .setGrowthFactor(exponentialFitter.base()) - .setScale(exponentialFitter.scale())); - } else if (fitter instanceof CustomFitter) { - bucketOptions.setExplicitBuckets(new Explicit().setBounds(fitter.boundaries().asList())); - } else { - throw new IllegalArgumentException("Illegal DistributionFitter type"); - } - - return bucketOptions; - } - - private static List encodeDistributionPoints( - google.registry.monitoring.metrics.Distribution distribution) { - return distribution.intervalCounts().asMapOfRanges().values().asList(); - } - - private static Distribution encodeDistribution( - google.registry.monitoring.metrics.Distribution nativeDistribution) { - return new Distribution() - .setMean(nativeDistribution.mean()) - .setCount(nativeDistribution.count()) - .setSumOfSquaredDeviation(nativeDistribution.sumOfSquaredDeviation()) - .setBucketOptions(encodeBucketOptions(nativeDistribution.distributionFitter())) - .setBucketCounts(encodeDistributionPoints(nativeDistribution)); - } - - /** - * Encodes a {@link MetricPoint} into a Stackdriver {@link TimeSeries}. - * - *

This method will register the underlying {@link google.registry.monitoring.metrics.Metric} - * as a Stackdriver {@link MetricDescriptor}. - * - * @see - * Stackdriver TimeSeries API - */ - @VisibleForTesting - TimeSeries getEncodedTimeSeries(google.registry.monitoring.metrics.MetricPoint point) - throws IOException { - google.registry.monitoring.metrics.Metric metric = point.metric(); - try { - checkArgument( - ENCODED_METRIC_KINDS.containsKey(metric.getMetricSchema().kind().name()), - METRIC_KIND_ERROR); - checkArgument(ENCODED_METRIC_TYPES.containsKey(metric.getValueClass()), METRIC_TYPE_ERROR); - } catch (IllegalArgumentException e) { - throw new IOException(e.getMessage()); - } - - MetricDescriptor descriptor = registerMetric(metric); - - if (point.labelValues().size() != point.metric().getMetricSchema().labels().size()) { - throw new IOException(METRIC_LABEL_COUNT_ERROR); - } - - V value = point.value(); - TypedValue encodedValue = new TypedValue(); - Class valueClass = metric.getValueClass(); - - if (valueClass == Long.class) { - encodedValue.setInt64Value((Long) value); - } else if (valueClass == Double.class) { - encodedValue.setDoubleValue((Double) value); - } else if (valueClass == Boolean.class) { - encodedValue.setBoolValue((Boolean) value); - } else if (valueClass == String.class) { - encodedValue.setStringValue((String) value); - } else if (valueClass == google.registry.monitoring.metrics.Distribution.class) { - encodedValue.setDistributionValue( - encodeDistribution((google.registry.monitoring.metrics.Distribution) value)); - } else { - // This is unreachable because the precondition checks will catch all NotSerializable - // exceptions. - throw new IllegalArgumentException("Invalid metric valueClass: " + metric.getValueClass()); - } - - Point encodedPoint = - new Point() - .setInterval(encodeTimeInterval(point.interval(), metric.getMetricSchema().kind())) - .setValue(encodedValue); - - List encodedLabels = descriptor.getLabels(); - // The MetricDescriptors returned by the GCM API have null fields rather than empty lists - encodedLabels = encodedLabels == null ? ImmutableList.of() : encodedLabels; - - ImmutableMap.Builder labelValues = new ImmutableMap.Builder<>(); - int i = 0; - for (LabelDescriptor labelDescriptor : encodedLabels) { - labelValues.put(labelDescriptor.getKey(), point.labelValues().get(i++)); - } - - Metric encodedMetric = - new Metric().setType(descriptor.getType()).setLabels(labelValues.build()); - - return new TimeSeries() - .setMetric(encodedMetric) - .setPoints(ImmutableList.of(encodedPoint)) - .setResource(monitoredResource) - // these two attributes are ignored by the API, we set them here to use elsewhere - // for internal metrics. - .setMetricKind(descriptor.getMetricKind()) - .setValueType(descriptor.getValueType()); - } -} diff --git a/java/google/registry/monitoring/whitebox/BUILD b/java/google/registry/monitoring/whitebox/BUILD index 2fcefebe3..a32572d68 100644 --- a/java/google/registry/monitoring/whitebox/BUILD +++ b/java/google/registry/monitoring/whitebox/BUILD @@ -11,8 +11,6 @@ java_library( "//java/google/registry/bigquery", "//java/google/registry/config", "//java/google/registry/model", - "//java/google/registry/monitoring/metrics", - "//java/google/registry/monitoring/metrics/stackdriver", "//java/google/registry/request", "//java/google/registry/request/auth", "//java/google/registry/util", @@ -26,6 +24,8 @@ java_library( "@com_google_dagger", "@com_google_guava", "@com_google_http_client", + "@com_google_monitoring_client_metrics", + "@com_google_monitoring_client_stackdriver", "@javax_servlet_api", "@joda_time", ], diff --git a/java/google/registry/monitoring/whitebox/StackdriverModule.java b/java/google/registry/monitoring/whitebox/StackdriverModule.java index 889c094cc..6cee68028 100644 --- a/java/google/registry/monitoring/whitebox/StackdriverModule.java +++ b/java/google/registry/monitoring/whitebox/StackdriverModule.java @@ -23,12 +23,12 @@ import com.google.api.services.monitoring.v3.model.MonitoredResource; import com.google.appengine.api.modules.ModulesService; import com.google.common.collect.ImmutableMap; import com.google.common.util.concurrent.ThreadFactoryBuilder; +import com.google.monitoring.metrics.MetricReporter; +import com.google.monitoring.metrics.MetricWriter; +import com.google.monitoring.metrics.stackdriver.StackdriverWriter; import dagger.Module; import dagger.Provides; import google.registry.config.RegistryConfig.Config; -import google.registry.monitoring.metrics.MetricReporter; -import google.registry.monitoring.metrics.MetricWriter; -import google.registry.monitoring.metrics.stackdriver.StackdriverWriter; import java.util.Set; import java.util.function.Function; import org.joda.time.Duration; diff --git a/java/google/registry/proxy/BUILD b/java/google/registry/proxy/BUILD index 8e75f4b78..d7eb22e4b 100644 --- a/java/google/registry/proxy/BUILD +++ b/java/google/registry/proxy/BUILD @@ -17,8 +17,6 @@ java_library( ]), deps = [ "//java/google/registry/config", - "//java/google/registry/monitoring/metrics", - "//java/google/registry/monitoring/metrics/stackdriver", "//java/google/registry/util", "@com_beust_jcommander", "@com_google_api_client", @@ -28,6 +26,8 @@ java_library( "@com_google_code_findbugs_jsr305", "@com_google_dagger", "@com_google_guava", + "@com_google_monitoring_client_metrics", + "@com_google_monitoring_client_stackdriver", "@io_netty_buffer", "@io_netty_codec", "@io_netty_codec_http", diff --git a/java/google/registry/proxy/MetricsModule.java b/java/google/registry/proxy/MetricsModule.java index ab226d371..c3f96ad82 100644 --- a/java/google/registry/proxy/MetricsModule.java +++ b/java/google/registry/proxy/MetricsModule.java @@ -20,12 +20,12 @@ import com.google.api.services.monitoring.v3.Monitoring; import com.google.api.services.monitoring.v3.model.MonitoredResource; import com.google.common.collect.ImmutableMap; import com.google.common.util.concurrent.ThreadFactoryBuilder; +import com.google.monitoring.metrics.MetricReporter; +import com.google.monitoring.metrics.MetricWriter; +import com.google.monitoring.metrics.stackdriver.StackdriverWriter; import dagger.Component; import dagger.Module; import dagger.Provides; -import google.registry.monitoring.metrics.MetricReporter; -import google.registry.monitoring.metrics.MetricWriter; -import google.registry.monitoring.metrics.stackdriver.StackdriverWriter; import javax.inject.Singleton; /** Module that provides necessary bindings to instantiate a {@link MetricReporter} */ diff --git a/java/google/registry/proxy/ProxyServer.java b/java/google/registry/proxy/ProxyServer.java index 2e664163e..6524ba673 100644 --- a/java/google/registry/proxy/ProxyServer.java +++ b/java/google/registry/proxy/ProxyServer.java @@ -19,7 +19,7 @@ import static google.registry.proxy.handler.RelayHandler.RELAY_CHANNEL_KEY; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; -import google.registry.monitoring.metrics.MetricReporter; +import com.google.monitoring.metrics.MetricReporter; import google.registry.proxy.Protocol.BackendProtocol; import google.registry.proxy.Protocol.FrontendProtocol; import google.registry.proxy.ProxyModule.ProxyComponent; diff --git a/java/google/registry/proxy/metric/BackendMetrics.java b/java/google/registry/proxy/metric/BackendMetrics.java index f33202d9a..124f0a632 100644 --- a/java/google/registry/proxy/metric/BackendMetrics.java +++ b/java/google/registry/proxy/metric/BackendMetrics.java @@ -15,13 +15,13 @@ package google.registry.proxy.metric; import com.google.common.collect.ImmutableSet; -import google.registry.monitoring.metrics.CustomFitter; -import google.registry.monitoring.metrics.EventMetric; -import google.registry.monitoring.metrics.ExponentialFitter; -import google.registry.monitoring.metrics.FibonacciFitter; -import google.registry.monitoring.metrics.IncrementableMetric; -import google.registry.monitoring.metrics.LabelDescriptor; -import google.registry.monitoring.metrics.MetricRegistryImpl; +import com.google.monitoring.metrics.CustomFitter; +import com.google.monitoring.metrics.EventMetric; +import com.google.monitoring.metrics.ExponentialFitter; +import com.google.monitoring.metrics.FibonacciFitter; +import com.google.monitoring.metrics.IncrementableMetric; +import com.google.monitoring.metrics.LabelDescriptor; +import com.google.monitoring.metrics.MetricRegistryImpl; import google.registry.util.NonFinalForTesting; import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.FullHttpResponse; diff --git a/java/google/registry/proxy/metric/FrontendMetrics.java b/java/google/registry/proxy/metric/FrontendMetrics.java index c216c099a..d7eebe2ff 100644 --- a/java/google/registry/proxy/metric/FrontendMetrics.java +++ b/java/google/registry/proxy/metric/FrontendMetrics.java @@ -18,10 +18,10 @@ import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; -import google.registry.monitoring.metrics.IncrementableMetric; -import google.registry.monitoring.metrics.LabelDescriptor; -import google.registry.monitoring.metrics.Metric; -import google.registry.monitoring.metrics.MetricRegistryImpl; +import com.google.monitoring.metrics.IncrementableMetric; +import com.google.monitoring.metrics.LabelDescriptor; +import com.google.monitoring.metrics.Metric; +import com.google.monitoring.metrics.MetricRegistryImpl; import google.registry.util.NonFinalForTesting; import io.netty.channel.Channel; import io.netty.channel.group.ChannelGroup; diff --git a/java/google/registry/rdap/BUILD b/java/google/registry/rdap/BUILD index af35e99dd..c464d7a4b 100644 --- a/java/google/registry/rdap/BUILD +++ b/java/google/registry/rdap/BUILD @@ -11,7 +11,6 @@ java_library( "//java/google/registry/config", "//java/google/registry/flows", "//java/google/registry/model", - "//java/google/registry/monitoring/metrics", "//java/google/registry/request", "//java/google/registry/request/auth", "//java/google/registry/ui/server/registrar", @@ -22,6 +21,7 @@ java_library( "@com_google_dagger", "@com_google_guava", "@com_google_http_client_jackson2", + "@com_google_monitoring_client_metrics", "@com_google_re2j", "@com_googlecode_json_simple", "@javax_servlet_api", diff --git a/java/google/registry/rdap/RdapMetrics.java b/java/google/registry/rdap/RdapMetrics.java index 40998608d..90a631053 100644 --- a/java/google/registry/rdap/RdapMetrics.java +++ b/java/google/registry/rdap/RdapMetrics.java @@ -17,12 +17,12 @@ package google.registry.rdap; import com.google.auto.value.AutoValue; import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.ImmutableSet; -import google.registry.monitoring.metrics.DistributionFitter; -import google.registry.monitoring.metrics.EventMetric; -import google.registry.monitoring.metrics.FibonacciFitter; -import google.registry.monitoring.metrics.IncrementableMetric; -import google.registry.monitoring.metrics.LabelDescriptor; -import google.registry.monitoring.metrics.MetricRegistryImpl; +import com.google.monitoring.metrics.DistributionFitter; +import com.google.monitoring.metrics.EventMetric; +import com.google.monitoring.metrics.FibonacciFitter; +import com.google.monitoring.metrics.IncrementableMetric; +import com.google.monitoring.metrics.LabelDescriptor; +import com.google.monitoring.metrics.MetricRegistryImpl; import google.registry.rdap.RdapSearchResults.IncompletenessWarningType; import google.registry.request.Action; import java.util.Optional; diff --git a/java/google/registry/repositories.bzl b/java/google/registry/repositories.bzl index 35352d135..22145808b 100644 --- a/java/google/registry/repositories.bzl +++ b/java/google/registry/repositories.bzl @@ -74,6 +74,9 @@ def domain_registry_repositories( omit_com_google_http_client=False, omit_com_google_http_client_appengine=False, omit_com_google_http_client_jackson2=False, + omit_com_google_monitoring_client_metrics=False, + omit_com_google_monitoring_client_stackdriver=False, + omit_com_google_monitoring_client_contrib=False, omit_com_google_oauth_client=False, omit_com_google_oauth_client_appengine=False, omit_com_google_oauth_client_java6=False, @@ -256,6 +259,12 @@ def domain_registry_repositories( com_google_http_client_appengine() if not omit_com_google_http_client_jackson2: com_google_http_client_jackson2() + if not omit_com_google_monitoring_client_metrics: + com_google_monitoring_client_metrics() + if not omit_com_google_monitoring_client_stackdriver: + com_google_monitoring_client_stackdriver() + if not omit_com_google_monitoring_client_contrib: + com_google_monitoring_client_contrib() if not omit_com_google_oauth_client: com_google_oauth_client() if not omit_com_google_oauth_client_appengine: @@ -518,6 +527,56 @@ def com_google_api_client_jackson2(): ], ) +def com_google_monitoring_client_metrics(): + java_import_external( + name = "com_google_monitoring_client_metrics", + licenses = ["notice"], # The Apache Software License, Version 2.0 + jar_sha256 = "955fdd758b13f00aad48675a10060cad868b96c83c3a42e7a204c102d6d97cbf", + jar_urls = [ + "http://maven.ibiblio.org/maven2/com/google/monitoring-client/metrics/1.0.3/metrics-1.0.3.jar", + "http://repo1.maven.org/maven2/com/google/monitoring-client/metrics/1.0.3/metrics-1.0.3.jar", + ], + deps = [ + "@com_google_guava", + "@com_google_auto_value", + "@com_google_errorprone_error_prone_annotations", + "@joda_time", + "@com_google_re2j", + ], + ) + +def com_google_monitoring_client_stackdriver(): + java_import_external( + name = "com_google_monitoring_client_stackdriver", + licenses = ["notice"], # The Apache Software License, Version 2.0 + jar_sha256 = "89e90fc245249b6e480167033573ceaa5397b6648844331f72f68c5938789c80", + jar_urls = [ + "http://repo1.maven.org/maven2/com/google/monitoring-client/stackdriver/1.0.3/stackdriver-1.0.3.jar", + "http://maven.ibiblio.org/maven2/com/google/monitoring-client/stackdriver/1.0.3/stackdriver-1.0.3.jar", + ], + deps = [ + "@com_google_guava", + "@com_google_apis_google_api_services_monitoring", + "@com_google_monitoring_client_metrics", + ], + ) + +def com_google_monitoring_client_contrib(): + java_import_external( + name = "com_google_monitoring_client_contrib", + licenses = ["notice"], # The Apache Software License, Version 2.0 + jar_sha256 = "b61f4a2738cc687ea6680488db51ee2409066e2aa59caf9b547fc3e19efe6e43", + jar_urls = [ + "http://maven.ibiblio.org/maven2/com/google/monitoring-client/contrib/1.0.3/contrib-1.0.3.jar", + "http://repo1.maven.org/maven2/com/google/monitoring-client/contrib/1.0.3/contrib-1.0.3.jar", + ], + testonly_ = True, + deps = [ + "@com_google_truth", + "@com_google_monitoring_client_metrics", + ], + ) + def com_google_api_client_java6(): java_import_external( name = "com_google_api_client_java6", diff --git a/java/google/registry/whois/BUILD b/java/google/registry/whois/BUILD index 3c2b8b1a5..1f513cc0d 100644 --- a/java/google/registry/whois/BUILD +++ b/java/google/registry/whois/BUILD @@ -10,7 +10,6 @@ java_library( deps = [ "//java/google/registry/config", "//java/google/registry/model", - "//java/google/registry/monitoring/metrics", "//java/google/registry/request", "//java/google/registry/request/auth", "//java/google/registry/util", @@ -21,6 +20,7 @@ java_library( "@com_google_code_findbugs_jsr305", "@com_google_dagger", "@com_google_guava", + "@com_google_monitoring_client_metrics", "@javax_servlet_api", "@joda_time", ], diff --git a/java/google/registry/whois/WhoisMetrics.java b/java/google/registry/whois/WhoisMetrics.java index 6a995e66b..00ae53322 100644 --- a/java/google/registry/whois/WhoisMetrics.java +++ b/java/google/registry/whois/WhoisMetrics.java @@ -15,14 +15,14 @@ package google.registry.whois; import static com.google.common.base.Preconditions.checkState; -import static google.registry.monitoring.metrics.EventMetric.DEFAULT_FITTER; +import static com.google.monitoring.metrics.EventMetric.DEFAULT_FITTER; import com.google.auto.value.AutoValue; import com.google.common.collect.ImmutableSet; -import google.registry.monitoring.metrics.EventMetric; -import google.registry.monitoring.metrics.IncrementableMetric; -import google.registry.monitoring.metrics.LabelDescriptor; -import google.registry.monitoring.metrics.MetricRegistryImpl; +import com.google.monitoring.metrics.EventMetric; +import com.google.monitoring.metrics.IncrementableMetric; +import com.google.monitoring.metrics.LabelDescriptor; +import com.google.monitoring.metrics.MetricRegistryImpl; import google.registry.util.Clock; import java.util.Optional; import javax.inject.Inject; diff --git a/javatests/google/registry/flows/BUILD b/javatests/google/registry/flows/BUILD index b8523e332..f8585bf64 100644 --- a/javatests/google/registry/flows/BUILD +++ b/javatests/google/registry/flows/BUILD @@ -28,7 +28,6 @@ java_library( "//java/google/registry/dns", "//java/google/registry/flows", "//java/google/registry/model", - "//java/google/registry/monitoring/metrics", "//java/google/registry/monitoring/whitebox", "//java/google/registry/pricing", "//java/google/registry/request", @@ -46,6 +45,7 @@ java_library( "@com_google_dagger", "@com_google_guava", "@com_google_guava_testlib", + "@com_google_monitoring_client_metrics", "@com_google_re2j", "@com_google_truth", "@com_google_truth_extensions_truth_java8_extension", diff --git a/javatests/google/registry/flows/async/AsyncFlowMetricsTest.java b/javatests/google/registry/flows/async/AsyncFlowMetricsTest.java index 134c81b74..88f39e2b7 100644 --- a/javatests/google/registry/flows/async/AsyncFlowMetricsTest.java +++ b/javatests/google/registry/flows/async/AsyncFlowMetricsTest.java @@ -20,8 +20,8 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; -import google.registry.monitoring.metrics.EventMetric; -import google.registry.monitoring.metrics.IncrementableMetric; +import com.google.monitoring.metrics.EventMetric; +import com.google.monitoring.metrics.IncrementableMetric; import google.registry.testing.FakeClock; import google.registry.testing.InjectRule; import google.registry.testing.ShardableTestCase; diff --git a/javatests/google/registry/model/BUILD b/javatests/google/registry/model/BUILD index fa52101af..9c78fd346 100644 --- a/javatests/google/registry/model/BUILD +++ b/javatests/google/registry/model/BUILD @@ -23,7 +23,6 @@ java_library( "//java/google/registry/dns/writer", "//java/google/registry/flows", "//java/google/registry/model", - "//java/google/registry/monitoring/metrics/contrib", "//java/google/registry/util", "//java/google/registry/xml", "//javatests/google/registry/testing", @@ -34,6 +33,7 @@ java_library( "@com_google_code_findbugs_jsr305", "@com_google_guava", "@com_google_guava_testlib", + "@com_google_monitoring_client_contrib", "@com_google_truth", "@com_google_truth_extensions_truth_java8_extension", "@joda_time", diff --git a/javatests/google/registry/model/registry/label/PremiumListUtilsTest.java b/javatests/google/registry/model/registry/label/PremiumListUtilsTest.java index c057df860..701f2a5a6 100644 --- a/javatests/google/registry/model/registry/label/PremiumListUtilsTest.java +++ b/javatests/google/registry/model/registry/label/PremiumListUtilsTest.java @@ -16,6 +16,8 @@ package google.registry.model.registry.label; import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth8.assertThat; +import static com.google.monitoring.metrics.contrib.DistributionMetricSubject.assertThat; +import static com.google.monitoring.metrics.contrib.LongMetricSubject.assertThat; import static google.registry.model.ofy.ObjectifyService.ofy; import static google.registry.model.registry.label.DomainLabelMetrics.PremiumListCheckOutcome.BLOOM_FILTER_NEGATIVE; import static google.registry.model.registry.label.DomainLabelMetrics.PremiumListCheckOutcome.CACHED_NEGATIVE; @@ -28,8 +30,6 @@ import static google.registry.model.registry.label.PremiumListUtils.deletePremiu import static google.registry.model.registry.label.PremiumListUtils.doesPremiumListExist; import static google.registry.model.registry.label.PremiumListUtils.getPremiumPrice; import static google.registry.model.registry.label.PremiumListUtils.savePremiumListAndEntries; -import static google.registry.monitoring.metrics.contrib.DistributionMetricSubject.assertThat; -import static google.registry.monitoring.metrics.contrib.LongMetricSubject.assertThat; import static google.registry.testing.DatastoreHelper.createTld; import static google.registry.testing.DatastoreHelper.loadPremiumListEntries; import static google.registry.testing.DatastoreHelper.persistPremiumList; diff --git a/javatests/google/registry/model/registry/label/ReservedListTest.java b/javatests/google/registry/model/registry/label/ReservedListTest.java index abc0103ba..9ff854fac 100644 --- a/javatests/google/registry/model/registry/label/ReservedListTest.java +++ b/javatests/google/registry/model/registry/label/ReservedListTest.java @@ -16,6 +16,8 @@ package google.registry.model.registry.label; import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertWithMessage; +import static com.google.monitoring.metrics.contrib.DistributionMetricSubject.assertThat; +import static com.google.monitoring.metrics.contrib.LongMetricSubject.assertThat; import static google.registry.model.registry.label.DomainLabelMetrics.reservedListChecks; import static google.registry.model.registry.label.DomainLabelMetrics.reservedListHits; import static google.registry.model.registry.label.DomainLabelMetrics.reservedListProcessingTime; @@ -28,8 +30,6 @@ import static google.registry.model.registry.label.ReservationType.RESERVED_FOR_ import static google.registry.model.registry.label.ReservedList.getAllowedNameservers; import static google.registry.model.registry.label.ReservedList.getReservationTypes; import static google.registry.model.registry.label.ReservedList.matchesAnchorTenantReservation; -import static google.registry.monitoring.metrics.contrib.DistributionMetricSubject.assertThat; -import static google.registry.monitoring.metrics.contrib.LongMetricSubject.assertThat; import static google.registry.testing.DatastoreHelper.createTld; import static google.registry.testing.DatastoreHelper.persistReservedList; import static google.registry.testing.DatastoreHelper.persistResource; diff --git a/javatests/google/registry/monitoring/metrics/BUILD b/javatests/google/registry/monitoring/metrics/BUILD deleted file mode 100644 index 922f09d4b..000000000 --- a/javatests/google/registry/monitoring/metrics/BUILD +++ /dev/null @@ -1,31 +0,0 @@ -package( - default_testonly = 1, - default_visibility = ["//java/google/registry:registry_project"], -) - -licenses(["notice"]) # Apache 2.0 - -load("//java/com/google/testing/builddefs:GenTestRules.bzl", "GenTestRules") - -java_library( - name = "metrics", - srcs = glob(["*.java"]), - deps = [ - "//java/google/registry/monitoring/metrics", - "//third_party/junit", - "@com_google_guava", - "@com_google_truth", - "@com_google_truth_extensions_truth_java8_extension", - "@joda_time", - "@junit", - "@org_mockito_all", - ], -) - -GenTestRules( - name = "GeneratedTestRules", - test_files = glob(["*Test.java"]), - deps = [ - ":metrics", - ], -) diff --git a/javatests/google/registry/monitoring/metrics/CounterTest.java b/javatests/google/registry/monitoring/metrics/CounterTest.java deleted file mode 100644 index 949c635fb..000000000 --- a/javatests/google/registry/monitoring/metrics/CounterTest.java +++ /dev/null @@ -1,184 +0,0 @@ -// Copyright 2017 The Nomulus 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 static com.google.common.truth.Truth.assertThat; -import static google.registry.testing.JUnitBackports.expectThrows; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableSet; -import org.joda.time.Instant; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Unit tests for {@link Counter}. */ -@RunWith(JUnit4.class) -public class CounterTest { - @Test - public void testGetCardinality_reflectsCurrentCardinality() { - Counter counter = - new Counter( - "/metric", - "description", - "vdn", - ImmutableSet.of(LabelDescriptor.create("label1", "bar"))); - assertThat(counter.getCardinality()).isEqualTo(0); - - counter.increment("foo"); - assertThat(counter.getCardinality()).isEqualTo(1); - counter.increment("bar"); - assertThat(counter.getCardinality()).isEqualTo(2); - counter.increment("foo"); - assertThat(counter.getCardinality()).isEqualTo(2); - } - - @Test - public void testIncrementBy_wrongLabelValueCount_throwsException() { - Counter counter = - new Counter( - "/metric", - "description", - "vdn", - ImmutableSet.of( - LabelDescriptor.create("label1", "bar"), LabelDescriptor.create("label2", "bar"))); - - IllegalArgumentException thrown = - expectThrows(IllegalArgumentException.class, () -> counter.increment("blah")); - assertThat(thrown) - .hasMessageThat() - .contains( - "The count of labelValues must be equal to the underlying Metric's count of labels."); - } - - @Test - public void testIncrement_incrementsValues() { - Counter counter = - new Counter( - "/metric", - "description", - "vdn", - ImmutableSet.of(LabelDescriptor.create("label1", "bar"))); - - assertThat(counter.getTimestampedValues()).isEmpty(); - - // use package-private incrementBy once to set the start timestamp predictably. - counter.incrementBy(1, new Instant(1337), ImmutableList.of("test_value1")); - assertThat(counter.getTimestampedValues(new Instant(1337))) - .containsExactly( - MetricPoint.create(counter, ImmutableList.of("test_value1"), new Instant(1337), 1L)); - - counter.increment("test_value1"); - assertThat(counter.getTimestampedValues(new Instant(1337))) - .containsExactly( - MetricPoint.create(counter, ImmutableList.of("test_value1"), new Instant(1337), 2L)); - } - - @Test - public void testIncrementBy_incrementsValues() { - Counter counter = - new Counter( - "/metric", - "description", - "vdn", - ImmutableSet.of(LabelDescriptor.create("label1", "bar"))); - - assertThat(counter.getTimestampedValues()).isEmpty(); - - counter.incrementBy(1, new Instant(1337), ImmutableList.of("test_value1")); - assertThat(counter.getTimestampedValues(new Instant(1337))) - .containsExactly( - MetricPoint.create(counter, ImmutableList.of("test_value1"), new Instant(1337), 1L)); - - counter.set(-10L, new Instant(1337), ImmutableList.of("test_value2")); - counter.incrementBy(5, new Instant(1337), ImmutableList.of("test_value2")); - assertThat(counter.getTimestampedValues(new Instant(1337))) - .containsExactly( - MetricPoint.create(counter, ImmutableList.of("test_value1"), new Instant(1337), 1L), - MetricPoint.create(counter, ImmutableList.of("test_value2"), new Instant(1337), -5L)); - } - - @Test - public void testIncrementBy_negativeOffset_throwsException() { - Counter counter = - new Counter( - "/metric", - "description", - "vdn", - ImmutableSet.of(LabelDescriptor.create("label1", "bar"))); - - IllegalArgumentException thrown = - expectThrows(IllegalArgumentException.class, () -> counter.incrementBy(-1L, "foo")); - assertThat(thrown).hasMessageThat().contains("The offset provided must be non-negative"); - } - - @Test - public void testResetAll_resetsAllValuesAndStartTimestamps() { - Counter counter = - new Counter( - "/metric", - "description", - "vdn", - ImmutableSet.of(LabelDescriptor.create("label1", "bar"))); - - counter.incrementBy(3, new Instant(1337), ImmutableList.of("foo")); - counter.incrementBy(5, new Instant(1338), ImmutableList.of("moo")); - - assertThat(counter.getTimestampedValues(new Instant(1400))) - .containsExactly( - MetricPoint.create( - counter, ImmutableList.of("foo"), new Instant(1337), new Instant(1400), 3L), - MetricPoint.create( - counter, ImmutableList.of("moo"), new Instant(1338), new Instant(1400), 5L)); - - counter.reset(new Instant(1339)); - - assertThat(counter.getTimestampedValues(new Instant(1400))) - .containsExactly( - MetricPoint.create( - counter, ImmutableList.of("foo"), new Instant(1339), new Instant(1400), 0L), - MetricPoint.create( - counter, ImmutableList.of("moo"), new Instant(1339), new Instant(1400), 0L)); - } - - @Test - public void testReset_resetsValuesAndStartTimestamps() { - Counter counter = - new Counter( - "/metric", - "description", - "vdn", - ImmutableSet.of(LabelDescriptor.create("label1", "bar"))); - - counter.incrementBy(3, new Instant(1337), ImmutableList.of("foo")); - counter.incrementBy(5, new Instant(1338), ImmutableList.of("moo")); - - assertThat(counter.getTimestampedValues(new Instant(1400))) - .containsExactly( - MetricPoint.create( - counter, ImmutableList.of("foo"), new Instant(1337), new Instant(1400), 3L), - MetricPoint.create( - counter, ImmutableList.of("moo"), new Instant(1338), new Instant(1400), 5L)); - - counter.reset(new Instant(1339), ImmutableList.of("foo")); - - assertThat(counter.getTimestampedValues(new Instant(1400))) - .containsExactly( - MetricPoint.create( - counter, ImmutableList.of("foo"), new Instant(1339), new Instant(1400), 0L), - MetricPoint.create( - counter, ImmutableList.of("moo"), new Instant(1338), new Instant(1400), 5L)); - } -} diff --git a/javatests/google/registry/monitoring/metrics/CustomFitterTest.java b/javatests/google/registry/monitoring/metrics/CustomFitterTest.java deleted file mode 100644 index 25fcb9dd8..000000000 --- a/javatests/google/registry/monitoring/metrics/CustomFitterTest.java +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright 2017 The Nomulus 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 static com.google.common.truth.Truth.assertThat; -import static google.registry.testing.JUnitBackports.expectThrows; - -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.ImmutableSortedSet; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Tests for {@link CustomFitter}. */ -@RunWith(JUnit4.class) -public class CustomFitterTest { - - @Test - public void testCreateCustomFitter_emptyBounds_throwsException() throws Exception { - IllegalArgumentException thrown = - expectThrows(IllegalArgumentException.class, () -> CustomFitter.create(ImmutableSet.of())); - assertThat(thrown).hasMessageThat().contains("boundaries must not be empty"); - } - - @Test - public void testCreateCustomFitter_outOfOrderBounds_throwsException() throws Exception { - IllegalArgumentException thrown = - expectThrows( - IllegalArgumentException.class, () -> CustomFitter.create(ImmutableSet.of(2.0, 0.0))); - assertThat(thrown).hasMessageThat().contains("boundaries must be sorted"); - } - - @Test - public void testCreateCustomFitter_hasGivenBounds() { - CustomFitter fitter = CustomFitter.create(ImmutableSortedSet.of(1.0, 2.0)); - assertThat(fitter.boundaries()).containsExactly(1.0, 2.0).inOrder(); - } -} diff --git a/javatests/google/registry/monitoring/metrics/EventMetricTest.java b/javatests/google/registry/monitoring/metrics/EventMetricTest.java deleted file mode 100644 index 7124ab175..000000000 --- a/javatests/google/registry/monitoring/metrics/EventMetricTest.java +++ /dev/null @@ -1,314 +0,0 @@ -// Copyright 2017 The Nomulus 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 static com.google.common.truth.Truth.assertThat; -import static google.registry.testing.JUnitBackports.expectThrows; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableRangeMap; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Range; -import org.joda.time.Instant; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Unit tests for {@link EventMetric}. */ -@RunWith(JUnit4.class) -public class EventMetricTest { - - private final DistributionFitter distributionFitter = CustomFitter.create(ImmutableSet.of(5.0)); - private EventMetric metric; - @Before - public void setUp() { - metric = - new EventMetric( - "/metric", - "description", - "vdn", - distributionFitter, - ImmutableSet.of(LabelDescriptor.create("label1", "bar"))); - } - - @Test - public void testGetCardinality_reflectsCurrentCardinality() { - assertThat(metric.getCardinality()).isEqualTo(0); - - metric.record(1.0, "foo"); - - assertThat(metric.getCardinality()).isEqualTo(1); - - metric.record(1.0, "bar"); - - assertThat(metric.getCardinality()).isEqualTo(2); - - metric.record(1.0, "foo"); - - assertThat(metric.getCardinality()).isEqualTo(2); - } - - @Test - public void testIncrementBy_wrongLabelValueCount_throwsException() { - IllegalArgumentException thrown = - expectThrows(IllegalArgumentException.class, () -> metric.record(1.0, "blah", "blah")); - assertThat(thrown) - .hasMessageThat() - .contains( - "The count of labelValues must be equal to the underlying Metric's count of labels."); - } - - @Test - public void testRecord_updatesDistribution() { - assertThat(metric.getTimestampedValues()).isEmpty(); - - metric.recordMultiple(1.0, 1, new Instant(1337), ImmutableList.of("test_value1")); - - assertThat(metric.getTimestampedValues(new Instant(1338))) - .containsExactly( - MetricPoint.create( - metric, - ImmutableList.of("test_value1"), - new Instant(1337), - new Instant(1338), - ImmutableDistribution.create( - 1.0, - 0.0, - 1L, - ImmutableRangeMap.builder() - .put(Range.lessThan(5.0), 1L) - .put(Range.atLeast(5.0), 0L) - .build(), - distributionFitter))); - - metric.record(10.0, "test_value1"); - - assertThat(metric.getTimestampedValues(new Instant(1338))) - .containsExactly( - MetricPoint.create( - metric, - ImmutableList.of("test_value1"), - new Instant(1337), - new Instant(1338), - ImmutableDistribution.create( - 5.5, - 40.5, - 2L, - ImmutableRangeMap.builder() - .put(Range.lessThan(5.0), 1L) - .put(Range.atLeast(5.0), 1L) - .build(), - distributionFitter))); - } - - @Test - public void testRecord_multipleValues_updatesDistributions() { - assertThat(metric.getTimestampedValues()).isEmpty(); - - metric.recordMultiple(1.0, 3, new Instant(1337), ImmutableList.of("test_value1")); - - assertThat(metric.getTimestampedValues(new Instant(1338))) - .containsExactly( - MetricPoint.create( - metric, - ImmutableList.of("test_value1"), - new Instant(1337), - new Instant(1338), - ImmutableDistribution.create( - 1.0, - 0, - 3L, - ImmutableRangeMap.builder() - .put(Range.lessThan(5.0), 3L) - .put(Range.atLeast(5.0), 0L) - .build(), - distributionFitter))); - - metric.recordMultiple(2.0, 5, new Instant(1337), ImmutableList.of("test_value1")); - metric.recordMultiple(7.0, 10, new Instant(1337), ImmutableList.of("test_value2")); - - assertThat(metric.getTimestampedValues(new Instant(1338))) - .containsExactly( - MetricPoint.create( - metric, - ImmutableList.of("test_value1"), - new Instant(1337), - new Instant(1338), - ImmutableDistribution.create( - 1.625, - 1.875, - 8L, - ImmutableRangeMap.builder() - .put(Range.lessThan(5.0), 8L) - .put(Range.atLeast(5.0), 0L) - .build(), - distributionFitter)), - MetricPoint.create( - metric, - ImmutableList.of("test_value2"), - new Instant(1337), - new Instant(1338), - ImmutableDistribution.create( - 7.0, - 0, - 10L, - ImmutableRangeMap.builder() - .put(Range.lessThan(5.0), 0L) - .put(Range.atLeast(5.0), 10L) - .build(), - distributionFitter))); - } - - @Test - public void testResetAll_resetsAllValuesAndStartTimestamps() { - metric.recordMultiple(3.0, 1, new Instant(1336), ImmutableList.of("foo")); - metric.recordMultiple(5.0, 1, new Instant(1337), ImmutableList.of("moo")); - - assertThat(metric.getTimestampedValues(new Instant(1338))) - .containsExactly( - MetricPoint.create( - metric, - ImmutableList.of("foo"), - new Instant(1336), - new Instant(1338), - ImmutableDistribution.create( - 3.0, - 0.0, - 1L, - ImmutableRangeMap.builder() - .put(Range.lessThan(5.0), 1L) - .put(Range.atLeast(5.0), 0L) - .build(), - distributionFitter)), - MetricPoint.create( - metric, - ImmutableList.of("moo"), - new Instant(1337), - new Instant(1338), - ImmutableDistribution.create( - 5.0, - 0, - 1L, - ImmutableRangeMap.builder() - .put(Range.lessThan(5.0), 0L) - .put(Range.atLeast(5.0), 1L) - .build(), - distributionFitter))); - - metric.reset(new Instant(1339)); - - assertThat(metric.getTimestampedValues(new Instant(1340))) - .containsExactly( - MetricPoint.create( - metric, - ImmutableList.of("foo"), - new Instant(1339), - new Instant(1340), - ImmutableDistribution.create( - 0.0, - 0.0, - 0L, - ImmutableRangeMap.builder() - .put(Range.lessThan(5.0), 0L) - .put(Range.atLeast(5.0), 0L) - .build(), - distributionFitter)), - MetricPoint.create( - metric, - ImmutableList.of("moo"), - new Instant(1339), - new Instant(1340), - ImmutableDistribution.create( - 0.0, - 0, - 0L, - ImmutableRangeMap.builder() - .put(Range.lessThan(5.0), 0L) - .put(Range.atLeast(5.0), 0L) - .build(), - distributionFitter))); - } - - @Test - public void testReset_resetsValueAndStartTimestamp() { - metric.recordMultiple(3.0, 1, new Instant(1336), ImmutableList.of("foo")); - metric.recordMultiple(5.0, 1, new Instant(1337), ImmutableList.of("moo")); - - assertThat(metric.getTimestampedValues(new Instant(1338))) - .containsExactly( - MetricPoint.create( - metric, - ImmutableList.of("foo"), - new Instant(1336), - new Instant(1338), - ImmutableDistribution.create( - 3.0, - 0.0, - 1L, - ImmutableRangeMap.builder() - .put(Range.lessThan(5.0), 1L) - .put(Range.atLeast(5.0), 0L) - .build(), - distributionFitter)), - MetricPoint.create( - metric, - ImmutableList.of("moo"), - new Instant(1337), - new Instant(1338), - ImmutableDistribution.create( - 5.0, - 0, - 1L, - ImmutableRangeMap.builder() - .put(Range.lessThan(5.0), 0L) - .put(Range.atLeast(5.0), 1L) - .build(), - distributionFitter))); - - metric.reset(new Instant(1339), ImmutableList.of("foo")); - - assertThat(metric.getTimestampedValues(new Instant(1340))) - .containsExactly( - MetricPoint.create( - metric, - ImmutableList.of("foo"), - new Instant(1339), - new Instant(1340), - ImmutableDistribution.create( - 0.0, - 0.0, - 0L, - ImmutableRangeMap.builder() - .put(Range.lessThan(5.0), 0L) - .put(Range.atLeast(5.0), 0L) - .build(), - distributionFitter)), - MetricPoint.create( - metric, - ImmutableList.of("moo"), - new Instant(1337), - new Instant(1340), - ImmutableDistribution.create( - 5.0, - 0, - 1L, - ImmutableRangeMap.builder() - .put(Range.lessThan(5.0), 0L) - .put(Range.atLeast(5.0), 1L) - .build(), - distributionFitter))); - } -} diff --git a/javatests/google/registry/monitoring/metrics/ExponentialFitterTest.java b/javatests/google/registry/monitoring/metrics/ExponentialFitterTest.java deleted file mode 100644 index a8f25aa18..000000000 --- a/javatests/google/registry/monitoring/metrics/ExponentialFitterTest.java +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright 2017 The Nomulus 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 static com.google.common.truth.Truth.assertThat; -import static google.registry.testing.JUnitBackports.expectThrows; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Unit tests for {@link ExponentialFitter}. */ -@RunWith(JUnit4.class) -public class ExponentialFitterTest { - @Test - public void testCreateExponentialFitter_zeroNumIntervals_throwsException() throws Exception { - IllegalArgumentException thrown = - expectThrows(IllegalArgumentException.class, () -> ExponentialFitter.create(0, 3.0, 1.0)); - assertThat(thrown).hasMessageThat().contains("numFiniteIntervals must be greater than 0"); - } - - @Test - public void testCreateExponentialFitter_negativeNumIntervals_throwsException() throws Exception { - IllegalArgumentException thrown = - expectThrows(IllegalArgumentException.class, () -> ExponentialFitter.create(-1, 3.0, 1.0)); - assertThat(thrown).hasMessageThat().contains("numFiniteIntervals must be greater than 0"); - } - - @Test - public void testCreateExponentialFitter_invalidBase_throwsException() throws Exception { - IllegalArgumentException thrown = - expectThrows(IllegalArgumentException.class, () -> ExponentialFitter.create(3, 0.5, 1.0)); - assertThat(thrown).hasMessageThat().contains("base must be greater than 1"); - } - - @Test - public void testCreateExponentialFitter_zeroScale_throwsException() throws Exception { - IllegalArgumentException thrown = - expectThrows(IllegalArgumentException.class, () -> ExponentialFitter.create(3, 2.0, 0.0)); - assertThat(thrown).hasMessageThat().contains("scale must not be 0"); - } - - @Test - public void testCreateExponentialFitter_NanScale_throwsException() throws Exception { - IllegalArgumentException thrown = - expectThrows( - IllegalArgumentException.class, () -> ExponentialFitter.create(3, 2.0, Double.NaN)); - assertThat(thrown).hasMessageThat().contains("value must be finite, not NaN, and not -0.0"); - } - - @Test - public void testCreateExponentialFitter_hasCorrectBounds() { - ExponentialFitter fitter = ExponentialFitter.create(3, 5.0, 2.0); - - assertThat(fitter.boundaries()).containsExactly(2.0, 10.0, 50.0, 250.0).inOrder(); - } -} diff --git a/javatests/google/registry/monitoring/metrics/FibonacciFitterTest.java b/javatests/google/registry/monitoring/metrics/FibonacciFitterTest.java deleted file mode 100644 index c58dc5141..000000000 --- a/javatests/google/registry/monitoring/metrics/FibonacciFitterTest.java +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright 2017 The Nomulus 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 static com.google.common.truth.Truth.assertThat; -import static google.registry.testing.JUnitBackports.expectThrows; - -import com.google.common.collect.ImmutableList; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Unit tests for {@link FibonacciFitter}. */ -@RunWith(JUnit4.class) -public class FibonacciFitterTest { - - @Test - public void testCreate_maxBucketSizeNegative_throwsException() { - IllegalArgumentException e = - expectThrows(IllegalArgumentException.class, () -> FibonacciFitter.create(-1)); - assertThat(e).hasMessageThat().isEqualTo("maxBucketSize must be greater than 0"); - } - - @Test - public void testCreate_maxBucketSizeZero_throwsException() { - IllegalArgumentException e = - expectThrows(IllegalArgumentException.class, () -> FibonacciFitter.create(0)); - assertThat(e).hasMessageThat().isEqualTo("maxBucketSize must be greater than 0"); - } - - @Test - public void testCreate_maxBucketSizeOne_createsTwoBoundaries() { - assertThat(FibonacciFitter.create(1).boundaries()).containsExactly(0.0, 1.0).inOrder(); - } - - @Test - public void testCreate_maxBucketSizeTwo_createsThreeBoundaries() { - assertThat(FibonacciFitter.create(2).boundaries()).containsExactly(0.0, 1.0, 2.0).inOrder(); - } - - @Test - public void testCreate_maxBucketSizeThree_createsFourBoundaries() { - assertThat(FibonacciFitter.create(3).boundaries()) - .containsExactly(0.0, 1.0, 2.0, 3.0) - .inOrder(); - } - - @Test - public void testCreate_maxBucketSizeFour_createsFourBoundaries() { - assertThat(FibonacciFitter.create(4).boundaries()) - .containsExactly(0.0, 1.0, 2.0, 3.0) - .inOrder(); - } - - @Test - public void testCreate_maxBucketSizeLarge_createsFibonacciSequenceBoundaries() { - ImmutableList expectedBoundaries = - ImmutableList.of( - 0.0, 1.0, 2.0, 3.0, 5.0, 8.0, 13.0, 21.0, 34.0, 55.0, 89.0, 144.0, 233.0, 377.0, 610.0, - 987.0); - assertThat(FibonacciFitter.create(1000).boundaries()) - .containsExactlyElementsIn(expectedBoundaries) - .inOrder(); - } -} diff --git a/javatests/google/registry/monitoring/metrics/LabelDescriptorTest.java b/javatests/google/registry/monitoring/metrics/LabelDescriptorTest.java deleted file mode 100644 index 1d7def2a5..000000000 --- a/javatests/google/registry/monitoring/metrics/LabelDescriptorTest.java +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright 2017 The Nomulus 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 static com.google.common.truth.Truth.assertThat; -import static google.registry.testing.JUnitBackports.expectThrows; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Unit tests for {@link LabelDescriptor}. */ -@RunWith(JUnit4.class) -public class LabelDescriptorTest { - - @Test - public void testCreate_invalidLabel_throwsException() { - IllegalArgumentException thrown = - expectThrows( - IllegalArgumentException.class, () -> LabelDescriptor.create("@", "description")); - assertThat(thrown).hasMessageThat().contains("Label name must match the regex"); - } - - @Test - public void testCreate_blankNameField_throwsException() { - IllegalArgumentException thrown = - expectThrows( - IllegalArgumentException.class, () -> LabelDescriptor.create("", "description")); - assertThat(thrown).hasMessageThat().contains("Name must not be empty"); - } - - @Test - public void testCreate_blankDescriptionField_throwsException() { - IllegalArgumentException thrown = - expectThrows(IllegalArgumentException.class, () -> LabelDescriptor.create("name", "")); - assertThat(thrown).hasMessageThat().contains("Description must not be empty"); - } -} diff --git a/javatests/google/registry/monitoring/metrics/LinearFitterTest.java b/javatests/google/registry/monitoring/metrics/LinearFitterTest.java deleted file mode 100644 index f4ced9c6b..000000000 --- a/javatests/google/registry/monitoring/metrics/LinearFitterTest.java +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright 2017 The Nomulus 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 static com.google.common.truth.Truth.assertThat; -import static google.registry.testing.JUnitBackports.expectThrows; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Unit tests for {@link LinearFitter}. */ -@RunWith(JUnit4.class) -public class LinearFitterTest { - @Test - public void testCreateLinearFitter_zeroNumIntervals_throwsException() throws Exception { - IllegalArgumentException thrown = - expectThrows(IllegalArgumentException.class, () -> LinearFitter.create(0, 3.0, 0.0)); - assertThat(thrown).hasMessageThat().contains("numFiniteIntervals must be greater than 0"); - } - - @Test - public void testCreateLinearFitter_negativeNumIntervals_throwsException() throws Exception { - IllegalArgumentException thrown = - expectThrows(IllegalArgumentException.class, () -> LinearFitter.create(0, 3.0, 0.0)); - assertThat(thrown).hasMessageThat().contains("numFiniteIntervals must be greater than 0"); - } - - @Test - public void testCreateLinearFitter_zeroWidth_throwsException() throws Exception { - IllegalArgumentException thrown = - expectThrows(IllegalArgumentException.class, () -> LinearFitter.create(3, 0.0, 0.0)); - assertThat(thrown).hasMessageThat().contains("width must be greater than 0"); - } - - @Test - public void testCreateLinearFitter_negativeWidth_throwsException() throws Exception { - IllegalArgumentException thrown = - expectThrows(IllegalArgumentException.class, () -> LinearFitter.create(3, 0.0, 0.0)); - assertThat(thrown).hasMessageThat().contains("width must be greater than 0"); - } - - @Test - public void testCreateLinearFitter_NaNWidth_throwsException() throws Exception { - IllegalArgumentException thrown = - expectThrows(IllegalArgumentException.class, () -> LinearFitter.create(3, Double.NaN, 0.0)); - assertThat(thrown).hasMessageThat().contains("width must be greater than 0"); - } - - @Test - public void testCreateLinearFitter_NaNOffset_throwsException() throws Exception { - IllegalArgumentException thrown = - expectThrows(IllegalArgumentException.class, () -> LinearFitter.create(3, 1.0, Double.NaN)); - assertThat(thrown).hasMessageThat().contains("value must be finite, not NaN, and not -0.0"); - } - - @Test - public void testCreateLinearFitter_hasCorrectBounds() { - LinearFitter fitter = LinearFitter.create(1, 10, 0); - - assertThat(fitter.boundaries()).containsExactly(0.0, 10.0).inOrder(); - } - - @Test - public void testCreateLinearFitter_withOffset_hasCorrectBounds() { - LinearFitter fitter = LinearFitter.create(1, 10, 5); - - assertThat(fitter.boundaries()).containsExactly(5.0, 15.0).inOrder(); - } - - @Test - public void testCreateLinearFitter_withOffsetAndMultipleIntervals_hasCorrectBounds() { - LinearFitter fitter = LinearFitter.create(3, 10, 5); - - assertThat(fitter.boundaries()).containsExactly(5.0, 15.0, 25.0, 35.0).inOrder(); - } -} diff --git a/javatests/google/registry/monitoring/metrics/MetricExporterTest.java b/javatests/google/registry/monitoring/metrics/MetricExporterTest.java deleted file mode 100644 index 8a49e51a0..000000000 --- a/javatests/google/registry/monitoring/metrics/MetricExporterTest.java +++ /dev/null @@ -1,130 +0,0 @@ -// Copyright 2017 The Nomulus 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 static com.google.common.truth.Truth.assertThat; -import static org.junit.Assert.fail; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; - -import com.google.common.collect.ImmutableList; -import com.google.common.util.concurrent.Service.State; -import java.io.IOException; -import java.util.Optional; -import java.util.concurrent.ArrayBlockingQueue; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Matchers; -import org.mockito.Mock; -import org.mockito.runners.MockitoJUnitRunner; - -/** Unit tests for {@link MetricExporter}. */ -@RunWith(MockitoJUnitRunner.class) -public class MetricExporterTest { - - @Mock private MetricWriter writer; - @Mock private MetricPoint point; - private MetricExporter exporter; - private BlockingQueue>>> writeQueue; - private final Optional>> poisonPill = Optional.empty(); - private final Optional>> emptyBatch = - Optional.of(ImmutableList.>of()); - - @Before - public void setUp() throws Exception { - writeQueue = new ArrayBlockingQueue<>(1); - exporter = new MetricExporter(writeQueue, writer, Executors.defaultThreadFactory()); - } - - @Test - public void testRun_takesFromQueue_whileRunning() throws Exception { - exporter.startAsync().awaitRunning(); - - insertAndAssert(emptyBatch); - // Insert more batches to verify that the exporter hasn't gotten stuck - insertAndAssert(emptyBatch); - insertAndAssert(emptyBatch); - - assertThat(exporter.state()).isEqualTo(State.RUNNING); - } - - @Test - public void testRun_terminates_afterPoisonPill() throws Exception { - exporter.startAsync().awaitRunning(); - - insertAndAssert(poisonPill); - try { - exporter.awaitTerminated(500, TimeUnit.MILLISECONDS); - } catch (TimeoutException timeout) { - fail("MetricExporter did not reach the TERMINATED state after receiving a poison pill"); - } - - assertThat(exporter.state()).isEqualTo(State.TERMINATED); - } - - @Test - public void testRun_staysRunning_afterIOException() throws Exception { - Optional>> threeBatch = - Optional.of(ImmutableList.of(point, point, point)); - doThrow(new IOException()).when(writer).write(Matchers.>any()); - exporter.startAsync(); - - insertAndAssert(threeBatch); - // Insert another batch in order to block until the exporter has processed the last one - insertAndAssert(threeBatch); - // Insert another to make sure the exporter hasn't gotten stuck - insertAndAssert(threeBatch); - - assertThat(exporter.state()).isNotEqualTo(State.FAILED); - } - - @Test - public void testRun_writesMetrics() throws Exception { - Optional>> threeBatch = - Optional.of(ImmutableList.of(point, point, point)); - exporter.startAsync(); - - insertAndAssert(threeBatch); - // Insert another batch in order to block until the exporter has processed the last one - insertAndAssert(threeBatch); - - // Force the exporter to finish so that the verify counts below are deterministic - insertAndAssert(poisonPill); - try { - exporter.awaitTerminated(500, TimeUnit.MILLISECONDS); - } catch (TimeoutException timeout) { - fail("MetricExporter did not reach the TERMINATED state after receiving a poison pill"); - } - - assertThat(exporter.state()).isNotEqualTo(State.FAILED); - verify(writer, times(6)).write(point); - verify(writer, times(2)).flush(); - } - - /** - * Helper method to insert into the {@link BlockingQueue} and assert that the item has been - * enqueued. - */ - private void insertAndAssert(Optional>> batch) throws Exception { - boolean isTaken = writeQueue.offer(batch, 500, TimeUnit.MILLISECONDS); - assertThat(isTaken).isTrue(); - } -} diff --git a/javatests/google/registry/monitoring/metrics/MetricRegistryImplTest.java b/javatests/google/registry/monitoring/metrics/MetricRegistryImplTest.java deleted file mode 100644 index 3ee96cd22..000000000 --- a/javatests/google/registry/monitoring/metrics/MetricRegistryImplTest.java +++ /dev/null @@ -1,167 +0,0 @@ -// Copyright 2017 The Nomulus 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 static com.google.common.truth.Truth.assertThat; -import static google.registry.testing.JUnitBackports.expectThrows; -import static org.mockito.Mockito.mock; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; -import google.registry.monitoring.metrics.MetricSchema.Kind; -import org.junit.After; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** - * Unit tests for {@link MetricRegistryImpl}. - * - *

The MetricRegistryImpl is a singleton, so we have to be careful to empty it after every test - * to maintain a blank slate. - */ -@RunWith(JUnit4.class) -public class MetricRegistryImplTest { - private final LabelDescriptor label = - LabelDescriptor.create("test_labelname", "test_labeldescription"); - - @After - public void clearMetrics() { - MetricRegistryImpl.getDefault().unregisterAllMetrics(); - } - - @Test - public void testRegisterAndUnregister_tracksRegistrations() { - assertThat(MetricRegistryImpl.getDefault().getRegisteredMetrics()).isEmpty(); - - AbstractMetric metric = mock(AbstractMetric.class); - MetricRegistryImpl.getDefault().registerMetric("/test/metric", metric); - - assertThat(MetricRegistryImpl.getDefault().getRegisteredMetrics()).containsExactly(metric); - - MetricRegistryImpl.getDefault().unregisterMetric("/test/metric"); - - assertThat(MetricRegistryImpl.getDefault().getRegisteredMetrics()).isEmpty(); - } - - @Test - public void testNewGauge_createsGauge() { - Metric testGauge = - MetricRegistryImpl.getDefault() - .newGauge( - "/test_metric", - "test_description", - "test_valuedisplayname", - ImmutableSet.of(label), - () -> ImmutableMap.of(ImmutableList.of("foo"), 1L), - Long.class); - - assertThat(testGauge.getValueClass()).isSameAs(Long.class); - assertThat(testGauge.getMetricSchema()) - .isEqualTo( - MetricSchema.create( - "/test_metric", - "test_description", - "test_valuedisplayname", - Kind.GAUGE, - ImmutableSet.of(label))); - } - - @Test - public void testNewCounter_createsCounter() { - IncrementableMetric testCounter = - MetricRegistryImpl.getDefault() - .newIncrementableMetric( - "/test_counter", - "test_description", - "test_valuedisplayname", - ImmutableSet.of(label)); - - assertThat(testCounter.getValueClass()).isSameAs(Long.class); - assertThat(testCounter.getMetricSchema()) - .isEqualTo( - MetricSchema.create( - "/test_counter", - "test_description", - "test_valuedisplayname", - Kind.CUMULATIVE, - ImmutableSet.of(label))); - } - - @Test - public void testNewSettableMetric_createsSettableMetric() { - SettableMetric testMetric = - MetricRegistryImpl.getDefault() - .newSettableMetric( - "/test_metric", - "test_description", - "test_valuedisplayname", - ImmutableSet.of(label), - Boolean.class); - - assertThat(testMetric.getValueClass()).isSameAs(Boolean.class); - assertThat(testMetric.getMetricSchema()) - .isEqualTo( - MetricSchema.create( - "/test_metric", - "test_description", - "test_valuedisplayname", - Kind.GAUGE, - ImmutableSet.of(label))); - } - - @Test - public void testNewEventMetric_createsEventMetric() { - DistributionFitter fitter = CustomFitter.create(ImmutableSet.of(0.0)); - EventMetric testMetric = - MetricRegistryImpl.getDefault() - .newEventMetric( - "/test_metric", - "test_description", - "test_valuedisplayname", - ImmutableSet.of(label), - fitter); - - assertThat(testMetric.getValueClass()).isSameAs(Distribution.class); - assertThat(testMetric.getMetricSchema()) - .isEqualTo( - MetricSchema.create( - "/test_metric", - "test_description", - "test_valuedisplayname", - Kind.CUMULATIVE, - ImmutableSet.of(label))); - } - - @Test - public void testRegister_duplicateMetric_throwsException() { - SettableMetric testMetric = - MetricRegistryImpl.getDefault() - .newSettableMetric( - "/test_metric", - "test_description", - "test_valuedisplayname", - ImmutableSet.of(label), - Boolean.class); - MetricRegistryImpl.getDefault().registerMetric("/test/metric", testMetric); - - IllegalStateException thrown = - expectThrows( - IllegalStateException.class, - () -> MetricRegistryImpl.getDefault().registerMetric("/test/metric", testMetric)); - assertThat(thrown).hasMessageThat().contains("Duplicate metric of same name"); - } -} diff --git a/javatests/google/registry/monitoring/metrics/MetricReporterTest.java b/javatests/google/registry/monitoring/metrics/MetricReporterTest.java deleted file mode 100644 index dfb7dd359..000000000 --- a/javatests/google/registry/monitoring/metrics/MetricReporterTest.java +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright 2017 The Nomulus 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 static org.mockito.Mockito.spy; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableSet; -import java.util.Optional; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.ThreadFactory; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.InOrder; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.mockito.runners.MockitoJUnitRunner; - -/** Unit tests for {@link MetricReporter}. */ -@RunWith(MockitoJUnitRunner.class) -public class MetricReporterTest { - - @Mock MetricRegistry registry; - @Mock Metric metric; - @Mock ThreadFactory threadFactory; - @Mock MetricWriter writer; - @Mock MetricSchema metricSchema; - @Mock BlockingQueue>>> writeQueue; - - @Test - public void testRunOneIteration_enqueuesBatch() throws Exception { - Metric metric = new Counter("/name", "description", "vdn", ImmutableSet.of()); - when(registry.getRegisteredMetrics()).thenReturn(ImmutableList.of(metric, metric)); - MetricReporter reporter = new MetricReporter(writer, 10L, threadFactory, registry, writeQueue); - - reporter.runOneIteration(); - - verify(writeQueue).offer(Optional.of(ImmutableList.of())); - } - - @Test - public void testShutDown_enqueuesBatchAndPoisonPill() throws Exception { - // Set up a registry with no metrics. - when(registry.getRegisteredMetrics()).thenReturn(ImmutableList.of()); - MetricReporter reporter = - spy(new MetricReporter(writer, 10L, threadFactory, registry, writeQueue)); - - reporter.shutDown(); - - verify(reporter).runOneIteration(); - InOrder interactions = Mockito.inOrder(writeQueue); - interactions.verify(writeQueue).offer(Optional.of(ImmutableList.of())); - interactions.verify(writeQueue).offer(Optional.empty()); - } -} diff --git a/javatests/google/registry/monitoring/metrics/MetricSchemaTest.java b/javatests/google/registry/monitoring/metrics/MetricSchemaTest.java deleted file mode 100644 index 34d293604..000000000 --- a/javatests/google/registry/monitoring/metrics/MetricSchemaTest.java +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright 2017 The Nomulus 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 static com.google.common.truth.Truth.assertThat; -import static google.registry.testing.JUnitBackports.expectThrows; - -import com.google.common.collect.ImmutableSet; -import google.registry.monitoring.metrics.MetricSchema.Kind; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Unit tests for {@link MetricSchema}. */ -@RunWith(JUnit4.class) -public class MetricSchemaTest { - - @Test - public void testCreate_blankNameField_throwsException() { - IllegalArgumentException thrown = - expectThrows( - IllegalArgumentException.class, - () -> - MetricSchema.create( - "", - "description", - "valueDisplayName", - Kind.GAUGE, - ImmutableSet.of())); - assertThat(thrown).hasMessageThat().contains("Name must not be blank"); - } - - @Test - public void testCreate_blankDescriptionField_throwsException() { - IllegalArgumentException thrown = - expectThrows( - IllegalArgumentException.class, - () -> - MetricSchema.create( - "/name", "", "valueDisplayName", Kind.GAUGE, ImmutableSet.of())); - assertThat(thrown).hasMessageThat().contains("Description must not be blank"); - } - - @Test - public void testCreate_blankValueDisplayNameField_throwsException() { - IllegalArgumentException thrown = - expectThrows( - IllegalArgumentException.class, - () -> MetricSchema.create("/name", "description", "", Kind.GAUGE, ImmutableSet.of())); - assertThat(thrown).hasMessageThat().contains("Value Display Name must not be empty"); - } - - @Test - public void testCreate_nakedNames_throwsException() { - IllegalArgumentException thrown = - expectThrows( - IllegalArgumentException.class, - () -> - MetricSchema.create( - "foo", "description", "valueDisplayName", Kind.GAUGE, ImmutableSet.of())); - assertThat(thrown).hasMessageThat().contains("Name must be URL-like and start with a '/'"); - } -} diff --git a/javatests/google/registry/monitoring/metrics/MutableDistributionTest.java b/javatests/google/registry/monitoring/metrics/MutableDistributionTest.java deleted file mode 100644 index 02c7dca40..000000000 --- a/javatests/google/registry/monitoring/metrics/MutableDistributionTest.java +++ /dev/null @@ -1,293 +0,0 @@ -// Copyright 2017 The Nomulus 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 static com.google.common.truth.Truth.assertThat; -import static google.registry.testing.JUnitBackports.expectThrows; - -import com.google.common.collect.ImmutableRangeMap; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Range; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Tests for {@link MutableDistribution} */ -@RunWith(JUnit4.class) -public class MutableDistributionTest { - - private MutableDistribution distribution; - @Before - public void setUp() throws Exception { - distribution = new MutableDistribution(CustomFitter.create(ImmutableSet.of(3.0, 5.0))); - } - - @Test - public void testAdd_oneValue() { - distribution.add(5.0); - - assertThat(distribution.count()).isEqualTo(1); - assertThat(distribution.mean()).isWithin(0.0).of(5.0); - assertThat(distribution.sumOfSquaredDeviation()).isWithin(0.0).of(0); - assertThat(distribution.intervalCounts()) - .isEqualTo( - ImmutableRangeMap.builder() - .put(Range.lessThan(3.0), 0L) - .put(Range.closedOpen(3.0, 5.0), 0L) - .put(Range.atLeast(5.0), 1L) - .build()); - } - - @Test - public void testAdd_zero() { - distribution.add(0.0); - - assertThat(distribution.count()).isEqualTo(1); - assertThat(distribution.mean()).isWithin(0.0).of(0.0); - assertThat(distribution.sumOfSquaredDeviation()).isWithin(0.0).of(0); - assertThat(distribution.intervalCounts()) - .isEqualTo( - ImmutableRangeMap.builder() - .put(Range.lessThan(3.0), 1L) - .put(Range.closedOpen(3.0, 5.0), 0L) - .put(Range.atLeast(5.0), 0L) - .build()); - } - - @Test - public void testAdd_multipleOfOneValue() { - distribution.add(4.0, 2); - - assertThat(distribution.count()).isEqualTo(2); - assertThat(distribution.mean()).isWithin(0.0).of(4.0); - assertThat(distribution.sumOfSquaredDeviation()).isWithin(0.0).of(0); - assertThat(distribution.intervalCounts()) - .isEqualTo( - ImmutableRangeMap.builder() - .put(Range.lessThan(3.0), 0L) - .put(Range.closedOpen(3.0, 5.0), 2L) - .put(Range.atLeast(5.0), 0L) - .build()); - } - - @Test - public void testAdd_positiveThenNegativeValue() { - distribution.add(2.0); - distribution.add(-2.0); - - assertThat(distribution.count()).isEqualTo(2); - assertThat(distribution.mean()).isWithin(0.0).of(0.0); - assertThat(distribution.sumOfSquaredDeviation()).isWithin(0.0).of(8.0); - assertThat(distribution.intervalCounts()) - .isEqualTo( - ImmutableRangeMap.builder() - .put(Range.lessThan(3.0), 2L) - .put(Range.closedOpen(3.0, 5.0), 0L) - .put(Range.atLeast(5.0), 0L) - .build()); - } - - @Test - public void testAdd_wideRangeOfValues() { - distribution.add(2.0); - distribution.add(16.0); - distribution.add(128.0, 5); - distribution.add(1024.0, 0); - - assertThat(distribution.count()).isEqualTo(7); - assertThat(distribution.mean()).isWithin(0.0).of(94.0); - assertThat(distribution.sumOfSquaredDeviation()).isWithin(0.0).of(20328.0); - assertThat(distribution.intervalCounts()) - .isEqualTo( - ImmutableRangeMap.builder() - .put(Range.lessThan(3.0), 1L) - .put(Range.closedOpen(3.0, 5.0), 0L) - .put(Range.atLeast(5.0), 6L) - .build()); - } - - @Test - public void testAdd_negativeZero_throwsException() { - IllegalArgumentException thrown = - expectThrows( - IllegalArgumentException.class, - () -> distribution.add(Double.longBitsToDouble(0x80000000))); - assertThat(thrown).hasMessageThat().contains("value must be finite, not NaN, and not -0.0"); - } - - @Test - public void testAdd_NaN_throwsException() { - IllegalArgumentException thrown = - expectThrows(IllegalArgumentException.class, () -> distribution.add(Double.NaN)); - assertThat(thrown).hasMessageThat().contains("value must be finite, not NaN, and not -0.0"); - } - - @Test - public void testAdd_positiveInfinity_throwsException() { - IllegalArgumentException thrown = - expectThrows( - IllegalArgumentException.class, () -> distribution.add(Double.POSITIVE_INFINITY)); - assertThat(thrown).hasMessageThat().contains("value must be finite, not NaN, and not -0.0"); - } - - @Test - public void testAdd_negativeInfinity_throwsException() { - IllegalArgumentException thrown = - expectThrows( - IllegalArgumentException.class, () -> distribution.add(Double.NEGATIVE_INFINITY)); - assertThat(thrown).hasMessageThat().contains("value must be finite, not NaN, and not -0.0"); - } - - @Test - public void testAdd_iteratedFloatingPointValues_hasLowAccumulatedError() { - for (int i = 0; i < 500; i++) { - distribution.add(1 / 3.0); - distribution.add(1 / 7.0); - } - - // Test for nine significant figures of accuracy. - assertThat(distribution.mean()).isWithin(0.000000001).of(5.0 / 21.0); - assertThat(distribution.sumOfSquaredDeviation()) - .isWithin(0.000000001) - .of(1000 * 4.0 / (21.0 * 21.0)); - } - - @Test - public void testAdd_fitterWithNoFiniteIntervals_underflowValue_returnsUnderflowInterval() - throws Exception { - MutableDistribution distribution = - new MutableDistribution(CustomFitter.create(ImmutableSet.of(5.0))); - - distribution.add(3.0); - - assertThat(distribution.intervalCounts()) - .isEqualTo( - ImmutableRangeMap.builder() - .put(Range.lessThan(5.0), 1L) - .put(Range.atLeast(5.0), 0L) - .build()); - } - - @Test - public void testAdd_noFiniteIntervals_overflowValue_returnsOverflowInterval() throws Exception { - MutableDistribution distribution = - new MutableDistribution(CustomFitter.create(ImmutableSet.of(5.0))); - - distribution.add(10.0); - - assertThat(distribution.intervalCounts()) - .isEqualTo( - ImmutableRangeMap.builder() - .put(Range.lessThan(5.0), 0L) - .put(Range.atLeast(5.0), 1L) - .build()); - } - - @Test - public void testAdd_noFiniteIntervals_edgeValue_returnsOverflowInterval() throws Exception { - MutableDistribution distribution = - new MutableDistribution(CustomFitter.create(ImmutableSet.of(2.0))); - - distribution.add(2.0); - - assertThat(distribution.intervalCounts()) - .isEqualTo( - ImmutableRangeMap.builder() - .put(Range.lessThan(2.0), 0L) - .put(Range.atLeast(2.0), 1L) - .build()); - } - - @Test - public void testAdd_oneFiniteInterval_underflowValue_returnsUnderflowInterval() throws Exception { - MutableDistribution distribution = - new MutableDistribution(CustomFitter.create(ImmutableSet.of(1.0, 5.0))); - - distribution.add(0.0); - - assertThat(distribution.intervalCounts()) - .isEqualTo( - ImmutableRangeMap.builder() - .put(Range.lessThan(1.0), 1L) - .put(Range.closedOpen(1.0, 5.0), 0L) - .put(Range.atLeast(5.0), 0L) - .build()); - } - - @Test - public void testAdd_oneFiniteInterval_overflowValue_returnsOverflowInterval() throws Exception { - MutableDistribution distribution = - new MutableDistribution(CustomFitter.create(ImmutableSet.of(1.0, 5.0))); - - distribution.add(10.0); - - assertThat(distribution.intervalCounts()) - .isEqualTo( - ImmutableRangeMap.builder() - .put(Range.lessThan(1.0), 0L) - .put(Range.closedOpen(1.0, 5.0), 0L) - .put(Range.atLeast(5.0), 1L) - .build()); - } - - @Test - public void testAdd_oneFiniteInterval_inBoundsValue_returnsInBoundsInterval() throws Exception { - MutableDistribution distribution = - new MutableDistribution(CustomFitter.create(ImmutableSet.of(1.0, 5.0))); - - distribution.add(3.0); - - assertThat(distribution.intervalCounts()) - .isEqualTo( - ImmutableRangeMap.builder() - .put(Range.lessThan(1.0), 0L) - .put(Range.closedOpen(1.0, 5.0), 1L) - .put(Range.atLeast(5.0), 0L) - .build()); - } - - @Test - public void testAdd_oneFiniteInterval_firstEdgeValue_returnsFiniteInterval() throws Exception { - MutableDistribution distribution = - new MutableDistribution(CustomFitter.create(ImmutableSet.of(1.0, 5.0))); - - distribution.add(1.0); - - assertThat(distribution.intervalCounts()) - .isEqualTo( - ImmutableRangeMap.builder() - .put(Range.lessThan(1.0), 0L) - .put(Range.closedOpen(1.0, 5.0), 1L) - .put(Range.atLeast(5.0), 0L) - .build()); - } - - @Test - public void testAdd_oneFiniteInterval_secondEdgeValue_returnsOverflowInterval() throws Exception { - MutableDistribution distribution = - new MutableDistribution(CustomFitter.create(ImmutableSet.of(1.0, 5.0))); - - distribution.add(5.0); - - assertThat(distribution.intervalCounts()) - .isEqualTo( - ImmutableRangeMap.builder() - .put(Range.lessThan(1.0), 0L) - .put(Range.closedOpen(1.0, 5.0), 0L) - .put(Range.atLeast(5.0), 1L) - .build()); - } -} diff --git a/javatests/google/registry/monitoring/metrics/StoredMetricTest.java b/javatests/google/registry/monitoring/metrics/StoredMetricTest.java deleted file mode 100644 index 6718d3a7a..000000000 --- a/javatests/google/registry/monitoring/metrics/StoredMetricTest.java +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright 2017 The Nomulus 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 static com.google.common.truth.Truth.assertThat; -import static google.registry.testing.JUnitBackports.expectThrows; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableSet; -import org.joda.time.Instant; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Unit tests for {@link StoredMetric}. */ -@RunWith(JUnit4.class) -public class StoredMetricTest { - - @Test - public void testGetCardinality_reflectsCurrentCardinality() { - StoredMetric smallMetric = - new StoredMetric<>("/metric", "description", "vdn", ImmutableSet.of(), Boolean.class); - assertThat(smallMetric.getCardinality()).isEqualTo(0); - - smallMetric.set(true); - - assertThat(smallMetric.getCardinality()).isEqualTo(1); - - StoredMetric dimensionalMetric = - new StoredMetric<>( - "/metric", - "description", - "vdn", - ImmutableSet.of(LabelDescriptor.create("foo", "bar")), - Boolean.class); - - dimensionalMetric.set(true, "test_value1"); - dimensionalMetric.set(true, "test_value2"); - - assertThat(dimensionalMetric.getCardinality()).isEqualTo(2); - } - - @Test - public void testSet_wrongNumberOfLabels_throwsException() { - StoredMetric dimensionalMetric = - new StoredMetric<>( - "/metric", - "description", - "vdn", - ImmutableSet.of( - LabelDescriptor.create("label1", "bar"), LabelDescriptor.create("label2", "bar")), - Boolean.class); - - IllegalArgumentException thrown = - expectThrows(IllegalArgumentException.class, () -> dimensionalMetric.set(true, "foo")); - assertThat(thrown) - .hasMessageThat() - .contains( - "The count of labelValues must be equal to the underlying Metric's count of labels."); - } - - @Test - public void testSet_setsValue() { - StoredMetric metric = - new StoredMetric<>( - "/metric", - "description", - "vdn", - ImmutableSet.of(LabelDescriptor.create("label1", "bar")), - Boolean.class); - - assertThat(metric.getTimestampedValues()).isEmpty(); - - metric.set(true, ImmutableList.of("test_value1")); - assertThat(metric.getTimestampedValues(new Instant(1337))) - .containsExactly( - MetricPoint.create(metric, ImmutableList.of("test_value1"), new Instant(1337), true)); - - metric.set(false, ImmutableList.of("test_value1")); - metric.set(true, ImmutableList.of("test_value2")); - assertThat(metric.getTimestampedValues(new Instant(1338))) - .containsExactly( - MetricPoint.create(metric, ImmutableList.of("test_value1"), new Instant(1338), false), - MetricPoint.create(metric, ImmutableList.of("test_value2"), new Instant(1338), true)); - } -} diff --git a/javatests/google/registry/monitoring/metrics/VirtualMetricTest.java b/javatests/google/registry/monitoring/metrics/VirtualMetricTest.java deleted file mode 100644 index a987f31a6..000000000 --- a/javatests/google/registry/monitoring/metrics/VirtualMetricTest.java +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright 2017 The Nomulus 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 static com.google.common.truth.Truth.assertThat; - -import com.google.common.base.Suppliers; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; -import org.joda.time.Instant; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** Unit tests for {@link VirtualMetric}. */ -@RunWith(JUnit4.class) -public class VirtualMetricTest { - - private final VirtualMetric metric = - new VirtualMetric<>( - "/metric", - "description", - "vdn", - ImmutableSet.of(LabelDescriptor.create("label1", "bar")), - Suppliers.ofInstance( - ImmutableMap.of( - ImmutableList.of("label_value1"), "value1", - ImmutableList.of("label_value2"), "value2")), - String.class); - - @Test - public void testGetCardinality_afterGetTimestampedValues_returnsLastCardinality() { - metric.getTimestampedValues(); - assertThat(metric.getCardinality()).isEqualTo(2); - } - - @Test - public void testGetCardinality_beforeGetTimestampedValues_returnsZero() { - assertThat(metric.getCardinality()).isEqualTo(0); - } - - @Test - public void testGetTimestampedValues_returnsValues() { - assertThat(metric.getTimestampedValues(new Instant(1337))) - .containsExactly( - MetricPoint.create( - metric, ImmutableList.of("label_value1"), new Instant(1337), "value1"), - MetricPoint.create( - metric, ImmutableList.of("label_value2"), new Instant(1337), "value2")); - } -} diff --git a/javatests/google/registry/monitoring/metrics/contrib/BUILD b/javatests/google/registry/monitoring/metrics/contrib/BUILD deleted file mode 100644 index 5d4efe8a7..000000000 --- a/javatests/google/registry/monitoring/metrics/contrib/BUILD +++ /dev/null @@ -1,30 +0,0 @@ -package( - default_testonly = 1, - default_visibility = ["//java/google/registry:registry_project"], -) - -licenses(["notice"]) # Apache 2.0 - -load("//java/com/google/testing/builddefs:GenTestRules.bzl", "GenTestRules") - -java_library( - name = "contrib", - srcs = glob(["*.java"]), - deps = [ - "//java/google/registry/monitoring/metrics", - "//java/google/registry/monitoring/metrics/contrib", - "//third_party/junit", - "@com_google_guava", - "@com_google_truth", - "@com_google_truth_extensions_truth_java8_extension", - "@junit", - ], -) - -GenTestRules( - name = "GeneratedTestRules", - test_files = glob(["*Test.java"]), - deps = [ - ":contrib", - ], -) diff --git a/javatests/google/registry/monitoring/metrics/contrib/DistributionMetricSubjectTest.java b/javatests/google/registry/monitoring/metrics/contrib/DistributionMetricSubjectTest.java deleted file mode 100644 index 832415691..000000000 --- a/javatests/google/registry/monitoring/metrics/contrib/DistributionMetricSubjectTest.java +++ /dev/null @@ -1,189 +0,0 @@ -// Copyright 2017 The Nomulus 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.contrib; - -import static com.google.common.truth.Truth.assertThat; -import static google.registry.monitoring.metrics.contrib.DistributionMetricSubject.assertThat; -import static google.registry.testing.JUnitBackports.expectThrows; - -import com.google.common.collect.ImmutableSet; -import google.registry.monitoring.metrics.EventMetric; -import google.registry.monitoring.metrics.LabelDescriptor; -import google.registry.monitoring.metrics.MetricRegistryImpl; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -@RunWith(JUnit4.class) -public class DistributionMetricSubjectTest { - - private static final ImmutableSet LABEL_DESCRIPTORS = - ImmutableSet.of( - LabelDescriptor.create("species", "Sheep Species"), - LabelDescriptor.create("color", "Sheep Color")); - - private static final EventMetric metric = - MetricRegistryImpl.getDefault() - .newEventMetric( - "/test/event/sheep", - "Sheep Latency", - "sheeplatency", - LABEL_DESCRIPTORS, - EventMetric.DEFAULT_FITTER); - - @Before - public void before() { - metric.reset(); - metric.record(2.5, "Domestic", "Green"); - metric.record(10, "Bighorn", "Blue"); - } - - @Test - public void testWrongNumberOfLabels_fails() { - AssertionError e = - expectThrows( - AssertionError.class, () -> assertThat(metric).hasAnyValueForLabels("Domestic")); - assertThat(e) - .hasMessageThat() - .isEqualTo( - "Not true that has a value for labels ." - + " It has labeled values <[Bighorn:Blue =>" - + " {[4.0..16.0)=1}, Domestic:Green => {[1.0..4.0)=1}]>"); - } - - @Test - public void testDoesNotHaveWrongNumberOfLabels_succeeds() { - assertThat(metric).doesNotHaveAnyValueForLabels("Domestic"); - } - - @Test - public void testHasAnyValueForLabels_success() { - assertThat(metric) - .hasAnyValueForLabels("Domestic", "Green") - .and() - .hasAnyValueForLabels("Bighorn", "Blue") - .and() - .hasNoOtherValues(); - } - - @Test - public void testDoesNotHaveValueForLabels_success() { - assertThat(metric).doesNotHaveAnyValueForLabels("Domestic", "Blue"); - } - - @Test - public void testDoesNotHaveValueForLabels_failure() { - AssertionError e = - expectThrows( - AssertionError.class, - () -> assertThat(metric).doesNotHaveAnyValueForLabels("Domestic", "Green")); - assertThat(e) - .hasMessageThat() - .isEqualTo( - "Not true that has no value for labels ." - + " It has a value of <{[1.0..4.0)=1}>"); - } - - @Test - public void testUnexpectedValue_failure() { - AssertionError e = - expectThrows( - AssertionError.class, - () -> - assertThat(metric) - .hasAnyValueForLabels("Domestic", "Green") - .and() - .hasNoOtherValues()); - assertThat(e) - .hasMessageThat() - .isEqualTo( - "Not true that has ." - + " It has labeled values <[Bighorn:Blue =>" - + " {[4.0..16.0)=1}, Domestic:Green => {[1.0..4.0)=1}]>"); - } - - @Test - public void testExpectedDataSet_success() { - metric.record(7.5, "Domestic", "Green"); - assertThat(metric).hasDataSetForLabels(ImmutableSet.of(2.5, 7.5), "Domestic", "Green"); - } - - @Test - public void testExpectedDataSetsChained_success() { - metric.record(7.5, "Domestic", "Green"); - assertThat(metric) - .hasDataSetForLabels(ImmutableSet.of(2.5, 7.5), "Domestic", "Green") - .and() - .hasDataSetForLabels(ImmutableSet.of(10), "Bighorn", "Blue") - .and() - .hasNoOtherValues(); - } - - @Test - public void testUnexpectedDataSet_failure() { - AssertionError e = - expectThrows( - AssertionError.class, - () -> - assertThat(metric) - .hasDataSetForLabels(ImmutableSet.of(2.5, 7.5), "Domestic", "Green")); - assertThat(e) - .hasMessageThat() - .isEqualTo( - "Not true that has a value of" - + " {[1.0..4.0)=1,[4.0..16.0)=1} for labels ." - + " It has a value of <{[1.0..4.0)=1}>"); - } - - @Test - public void testNonExistentLabels_failure() { - AssertionError e = - expectThrows( - AssertionError.class, - () -> - assertThat(metric) - .hasDataSetForLabels(ImmutableSet.of(2.5, 7.5), "Domestic", "Blue")); - assertThat(e) - .hasMessageThat() - .isEqualTo( - "Not true that has a value for labels ." - + " It has labeled values <[Bighorn:Blue => {[4.0..16.0)=1}," - + " Domestic:Green => {[1.0..4.0)=1}]>"); - } - - @Test - public void testEmptyMetric_failure() { - EventMetric emptyMetric = - MetricRegistryImpl.getDefault() - .newEventMetric( - "/test/event/goat", - "Sheep Latency", - "sheeplatency", - LABEL_DESCRIPTORS, - EventMetric.DEFAULT_FITTER); - AssertionError e = - expectThrows( - AssertionError.class, - () -> - assertThat(emptyMetric) - .hasDataSetForLabels(ImmutableSet.of(2.5, 7.5), "Domestic", "Blue")); - assertThat(e) - .hasMessageThat() - .isEqualTo( - "Not true that has a distribution for labels ." - + " It has "); - } -} diff --git a/javatests/google/registry/monitoring/metrics/contrib/LongMetricSubjectTest.java b/javatests/google/registry/monitoring/metrics/contrib/LongMetricSubjectTest.java deleted file mode 100644 index 0e4155274..000000000 --- a/javatests/google/registry/monitoring/metrics/contrib/LongMetricSubjectTest.java +++ /dev/null @@ -1,137 +0,0 @@ -// Copyright 2017 The Nomulus 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.contrib; - -import static com.google.common.truth.Truth.assertThat; -import static google.registry.monitoring.metrics.contrib.LongMetricSubject.assertThat; -import static google.registry.testing.JUnitBackports.expectThrows; - -import com.google.common.collect.ImmutableSet; -import google.registry.monitoring.metrics.IncrementableMetric; -import google.registry.monitoring.metrics.LabelDescriptor; -import google.registry.monitoring.metrics.MetricRegistryImpl; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -@RunWith(JUnit4.class) -public class LongMetricSubjectTest { - - private static final ImmutableSet LABEL_DESCRIPTORS = - ImmutableSet.of( - LabelDescriptor.create("species", "Sheep Species"), - LabelDescriptor.create("color", "Sheep Color")); - - private static final IncrementableMetric metric = - MetricRegistryImpl.getDefault() - .newIncrementableMetric( - "/test/incrementable/sheep", - "Count of Sheep", - "sheepcount", - LABEL_DESCRIPTORS); - - @Before - public void before() { - metric.reset(); - metric.increment("Domestic", "Green"); - metric.incrementBy(2, "Bighorn", "Blue"); - } - - @Test - public void testWrongNumberOfLabels_fails() { - AssertionError e = - expectThrows( - AssertionError.class, () -> assertThat(metric).hasValueForLabels(1, "Domestic")); - assertThat(e) - .hasMessageThat() - .isEqualTo( - "Not true that has a value for labels ." - + " It has labeled values <[Bighorn:Blue => 2, Domestic:Green => 1]>"); - } - - @Test - public void testDoesNotHaveWrongNumberOfLabels_succeeds() { - assertThat(metric).doesNotHaveAnyValueForLabels("Domestic"); - } - - @Test - public void testHasValueForLabels_success() { - assertThat(metric) - .hasValueForLabels(1, "Domestic", "Green") - .and() - .hasValueForLabels(2, "Bighorn", "Blue") - .and() - .hasNoOtherValues(); - } - - @Test - public void testHasAnyValueForLabels_success() { - assertThat(metric) - .hasAnyValueForLabels("Domestic", "Green") - .and() - .hasAnyValueForLabels("Bighorn", "Blue") - .and() - .hasNoOtherValues(); - } - - @Test - public void testDoesNotHaveValueForLabels_success() { - assertThat(metric).doesNotHaveAnyValueForLabels("Domestic", "Blue"); - } - - @Test - public void testDoesNotHaveValueForLabels_failure() { - AssertionError e = - expectThrows( - AssertionError.class, - () -> assertThat(metric).doesNotHaveAnyValueForLabels("Domestic", "Green")); - assertThat(e) - .hasMessageThat() - .isEqualTo( - "Not true that has no value for labels ." - + " It has a value of <1>"); - } - - @Test - public void testWrongValue_failure() { - AssertionError e = - expectThrows( - AssertionError.class, - () -> assertThat(metric).hasValueForLabels(2, "Domestic", "Green")); - assertThat(e) - .hasMessageThat() - .isEqualTo( - "Not true that has a value of 2" - + " for labels . It has a value of <1>"); - } - - @Test - public void testUnexpectedValue_failure() { - AssertionError e = - expectThrows( - AssertionError.class, - () -> - assertThat(metric) - .hasValueForLabels(1, "Domestic", "Green") - .and() - .hasNoOtherValues()); - assertThat(e) - .hasMessageThat() - .isEqualTo( - "Not true that has ." - + " It has labeled values <[Bighorn:Blue => 2, Domestic:Green => 1]>"); - } -} diff --git a/javatests/google/registry/monitoring/metrics/example/BUILD b/javatests/google/registry/monitoring/metrics/example/BUILD deleted file mode 100644 index ff6127479..000000000 --- a/javatests/google/registry/monitoring/metrics/example/BUILD +++ /dev/null @@ -1,19 +0,0 @@ -package( - default_visibility = ["//java/google/registry:registry_project"], -) - -licenses(["notice"]) # Apache 2.0 - -java_binary( - name = "SheepCounterExample", - srcs = ["SheepCounterExample.java"], - deps = [ - "//java/google/registry/monitoring/metrics", - "//java/google/registry/monitoring/metrics/stackdriver", - "@com_google_api_client", - "@com_google_apis_google_api_services_monitoring", - "@com_google_guava", - "@com_google_http_client", - "@com_google_http_client_jackson2", - ], -) diff --git a/javatests/google/registry/monitoring/metrics/example/SheepCounterExample.java b/javatests/google/registry/monitoring/metrics/example/SheepCounterExample.java deleted file mode 100644 index 58cfd56df..000000000 --- a/javatests/google/registry/monitoring/metrics/example/SheepCounterExample.java +++ /dev/null @@ -1,259 +0,0 @@ -// Copyright 2017 The Nomulus 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.example; - -import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; -import com.google.api.client.http.HttpTransport; -import com.google.api.client.http.javanet.NetHttpTransport; -import com.google.api.client.json.JsonFactory; -import com.google.api.client.json.jackson2.JacksonFactory; -import com.google.api.services.monitoring.v3.Monitoring; -import com.google.api.services.monitoring.v3.MonitoringScopes; -import com.google.api.services.monitoring.v3.model.MonitoredResource; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; -import google.registry.monitoring.metrics.EventMetric; -import google.registry.monitoring.metrics.IncrementableMetric; -import google.registry.monitoring.metrics.LabelDescriptor; -import google.registry.monitoring.metrics.LinearFitter; -import google.registry.monitoring.metrics.Metric; -import google.registry.monitoring.metrics.MetricRegistryImpl; -import google.registry.monitoring.metrics.MetricReporter; -import google.registry.monitoring.metrics.MetricWriter; -import google.registry.monitoring.metrics.SettableMetric; -import google.registry.monitoring.metrics.stackdriver.StackdriverWriter; -import java.io.IOException; -import java.util.Random; -import java.util.concurrent.Executors; -import java.util.logging.Handler; -import java.util.logging.Level; -import java.util.logging.LogManager; -import java.util.logging.Logger; - -/** A sample application which uses the Metrics API to count sheep while sleeping. */ -public final class SheepCounterExample { - - /* - * The code below for using a custom {@link LogManager} is only necessary to enable logging at JVM - * shutdown to show the shutdown logs of {@link MetricReporter} in this small standalone - * application. - * - *

It is NOT necessary for normal use of the Metrics library. - */ - static { - // must be called before any Logger method is used. - System.setProperty("java.util.logging.manager", DelayedShutdownLogManager.class.getName()); - } - - private static final Logger logger = Logger.getLogger(SheepCounterExample.class.getName()); - - /** - * The time interval, in seconds, between when the {@link MetricReporter} will read {@link Metric} - * instances and enqueue them to the {@link MetricWriter}. - * - * @see MetricReporter - */ - private static final long METRICS_REPORTING_INTERVAL = 30L; - - /** - * The maximum queries per second to the Stackdriver API. Contact Cloud Support to raise this from - * the default value if necessary. - */ - private static final int STACKDRIVER_MAX_QPS = 30; - - /** - * The maximum number of {@link com.google.api.services.monitoring.v3.model.TimeSeries} that can - * be bundled into a single {@link - * com.google.api.services.monitoring.v3.model.CreateTimeSeriesRequest}. This must be at most 200. - * Setting this lower will cause the {@link StackdriverWriter} to {@link - * StackdriverWriter#flush()} more frequently. - */ - private static final int STACKDRIVER_MAX_POINTS_PER_REQUEST = 200; - - // Create some metrics to track your ZZZs. - private static final ImmutableList SHEEP_COLORS = - ImmutableList.of("Green", "Yellow", "Red", "Blue"); - private static final ImmutableList SHEEP_SPECIES = - ImmutableList.of("Domestic", "Bighorn"); - private static final ImmutableSet SHEEP_ATTRIBUTES = - ImmutableSet.of( - LabelDescriptor.create("color", "Sheep Color"), - LabelDescriptor.create("species", "Sheep Species")); - - /** - * Counters are good for tracking monotonically increasing values, like request counts or error - * counts. Or, in this case, sheep. - */ - private static final IncrementableMetric sheepCounter = - MetricRegistryImpl.getDefault() - .newIncrementableMetric( - "/sheep", "Counts sheep over time.", "Number of Sheep", SHEEP_ATTRIBUTES); - - /** - * Settable metrics are good for state indicators. For example, you could use one to track the - * lifecycle of a {@link com.google.common.util.concurrent.Service}. In this case, we are just - * using it to track the sleep state of this application. - */ - private static final SettableMetric isSleeping = - MetricRegistryImpl.getDefault() - .newSettableMetric( - "/is_sleeping", - "Tracks sleep state.", - "Sleeping?", - ImmutableSet.of(), - Boolean.class); - - /** - * Gauge metrics never need to be accessed, so the assignment here is unnecessary. You only need - * it if you plan on calling {@link Metric#getTimestampedValues()} to read the values of the - * metric in the code yourself. - */ - @SuppressWarnings("unused") - private static final Metric sleepQuality = - MetricRegistryImpl.getDefault() - .newGauge( - "/sleep_quality", - "Quality of the sleep.", - "Quality", - ImmutableSet.of(), - () -> ImmutableMap.of(ImmutableList.of(), new Random().nextDouble()), - Double.class); - - /** - * Event metrics track aspects of an "event." Here, we track the fluffiness of the sheep we've - * seen. - */ - private static final EventMetric sheepFluffiness = - MetricRegistryImpl.getDefault() - .newEventMetric( - "/sheep_fluffiness", - "Measures the fluffiness of seen sheep.", - "Fill Power", - SHEEP_ATTRIBUTES, - LinearFitter.create(5, 20.0, 20.0)); - - private static Monitoring createAuthorizedMonitoringClient() throws IOException { - // Grab the Application Default Credentials from the environment. - // Generate these with 'gcloud beta auth application-default login' - GoogleCredential credential = - GoogleCredential.getApplicationDefault().createScoped(MonitoringScopes.all()); - - // Create and return the CloudMonitoring service object - HttpTransport httpTransport = new NetHttpTransport(); - JsonFactory jsonFactory = new JacksonFactory(); - return new Monitoring.Builder(httpTransport, jsonFactory, credential) - .setApplicationName("Monitoring Sample") - .build(); - } - - public static void main(String[] args) throws Exception { - if (args.length < 1) { - System.err.println("Missing required project argument"); - System.err.printf( - "Usage: java %s gcp-project-id [verbose]\n", SheepCounterExample.class.getName()); - return; - } - String project = args[0]; - - // Turn up the logging verbosity - if (args.length > 1) { - Logger log = LogManager.getLogManager().getLogger(""); - log.setLevel(Level.ALL); - for (Handler h : log.getHandlers()) { - h.setLevel(Level.ALL); - } - } - - // Create a sample resource. In this case, a GCE Instance. - // See https://cloud.google.com/monitoring/api/resources for a list of resource types. - MonitoredResource monitoredResource = - new MonitoredResource() - .setType("gce_instance") - .setLabels( - ImmutableMap.of( - "instance_id", "test-instance", - "zone", "us-central1-f")); - - // Set up the Metrics infrastructure. - MetricWriter stackdriverWriter = - new StackdriverWriter( - createAuthorizedMonitoringClient(), - project, - monitoredResource, - STACKDRIVER_MAX_QPS, - STACKDRIVER_MAX_POINTS_PER_REQUEST); - final MetricReporter reporter = - new MetricReporter( - stackdriverWriter, METRICS_REPORTING_INTERVAL, Executors.defaultThreadFactory()); - reporter.startAsync().awaitRunning(); - - // Set up a handler to stop sleeping on SIGINT. - Runtime.getRuntime() - .addShutdownHook( - new Thread( - () -> { - reporter.stopAsync().awaitTerminated(); - // Allow the LogManager to cleanup the loggers. - DelayedShutdownLogManager.resetFinally(); - })); - - System.err.println("Send SIGINT (Ctrl+C) to stop sleeping."); - while (true) { - // Count some Googley sheep. - int colorIndex = new Random().nextInt(SHEEP_COLORS.size()); - int speciesIndex = new Random().nextInt(SHEEP_SPECIES.size()); - sheepCounter.incrementBy(1, SHEEP_COLORS.get(colorIndex), SHEEP_SPECIES.get(speciesIndex)); - sheepFluffiness.record( - new Random().nextDouble() * 200, - SHEEP_COLORS.get(colorIndex), - SHEEP_SPECIES.get(speciesIndex)); - isSleeping.set(true); - - logger.info("zzz..."); - Thread.sleep(5000); - } - } - - /** - * Special {@link LogManager} with a no-op {@link LogManager#reset()} so that logging can proceed - * as usual until stopped in in another runtime shutdown hook. - * - *

The class is marked public because it is loaded by the JVM classloader at runtime. - */ - @SuppressWarnings("WeakerAccess") - public static class DelayedShutdownLogManager extends LogManager { - - private static DelayedShutdownLogManager instance; - - public DelayedShutdownLogManager() { - instance = this; - } - - /** A no-op implementation. */ - @Override - public void reset() { - /* don't reset yet. */ - } - - static void resetFinally() { - instance.delayedReset(); - } - - private void delayedReset() { - super.reset(); - } - } -} diff --git a/javatests/google/registry/monitoring/metrics/stackdriver/BUILD b/javatests/google/registry/monitoring/metrics/stackdriver/BUILD deleted file mode 100644 index 593d4724b..000000000 --- a/javatests/google/registry/monitoring/metrics/stackdriver/BUILD +++ /dev/null @@ -1,36 +0,0 @@ -package( - default_testonly = 1, - default_visibility = ["//java/google/registry:registry_project"], -) - -licenses(["notice"]) # Apache 2.0 - -load("//java/com/google/testing/builddefs:GenTestRules.bzl", "GenTestRules") - -java_library( - name = "stackdriver", - srcs = glob(["*.java"]), - deps = [ - "//java/google/registry/monitoring/metrics", - "//java/google/registry/monitoring/metrics/stackdriver", - "//third_party/junit", - "@com_google_api_client", - "@com_google_apis_google_api_services_monitoring", - "@com_google_guava", - "@com_google_http_client", - "@com_google_http_client_jackson2", - "@com_google_truth", - "@com_google_truth_extensions_truth_java8_extension", - "@joda_time", - "@junit", - "@org_mockito_all", - ], -) - -GenTestRules( - name = "GeneratedTestRules", - test_files = glob(["*Test.java"]), - deps = [ - ":stackdriver", - ], -) diff --git a/javatests/google/registry/monitoring/metrics/stackdriver/GoogleJsonResponseExceptionHelper.java b/javatests/google/registry/monitoring/metrics/stackdriver/GoogleJsonResponseExceptionHelper.java deleted file mode 100644 index d8d129ae8..000000000 --- a/javatests/google/registry/monitoring/metrics/stackdriver/GoogleJsonResponseExceptionHelper.java +++ /dev/null @@ -1,171 +0,0 @@ -// Copyright 2017 The Nomulus 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.stackdriver; - -import com.google.api.client.googleapis.json.GoogleJsonResponseException; -import com.google.api.client.http.GenericUrl; -import com.google.api.client.http.HttpContent; -import com.google.api.client.http.HttpRequest; -import com.google.api.client.http.HttpRequestFactory; -import com.google.api.client.http.HttpResponse; -import com.google.api.client.http.HttpTransport; -import com.google.api.client.http.LowLevelHttpRequest; -import com.google.api.client.http.LowLevelHttpResponse; -import com.google.api.client.json.jackson2.JacksonFactory; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; - -/** A helper to create instances of {@link GoogleJsonResponseException}. */ -public class GoogleJsonResponseExceptionHelper { - /** - * @param statusCode the status code that should be in the returned {@link - * GoogleJsonResponseException} - * @return a {@link GoogleJsonResponseException} with the status code {@code statusCode} - * @throws IOException shouldn't occur - */ - public static GoogleJsonResponseException create(int statusCode) throws IOException { - HttpResponse response = createHttpResponse(statusCode, null); - return GoogleJsonResponseException.from(new JacksonFactory(), response); - } - - public static HttpResponse createHttpResponse(int statusCode, InputStream content) - throws IOException { - FakeHttpTransport transport = new FakeHttpTransport(statusCode, content); - HttpRequestFactory factory = transport.createRequestFactory(); - HttpRequest request = - factory.buildRequest( - "foo", new GenericUrl("http://example.com/bar"), new EmptyHttpContent()); - request.setThrowExceptionOnExecuteError(false); - return request.execute(); - } - - private static class FakeHttpTransport extends HttpTransport { - private final int statusCode; - private final InputStream content; - - FakeHttpTransport(int statusCode, InputStream content) { - this.statusCode = statusCode; - this.content = content; - } - - @Override - protected LowLevelHttpRequest buildRequest(String method, String url) throws IOException { - return new FakeLowLevelHttpRequest(statusCode, content); - } - } - - private static class FakeLowLevelHttpRequest extends LowLevelHttpRequest { - private final int statusCode; - private final InputStream content; - - FakeLowLevelHttpRequest(int statusCode, InputStream content) { - this.statusCode = statusCode; - this.content = content; - } - - @Override - public void addHeader(String name, String value) throws IOException { - // Nothing! - } - - @Override - public LowLevelHttpResponse execute() throws IOException { - return new FakeLowLevelHttpResponse(statusCode, content); - } - } - - private static class FakeLowLevelHttpResponse extends LowLevelHttpResponse { - private final int statusCode; - private final InputStream content; - - FakeLowLevelHttpResponse(int statusCode, InputStream content) { - this.statusCode = statusCode; - this.content = content; - } - - @Override - public InputStream getContent() throws IOException { - return content; - } - - @Override - public String getContentEncoding() throws IOException { - return null; - } - - @Override - public long getContentLength() throws IOException { - return 0; - } - - @Override - public String getContentType() throws IOException { - return "text/json"; - } - - @Override - public String getStatusLine() throws IOException { - return null; - } - - @Override - public int getStatusCode() throws IOException { - return statusCode; - } - - @Override - public String getReasonPhrase() throws IOException { - return null; - } - - @Override - public int getHeaderCount() throws IOException { - return 0; - } - - @Override - public String getHeaderName(int index) throws IOException { - return null; - } - - @Override - public String getHeaderValue(int index) throws IOException { - return null; - } - } - - private static class EmptyHttpContent implements HttpContent { - @Override - public long getLength() throws IOException { - return 0; - } - - @Override - public String getType() { - return "text/json"; - } - - @Override - public boolean retrySupported() { - return false; - } - - @Override - public void writeTo(OutputStream out) throws IOException { - // Nothing! - } - } -} diff --git a/javatests/google/registry/monitoring/metrics/stackdriver/StackdriverWriterTest.java b/javatests/google/registry/monitoring/metrics/stackdriver/StackdriverWriterTest.java deleted file mode 100644 index 6becb8c92..000000000 --- a/javatests/google/registry/monitoring/metrics/stackdriver/StackdriverWriterTest.java +++ /dev/null @@ -1,548 +0,0 @@ -// Copyright 2017 The Nomulus 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.stackdriver; - -import static com.google.common.truth.Truth.assertThat; -import static google.registry.testing.JUnitBackports.assertThrows; -import static java.nio.charset.StandardCharsets.UTF_8; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyString; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import com.google.api.client.googleapis.json.GoogleJsonResponseException; -import com.google.api.client.http.HttpResponse; -import com.google.api.client.http.HttpResponseException; -import com.google.api.services.monitoring.v3.Monitoring; -import com.google.api.services.monitoring.v3.model.BucketOptions; -import com.google.api.services.monitoring.v3.model.CreateTimeSeriesRequest; -import com.google.api.services.monitoring.v3.model.Explicit; -import com.google.api.services.monitoring.v3.model.Exponential; -import com.google.api.services.monitoring.v3.model.Linear; -import com.google.api.services.monitoring.v3.model.MetricDescriptor; -import com.google.api.services.monitoring.v3.model.MonitoredResource; -import com.google.api.services.monitoring.v3.model.Point; -import com.google.api.services.monitoring.v3.model.TimeSeries; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableSet; -import google.registry.monitoring.metrics.CustomFitter; -import google.registry.monitoring.metrics.Distribution; -import google.registry.monitoring.metrics.ExponentialFitter; -import google.registry.monitoring.metrics.LabelDescriptor; -import google.registry.monitoring.metrics.LinearFitter; -import google.registry.monitoring.metrics.Metric; -import google.registry.monitoring.metrics.MetricPoint; -import google.registry.monitoring.metrics.MetricSchema; -import google.registry.monitoring.metrics.MetricSchema.Kind; -import google.registry.monitoring.metrics.MutableDistribution; -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.util.List; -import org.joda.time.Instant; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.runners.MockitoJUnitRunner; -import org.mockito.stubbing.Answer; - -/** Unit tests for {@link StackdriverWriter}. */ -@RunWith(MockitoJUnitRunner.class) -public class StackdriverWriterTest { - - @Mock private Monitoring client; - @Mock private Monitoring.Projects projects; - @Mock private Monitoring.Projects.MetricDescriptors metricDescriptors; - @Mock private Monitoring.Projects.MetricDescriptors.Get metricDescriptorGet; - @Mock private Monitoring.Projects.TimeSeries timeSeries; - @Mock private Monitoring.Projects.MetricDescriptors.Create metricDescriptorCreate; - @Mock private Monitoring.Projects.TimeSeries.Create timeSeriesCreate; - @Mock private Metric metric; - @Mock private Metric boolMetric; - @Mock private Metric distributionMetric; - private static final String PROJECT = "PROJECT"; - private static final int MAX_QPS = 10; - private static final int MAX_POINTS_PER_REQUEST = 10; - private static final MonitoredResource MONITORED_RESOURCE = new MonitoredResource(); - - @Before - public void setUp() throws Exception { - when(metric.getValueClass()).thenReturn(Long.class); - when(metric.getCardinality()).thenReturn(1); - when(metric.getMetricSchema()) - .thenReturn( - MetricSchema.create( - "/name", - "desc", - "vdn", - Kind.CUMULATIVE, - ImmutableSet.of(LabelDescriptor.create("label1", "desc1")))); - // Store in an intermediate value, because Mockito hates when mocks are evaluated inside of - // thenReturn() methods. - MetricPoint longPoint = - MetricPoint.create( - metric, ImmutableList.of("value1"), new Instant(1337), new Instant(1338), 5L); - when(metric.getTimestampedValues()).thenReturn(ImmutableList.of(longPoint)); - - when(boolMetric.getValueClass()).thenReturn(Boolean.class); - when(boolMetric.getMetricSchema()) - .thenReturn( - MetricSchema.create( - "/name", - "desc", - "vdn", - Kind.GAUGE, - ImmutableSet.of(LabelDescriptor.create("label1", "desc1")))); - // Store in an intermediate value, because Mockito hates when mocks are evaluated inside of - // thenReturn() methods. - MetricPoint boolPoint = - MetricPoint.create(boolMetric, ImmutableList.of("foo"), new Instant(1337), true); - when(boolMetric.getTimestampedValues()).thenReturn(ImmutableList.of(boolPoint)); - - when(distributionMetric.getMetricSchema()) - .thenReturn( - MetricSchema.create( - "/name", - "desc", - "vdn", - Kind.GAUGE, - ImmutableSet.of(LabelDescriptor.create("label1", "desc1")))); - when(distributionMetric.getValueClass()).thenReturn(Distribution.class); - - MetricDescriptor descriptor = StackdriverWriter.encodeMetricDescriptor(metric); - when(client.projects()).thenReturn(projects); - when(projects.metricDescriptors()).thenReturn(metricDescriptors); - when(projects.timeSeries()).thenReturn(timeSeries); - when(metricDescriptors.create(anyString(), any(MetricDescriptor.class))) - .thenReturn(metricDescriptorCreate); - when(metricDescriptorCreate.execute()).thenReturn(descriptor); - when(metricDescriptors.get(anyString())).thenReturn(metricDescriptorGet); - when(metricDescriptorGet.execute()).thenReturn(descriptor); - when(timeSeries.create(anyString(), any(CreateTimeSeriesRequest.class))) - .thenReturn(timeSeriesCreate); - } - - @Test - public void testWrite_maxPoints_flushes() throws Exception { - StackdriverWriter writer = - spy( - new StackdriverWriter( - client, PROJECT, MONITORED_RESOURCE, MAX_QPS, MAX_POINTS_PER_REQUEST)); - - - for (int i = 0; i < MAX_POINTS_PER_REQUEST; i++) { - for (MetricPoint point : metric.getTimestampedValues()) { - writer.write(point); - } - } - - verify(writer).flush(); - } - - @Test - public void testWrite_lessThanMaxPoints_doesNotFlush() throws Exception { - StackdriverWriter writer = - spy( - new StackdriverWriter( - client, PROJECT, MONITORED_RESOURCE, MAX_QPS, MAX_POINTS_PER_REQUEST)); - for (int i = 0; i < MAX_POINTS_PER_REQUEST - 1; i++) { - for (MetricPoint point : metric.getTimestampedValues()) { - writer.write(point); - } - } - - verify(writer, never()).flush(); - } - - @Test - public void testWrite_invalidMetricType_throwsException() throws Exception { - when(metric.getValueClass()).thenAnswer((Answer>) invocation -> Object.class); - StackdriverWriter writer = - new StackdriverWriter(client, PROJECT, MONITORED_RESOURCE, MAX_QPS, MAX_POINTS_PER_REQUEST); - - for (MetricPoint point : metric.getTimestampedValues()) { - assertThrows(IOException.class, () -> writer.write(point)); - } - } - - @Test - public void testWrite_ManyPoints_flushesTwice() throws Exception { - StackdriverWriter writer = - spy( - new StackdriverWriter( - client, PROJECT, MONITORED_RESOURCE, MAX_QPS, MAX_POINTS_PER_REQUEST)); - - for (int i = 0; i < MAX_POINTS_PER_REQUEST * 2; i++) { - for (MetricPoint point : metric.getTimestampedValues()) { - writer.write(point); - } - } - - verify(writer, times(2)).flush(); - } - - @Test - public void testRegisterMetric_registersWithStackdriver() throws Exception { - StackdriverWriter writer = - new StackdriverWriter(client, PROJECT, MONITORED_RESOURCE, MAX_QPS, MAX_POINTS_PER_REQUEST); - - writer.registerMetric(metric); - - verify( - client - .projects() - .metricDescriptors() - .create(PROJECT, StackdriverWriter.encodeMetricDescriptor(metric))) - .execute(); - } - - @Test - public void registerMetric_doesNotReregisterDupe() throws Exception { - StackdriverWriter writer = - new StackdriverWriter(client, PROJECT, MONITORED_RESOURCE, MAX_QPS, MAX_POINTS_PER_REQUEST); - - writer.registerMetric(metric); - writer.registerMetric(metric); - - verify( - client - .projects() - .metricDescriptors() - .create(PROJECT, StackdriverWriter.encodeMetricDescriptor(metric))) - .execute(); - } - - @Test - public void registerMetric_fetchesStackdriverDefinition() throws Exception { - // Stackdriver throws an Exception with the status message "ALREADY_EXISTS" when you try to - // register a metric that's already been registered, so we fake one here. - ByteArrayInputStream inputStream = new ByteArrayInputStream("".getBytes(UTF_8)); - HttpResponse response = GoogleJsonResponseExceptionHelper.createHttpResponse(400, inputStream); - HttpResponseException.Builder httpResponseExceptionBuilder = - new HttpResponseException.Builder(response); - httpResponseExceptionBuilder.setStatusCode(400); - httpResponseExceptionBuilder.setStatusMessage("ALREADY_EXISTS"); - GoogleJsonResponseException exception = - new GoogleJsonResponseException(httpResponseExceptionBuilder, null); - when(metricDescriptorCreate.execute()).thenThrow(exception); - StackdriverWriter writer = - new StackdriverWriter(client, PROJECT, MONITORED_RESOURCE, MAX_QPS, MAX_POINTS_PER_REQUEST); - - writer.registerMetric(metric); - - verify(client.projects().metricDescriptors().get("metric")).execute(); - } - - @Test - public void registerMetric_rethrowsException() throws Exception { - ByteArrayInputStream inputStream = new ByteArrayInputStream("".getBytes(UTF_8)); - HttpResponse response = GoogleJsonResponseExceptionHelper.createHttpResponse(400, inputStream); - HttpResponseException.Builder httpResponseExceptionBuilder = - new HttpResponseException.Builder(response); - httpResponseExceptionBuilder.setStatusCode(404); - GoogleJsonResponseException exception = - new GoogleJsonResponseException(httpResponseExceptionBuilder, null); - when(metricDescriptorCreate.execute()).thenThrow(exception); - StackdriverWriter writer = - new StackdriverWriter(client, PROJECT, MONITORED_RESOURCE, MAX_QPS, MAX_POINTS_PER_REQUEST); - - assertThrows(GoogleJsonResponseException.class, () -> writer.registerMetric(metric)); - assertThat(exception.getStatusCode()).isEqualTo(404); - } - - @Test - public void getEncodedTimeSeries_nullLabels_encodes() throws Exception { - ByteArrayInputStream inputStream = new ByteArrayInputStream("".getBytes(UTF_8)); - HttpResponse response = GoogleJsonResponseExceptionHelper.createHttpResponse(400, inputStream); - HttpResponseException.Builder httpResponseExceptionBuilder = - new HttpResponseException.Builder(response); - httpResponseExceptionBuilder.setStatusCode(400); - httpResponseExceptionBuilder.setStatusMessage("ALREADY_EXISTS"); - GoogleJsonResponseException exception = - new GoogleJsonResponseException(httpResponseExceptionBuilder, null); - when(metricDescriptorCreate.execute()).thenThrow(exception); - when(metricDescriptorGet.execute()) - .thenReturn(new MetricDescriptor().setName("foo").setLabels(null)); - StackdriverWriter writer = - new StackdriverWriter(client, PROJECT, MONITORED_RESOURCE, MAX_QPS, MAX_POINTS_PER_REQUEST); - writer.registerMetric(metric); - - TimeSeries timeSeries = - writer.getEncodedTimeSeries( - MetricPoint.create(metric, ImmutableList.of("foo"), new Instant(1337), 10L)); - - assertThat(timeSeries.getMetric().getLabels()).isEmpty(); - } - - @Test - public void encodeMetricDescriptor_simpleMetric_encodes() { - MetricDescriptor descriptor = StackdriverWriter.encodeMetricDescriptor(metric); - - assertThat(descriptor.getType()).isEqualTo("custom.googleapis.com/name"); - assertThat(descriptor.getValueType()).isEqualTo("INT64"); - assertThat(descriptor.getDescription()).isEqualTo("desc"); - assertThat(descriptor.getDisplayName()).isEqualTo("vdn"); - assertThat(descriptor.getLabels()) - .containsExactly( - new com.google.api.services.monitoring.v3.model.LabelDescriptor() - .setValueType("STRING") - .setKey("label1") - .setDescription("desc1")); - } - - @Test - public void encodeLabelDescriptors_simpleLabels_encodes() { - ImmutableSet descriptors = - ImmutableSet.of( - LabelDescriptor.create("label1", "description1"), - LabelDescriptor.create("label2", "description2")); - - ImmutableList encodedDescritors = - StackdriverWriter.encodeLabelDescriptors(descriptors); - - assertThat(encodedDescritors) - .containsExactly( - new com.google.api.services.monitoring.v3.model.LabelDescriptor() - .setValueType("STRING") - .setKey("label1") - .setDescription("description1"), - new com.google.api.services.monitoring.v3.model.LabelDescriptor() - .setValueType("STRING") - .setKey("label2") - .setDescription("description2")); - } - - @Test - public void getEncodedTimeSeries_cumulativeMetricPoint_ZeroInterval_encodesGreaterEndTime() - throws Exception { - StackdriverWriter writer = - new StackdriverWriter(client, PROJECT, MONITORED_RESOURCE, MAX_QPS, MAX_POINTS_PER_REQUEST); - MetricPoint nativePoint = - MetricPoint.create( - metric, ImmutableList.of("foo"), new Instant(1337), new Instant(1337), 10L); - - TimeSeries timeSeries = writer.getEncodedTimeSeries(nativePoint); - - assertThat(timeSeries.getValueType()).isEqualTo("INT64"); - assertThat(timeSeries.getMetricKind()).isEqualTo("CUMULATIVE"); - List points = timeSeries.getPoints(); - assertThat(points).hasSize(1); - Point point = points.get(0); - assertThat(point.getValue().getInt64Value()).isEqualTo(10L); - assertThat(point.getInterval().getStartTime()).isEqualTo("1970-01-01T00:00:01.337Z"); - assertThat(point.getInterval().getEndTime()).isEqualTo("1970-01-01T00:00:01.338Z"); - } - - @Test - public void getEncodedTimeSeries_cumulativeMetricPoint_nonZeroInterval_encodesSameInterval() - throws Exception { - StackdriverWriter writer = - new StackdriverWriter(client, PROJECT, MONITORED_RESOURCE, MAX_QPS, MAX_POINTS_PER_REQUEST); - MetricPoint nativePoint = - MetricPoint.create( - metric, ImmutableList.of("foo"), new Instant(1337), new Instant(1339), 10L); - - TimeSeries timeSeries = writer.getEncodedTimeSeries(nativePoint); - - assertThat(timeSeries.getValueType()).isEqualTo("INT64"); - assertThat(timeSeries.getMetricKind()).isEqualTo("CUMULATIVE"); - List points = timeSeries.getPoints(); - assertThat(points).hasSize(1); - Point point = points.get(0); - assertThat(point.getValue().getInt64Value()).isEqualTo(10L); - assertThat(point.getInterval().getStartTime()).isEqualTo("1970-01-01T00:00:01.337Z"); - assertThat(point.getInterval().getEndTime()).isEqualTo("1970-01-01T00:00:01.339Z"); - } - - @Test - public void getEncodedTimeSeries_gaugeMetricPoint_zeroInterval_encodesSameInterval() - throws Exception { - when(metric.getMetricSchema()) - .thenReturn( - MetricSchema.create( - "/name", - "desc", - "vdn", - Kind.GAUGE, - ImmutableSet.of(LabelDescriptor.create("label1", "desc1")))); - // Store in an intermediate value, because Mockito hates when mocks are evaluated inside of - // thenReturn() methods. - MetricPoint testPoint = - MetricPoint.create(metric, ImmutableList.of("foo"), new Instant(1337), 10L); - when(metric.getTimestampedValues()).thenReturn(ImmutableList.of(testPoint)); - // Store in an intermediate value, because Mockito hates when mocks are evaluated inside of - // thenReturn() methods. - MetricDescriptor descriptor = StackdriverWriter.encodeMetricDescriptor(metric); - when(metricDescriptorCreate.execute()).thenReturn(descriptor); - StackdriverWriter writer = - new StackdriverWriter(client, PROJECT, MONITORED_RESOURCE, MAX_QPS, MAX_POINTS_PER_REQUEST); - MetricPoint nativePoint = - MetricPoint.create( - metric, ImmutableList.of("foo"), new Instant(1337), new Instant(1337), 10L); - - TimeSeries timeSeries = writer.getEncodedTimeSeries(nativePoint); - - assertThat(timeSeries.getValueType()).isEqualTo("INT64"); - assertThat(timeSeries.getMetricKind()).isEqualTo("GAUGE"); - List points = timeSeries.getPoints(); - assertThat(points).hasSize(1); - Point point = points.get(0); - assertThat(point.getValue().getInt64Value()).isEqualTo(10L); - assertThat(point.getInterval().getStartTime()).isEqualTo("1970-01-01T00:00:01.337Z"); - assertThat(point.getInterval().getEndTime()).isEqualTo("1970-01-01T00:00:01.337Z"); - } - - @Test - public void getEncodedTimeSeries_booleanMetric_encodes() throws Exception { - StackdriverWriter writer = - new StackdriverWriter(client, PROJECT, MONITORED_RESOURCE, MAX_QPS, MAX_POINTS_PER_REQUEST); - - MetricDescriptor boolDescriptor = StackdriverWriter.encodeMetricDescriptor(boolMetric); - when(metricDescriptorCreate.execute()).thenReturn(boolDescriptor); - MetricPoint nativePoint = - MetricPoint.create(boolMetric, ImmutableList.of("foo"), new Instant(1337), true); - - TimeSeries timeSeries = writer.getEncodedTimeSeries(nativePoint); - - assertThat(timeSeries.getValueType()).isEqualTo("BOOL"); - assertThat(timeSeries.getMetricKind()).isEqualTo("GAUGE"); - List points = timeSeries.getPoints(); - assertThat(points).hasSize(1); - Point point = points.get(0); - assertThat(point.getValue().getBoolValue()).isEqualTo(true); - assertThat(point.getInterval().getEndTime()).isEqualTo("1970-01-01T00:00:01.337Z"); - assertThat(point.getInterval().getStartTime()).isEqualTo("1970-01-01T00:00:01.337Z"); - } - - @Test - public void getEncodedTimeSeries_distributionMetricCustomFitter_encodes() throws Exception { - StackdriverWriter writer = - new StackdriverWriter(client, PROJECT, MONITORED_RESOURCE, MAX_QPS, MAX_POINTS_PER_REQUEST); - - MetricDescriptor descriptor = StackdriverWriter.encodeMetricDescriptor(distributionMetric); - when(metricDescriptorCreate.execute()).thenReturn(descriptor); - MutableDistribution distribution = - new MutableDistribution(CustomFitter.create(ImmutableSet.of(5.0))); - distribution.add(10.0, 5L); - distribution.add(0.0, 5L); - MetricPoint nativePoint = - MetricPoint.create( - distributionMetric, ImmutableList.of("foo"), new Instant(1337), distribution); - - TimeSeries timeSeries = writer.getEncodedTimeSeries(nativePoint); - - assertThat(timeSeries.getValueType()).isEqualTo("DISTRIBUTION"); - assertThat(timeSeries.getMetricKind()).isEqualTo("GAUGE"); - List points = timeSeries.getPoints(); - assertThat(points).hasSize(1); - Point point = points.get(0); - assertThat(point.getValue().getDistributionValue()) - .isEqualTo( - new com.google.api.services.monitoring.v3.model.Distribution() - .setMean(5.0) - .setSumOfSquaredDeviation(250.0) - .setCount(10L) - .setBucketCounts(ImmutableList.of(5L, 5L)) - .setBucketOptions( - new BucketOptions() - .setExplicitBuckets(new Explicit().setBounds(ImmutableList.of(5.0))))); - assertThat(point.getInterval().getEndTime()).isEqualTo("1970-01-01T00:00:01.337Z"); - assertThat(point.getInterval().getStartTime()).isEqualTo("1970-01-01T00:00:01.337Z"); - } - - @Test - public void getEncodedTimeSeries_distributionMetricLinearFitter_encodes() throws Exception { - StackdriverWriter writer = - new StackdriverWriter(client, PROJECT, MONITORED_RESOURCE, MAX_QPS, MAX_POINTS_PER_REQUEST); - - MetricDescriptor descriptor = StackdriverWriter.encodeMetricDescriptor(distributionMetric); - when(metricDescriptorCreate.execute()).thenReturn(descriptor); - MutableDistribution distribution = new MutableDistribution(LinearFitter.create(2, 5.0, 3.0)); - distribution.add(0.0, 1L); - distribution.add(3.0, 2L); - distribution.add(10.0, 5L); - distribution.add(20.0, 5L); - MetricPoint nativePoint = - MetricPoint.create( - distributionMetric, ImmutableList.of("foo"), new Instant(1337), distribution); - - - TimeSeries timeSeries = writer.getEncodedTimeSeries(nativePoint); - - assertThat(timeSeries.getValueType()).isEqualTo("DISTRIBUTION"); - assertThat(timeSeries.getMetricKind()).isEqualTo("GAUGE"); - List points = timeSeries.getPoints(); - assertThat(points).hasSize(1); - Point point = points.get(0); - assertThat(point.getValue().getDistributionValue()) - .isEqualTo( - new com.google.api.services.monitoring.v3.model.Distribution() - .setMean(12.0) - .setSumOfSquaredDeviation(646.0) - .setCount(13L) - .setBucketCounts(ImmutableList.of(1L, 2L, 5L, 5L)) - .setBucketOptions( - new BucketOptions() - .setLinearBuckets( - new Linear().setNumFiniteBuckets(2).setWidth(5.0).setOffset(3.0)))); - assertThat(point.getInterval().getEndTime()).isEqualTo("1970-01-01T00:00:01.337Z"); - assertThat(point.getInterval().getStartTime()).isEqualTo("1970-01-01T00:00:01.337Z"); - } - - @Test - public void getEncodedTimeSeries_distributionMetricExponentialFitter_encodes() throws Exception { - StackdriverWriter writer = - new StackdriverWriter(client, PROJECT, MONITORED_RESOURCE, MAX_QPS, MAX_POINTS_PER_REQUEST); - - MetricDescriptor descriptor = StackdriverWriter.encodeMetricDescriptor(distributionMetric); - when(metricDescriptorCreate.execute()).thenReturn(descriptor); - MutableDistribution distribution = - new MutableDistribution(ExponentialFitter.create(2, 3.0, 0.5)); - distribution.add(0.0, 1L); - distribution.add(3.0, 2L); - distribution.add(10.0, 5L); - distribution.add(20.0, 5L); - MetricPoint nativePoint = - MetricPoint.create( - distributionMetric, ImmutableList.of("foo"), new Instant(1337), distribution); - - TimeSeries timeSeries = writer.getEncodedTimeSeries(nativePoint); - - assertThat(timeSeries.getValueType()).isEqualTo("DISTRIBUTION"); - assertThat(timeSeries.getMetricKind()).isEqualTo("GAUGE"); - List points = timeSeries.getPoints(); - assertThat(points).hasSize(1); - Point point = points.get(0); - assertThat(point.getValue().getDistributionValue()) - .isEqualTo( - new com.google.api.services.monitoring.v3.model.Distribution() - .setMean(12.0) - .setSumOfSquaredDeviation(646.0) - .setCount(13L) - .setBucketCounts(ImmutableList.of(1L, 0L, 2L, 10L)) - .setBucketOptions( - new BucketOptions() - .setExponentialBuckets( - new Exponential() - .setNumFiniteBuckets(2) - .setGrowthFactor(3.0) - .setScale(0.5)))); - assertThat(point.getInterval().getEndTime()).isEqualTo("1970-01-01T00:00:01.337Z"); - assertThat(point.getInterval().getStartTime()).isEqualTo("1970-01-01T00:00:01.337Z"); - } -} diff --git a/javatests/google/registry/proxy/BUILD b/javatests/google/registry/proxy/BUILD index bd2eb6e34..6e98342d7 100644 --- a/javatests/google/registry/proxy/BUILD +++ b/javatests/google/registry/proxy/BUILD @@ -15,14 +15,14 @@ java_library( "quota/testdata/*.yaml", ]), deps = [ - "//java/google/registry/monitoring/metrics", - "//java/google/registry/monitoring/metrics/contrib", "//java/google/registry/proxy", "//java/google/registry/util", "//javatests/google/registry/testing", "@com_beust_jcommander", "@com_google_dagger", "@com_google_guava", + "@com_google_monitoring_client_contrib", + "@com_google_monitoring_client_metrics", "@com_google_truth", "@com_google_truth_extensions_truth_java8_extension", "@io_netty_buffer", diff --git a/javatests/google/registry/proxy/metric/BackendMetricsTest.java b/javatests/google/registry/proxy/metric/BackendMetricsTest.java index 83f7c6a93..db7d021fe 100644 --- a/javatests/google/registry/proxy/metric/BackendMetricsTest.java +++ b/javatests/google/registry/proxy/metric/BackendMetricsTest.java @@ -14,8 +14,8 @@ package google.registry.proxy.metric; -import static google.registry.monitoring.metrics.contrib.DistributionMetricSubject.assertThat; -import static google.registry.monitoring.metrics.contrib.LongMetricSubject.assertThat; +import static com.google.monitoring.metrics.contrib.DistributionMetricSubject.assertThat; +import static com.google.monitoring.metrics.contrib.LongMetricSubject.assertThat; import static google.registry.proxy.TestUtils.makeHttpPostRequest; import static google.registry.proxy.TestUtils.makeHttpResponse; diff --git a/javatests/google/registry/proxy/metric/FrontendMetricsTest.java b/javatests/google/registry/proxy/metric/FrontendMetricsTest.java index 1b1849364..f21d96951 100644 --- a/javatests/google/registry/proxy/metric/FrontendMetricsTest.java +++ b/javatests/google/registry/proxy/metric/FrontendMetricsTest.java @@ -15,7 +15,7 @@ package google.registry.proxy.metric; import static com.google.common.truth.Truth.assertThat; -import static google.registry.monitoring.metrics.contrib.LongMetricSubject.assertThat; +import static com.google.monitoring.metrics.contrib.LongMetricSubject.assertThat; import io.netty.channel.ChannelFuture; import io.netty.channel.DefaultChannelId; diff --git a/javatests/google/registry/rdap/BUILD b/javatests/google/registry/rdap/BUILD index 6983da762..ec6da920b 100644 --- a/javatests/google/registry/rdap/BUILD +++ b/javatests/google/registry/rdap/BUILD @@ -14,7 +14,6 @@ java_library( deps = [ "//java/google/registry/config", "//java/google/registry/model", - "//java/google/registry/monitoring/metrics/contrib", "//java/google/registry/rdap", "//java/google/registry/request", "//java/google/registry/request/auth", @@ -26,6 +25,7 @@ java_library( "@com_google_code_findbugs_jsr305", "@com_google_dagger", "@com_google_guava", + "@com_google_monitoring_client_contrib", "@com_google_truth", "@com_google_truth_extensions_truth_java8_extension", "@com_googlecode_json_simple", diff --git a/javatests/google/registry/rdap/RdapMetricsTest.java b/javatests/google/registry/rdap/RdapMetricsTest.java index daee457db..3fe441a4e 100644 --- a/javatests/google/registry/rdap/RdapMetricsTest.java +++ b/javatests/google/registry/rdap/RdapMetricsTest.java @@ -14,8 +14,8 @@ package google.registry.rdap; -import static google.registry.monitoring.metrics.contrib.DistributionMetricSubject.assertThat; -import static google.registry.monitoring.metrics.contrib.LongMetricSubject.assertThat; +import static com.google.monitoring.metrics.contrib.DistributionMetricSubject.assertThat; +import static com.google.monitoring.metrics.contrib.LongMetricSubject.assertThat; import com.google.common.collect.ImmutableSet; import google.registry.rdap.RdapMetrics.EndpointType;