From 969d9483ae048fd4fcc312ba2fdb7a9b8e163e18 Mon Sep 17 00:00:00 2001 From: shikhman Date: Tue, 6 Sep 2016 09:15:48 -0700 Subject: [PATCH] Add encoding for the Stackdriver Distribution value type to StackdriverWriter ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=132327732 --- .../monitoring/metrics/StackdriverWriter.java | 52 +++++++ .../metrics/StackdriverWriterTest.java | 135 ++++++++++++++++++ 2 files changed, 187 insertions(+) diff --git a/java/google/registry/monitoring/metrics/StackdriverWriter.java b/java/google/registry/monitoring/metrics/StackdriverWriter.java index e7a568226..d77cb3baa 100644 --- a/java/google/registry/monitoring/metrics/StackdriverWriter.java +++ b/java/google/registry/monitoring/metrics/StackdriverWriter.java @@ -20,8 +20,13 @@ 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; @@ -88,6 +93,7 @@ public class StackdriverWriter implements MetricWriter { .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 = @@ -258,6 +264,49 @@ public class StackdriverWriter implements MetricWriter { .setStartTime(DATETIME_FORMATTER.print(nativeInterval.getStart())); } + 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}. * @@ -298,6 +347,9 @@ public class StackdriverWriter implements MetricWriter { 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. diff --git a/javatests/google/registry/monitoring/metrics/StackdriverWriterTest.java b/javatests/google/registry/monitoring/metrics/StackdriverWriterTest.java index 6b527df53..f71c6e760 100644 --- a/javatests/google/registry/monitoring/metrics/StackdriverWriterTest.java +++ b/javatests/google/registry/monitoring/metrics/StackdriverWriterTest.java @@ -29,7 +29,11 @@ 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; @@ -352,4 +356,135 @@ public class StackdriverWriterTest { 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); + Metric metric = + new StoredMetric<>( + "/name", + "desc", + "vdn", + ImmutableSet.of(LabelDescriptor.create("label", "description")), + Distribution.class); + MetricDescriptor descriptor = StackdriverWriter.createMetricDescriptor(metric); + 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(metric, 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); + Metric metric = + new StoredMetric<>( + "/name", + "desc", + "vdn", + ImmutableSet.of(LabelDescriptor.create("label", "description")), + Distribution.class); + MetricDescriptor descriptor = StackdriverWriter.createMetricDescriptor(metric); + 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(metric, 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); + Metric metric = + new StoredMetric<>( + "/name", + "desc", + "vdn", + ImmutableSet.of(LabelDescriptor.create("label", "description")), + Distribution.class); + MetricDescriptor descriptor = StackdriverWriter.createMetricDescriptor(metric); + 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(metric, 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"); + } }