From 031c6f5a737d9c7e8d52ab24a6e04506b4b56c67 Mon Sep 17 00:00:00 2001 From: Mayur Kale Date: Fri, 12 Oct 2018 09:45:08 -0700 Subject: [PATCH 1/3] Stats/Stackdriver: export data using metrics API --- buildscripts/import-control.xml | 1 + .../stackdriver/StackdriverExportUtils.java | 390 +++++-------- .../StackdriverExporterWorker.java | 67 ++- .../stackdriver/StackdriverStatsExporter.java | 10 +- .../StackdriverExportUtilsTest.java | 521 +++++++----------- .../StackdriverExporterWorkerTest.java | 158 +++--- 6 files changed, 452 insertions(+), 695 deletions(-) diff --git a/buildscripts/import-control.xml b/buildscripts/import-control.xml index d545878aa2..fbf217d099 100644 --- a/buildscripts/import-control.xml +++ b/buildscripts/import-control.xml @@ -148,6 +148,7 @@ General guidelines on imports: + diff --git a/exporters/stats/stackdriver/src/main/java/io/opencensus/exporter/stats/stackdriver/StackdriverExportUtils.java b/exporters/stats/stackdriver/src/main/java/io/opencensus/exporter/stats/stackdriver/StackdriverExportUtils.java index 4f8715b0b1..4079ded719 100644 --- a/exporters/stats/stackdriver/src/main/java/io/opencensus/exporter/stats/stackdriver/StackdriverExportUtils.java +++ b/exporters/stats/stackdriver/src/main/java/io/opencensus/exporter/stats/stackdriver/StackdriverExportUtils.java @@ -44,28 +44,20 @@ import io.opencensus.contrib.monitoredresource.util.MonitoredResource.GcpGkeContainerMonitoredResource; import io.opencensus.contrib.monitoredresource.util.MonitoredResourceUtils; import io.opencensus.contrib.monitoredresource.util.ResourceType; -import io.opencensus.stats.Aggregation; -import io.opencensus.stats.Aggregation.LastValue; -import io.opencensus.stats.AggregationData; -import io.opencensus.stats.AggregationData.CountData; -import io.opencensus.stats.AggregationData.DistributionData; -import io.opencensus.stats.AggregationData.LastValueDataDouble; -import io.opencensus.stats.AggregationData.LastValueDataLong; -import io.opencensus.stats.AggregationData.SumDataDouble; -import io.opencensus.stats.AggregationData.SumDataLong; -import io.opencensus.stats.BucketBoundaries; -import io.opencensus.stats.Measure; -import io.opencensus.stats.View; -import io.opencensus.stats.ViewData; -import io.opencensus.tags.TagKey; -import io.opencensus.tags.TagValue; +import io.opencensus.metrics.LabelKey; +import io.opencensus.metrics.LabelValue; +import io.opencensus.metrics.export.Distribution.Bucket; +import io.opencensus.metrics.export.Distribution.BucketOptions.ExplicitOptions; +import io.opencensus.metrics.export.MetricDescriptor.Type; +import io.opencensus.metrics.export.Summary; +import io.opencensus.metrics.export.Value; import java.lang.management.ManagementFactory; import java.net.InetAddress; import java.net.UnknownHostException; import java.security.SecureRandom; +import java.util.ArrayList; import java.util.List; import java.util.Map; -import java.util.Map.Entry; import java.util.logging.Level; import java.util.logging.Logger; @@ -73,12 +65,11 @@ import org.checkerframework.checker.nullness.qual.Nullable; */ -/** Util methods to convert OpenCensus Stats data models to StackDriver monitoring data models. */ +/** Util methods to convert OpenCensus Metrics data models to StackDriver monitoring data models. */ @SuppressWarnings("deprecation") final class StackdriverExportUtils { // TODO(songya): do we want these constants to be customizable? - @VisibleForTesting static final String LABEL_DESCRIPTION = "OpenCensus TagKey"; @VisibleForTesting static final String OPENCENSUS_TASK = "opencensus_task"; @VisibleForTesting static final String OPENCENSUS_TASK_DESCRIPTION = "Opencensus task identifier"; private static final String GCP_GKE_CONTAINER = "k8s_container"; @@ -90,98 +81,45 @@ final class StackdriverExportUtils { private static final String OPENCENSUS_TASK_VALUE_DEFAULT = generateDefaultTaskValue(); private static final String PROJECT_ID_LABEL_KEY = "project_id"; - // Constant functions for ValueType. - private static final Function VALUE_TYPE_DOUBLE_FUNCTION = - Functions.returnConstant(MetricDescriptor.ValueType.DOUBLE); - private static final Function VALUE_TYPE_INT64_FUNCTION = - Functions.returnConstant(MetricDescriptor.ValueType.INT64); - private static final Function - VALUE_TYPE_UNRECOGNIZED_FUNCTION = - Functions.returnConstant(MetricDescriptor.ValueType.UNRECOGNIZED); - private static final Function - VALUE_TYPE_DISTRIBUTION_FUNCTION = - Functions.returnConstant(MetricDescriptor.ValueType.DISTRIBUTION); - private static final Function valueTypeMeanFunction = - new Function() { - @Override - public MetricDescriptor.ValueType apply(Aggregation arg) { - // TODO(songya): remove this once Mean aggregation is completely removed. Before that - // we need to continue supporting Mean, since it could still be used by users and some - // deprecated RPC views. - if (arg instanceof Aggregation.Mean) { - return MetricDescriptor.ValueType.DOUBLE; - } - return MetricDescriptor.ValueType.UNRECOGNIZED; - } - }; - - // Constant functions for MetricKind. - private static final Function METRIC_KIND_CUMULATIVE_FUNCTION = - Functions.returnConstant(MetricKind.CUMULATIVE); - private static final Function METRIC_KIND_UNRECOGNIZED_FUNCTION = - Functions.returnConstant(MetricKind.UNRECOGNIZED); - // Constant functions for TypedValue. - private static final Function typedValueSumDoubleFunction = - new Function() { + private static final Function typedValueDoubleFunction = + new Function() { @Override - public TypedValue apply(SumDataDouble arg) { + public TypedValue apply(Double arg) { Builder builder = TypedValue.newBuilder(); - builder.setDoubleValue(arg.getSum()); + builder.setDoubleValue(arg); return builder.build(); } }; - private static final Function typedValueSumLongFunction = - new Function() { + private static final Function typedValueLongFunction = + new Function() { @Override - public TypedValue apply(SumDataLong arg) { + public TypedValue apply(Long arg) { Builder builder = TypedValue.newBuilder(); - builder.setInt64Value(arg.getSum()); + builder.setInt64Value(arg); return builder.build(); } }; - private static final Function typedValueCountFunction = - new Function() { + private static final Function typedValueSummaryFunction = + new Function() { @Override - public TypedValue apply(CountData arg) { + public TypedValue apply(Summary arg) { + // StackDriver doesn't handle Summary value. Builder builder = TypedValue.newBuilder(); - builder.setInt64Value(arg.getCount()); return builder.build(); } }; - private static final Function typedValueLastValueDoubleFunction = - new Function() { - @Override - public TypedValue apply(LastValueDataDouble arg) { - Builder builder = TypedValue.newBuilder(); - builder.setDoubleValue(arg.getLastValue()); - return builder.build(); - } - }; - private static final Function typedValueLastValueLongFunction = - new Function() { + + // Constant functions for BucketOptions. + private static final Function bucketOptionsExplicitFunction = + new Function() { @Override - public TypedValue apply(LastValueDataLong arg) { - Builder builder = TypedValue.newBuilder(); - builder.setInt64Value(arg.getLastValue()); + public BucketOptions apply(ExplicitOptions arg) { + BucketOptions.Builder builder = BucketOptions.newBuilder(); + builder.setExplicitBuckets(Explicit.newBuilder().addAllBounds(arg.getBucketBoundaries())); return builder.build(); } }; - private static final Function typedValueMeanFunction = - new Function() { - @Override - public TypedValue apply(AggregationData arg) { - Builder builder = TypedValue.newBuilder(); - // TODO(songya): remove this once Mean aggregation is completely removed. Before that - // we need to continue supporting Mean, since it could still be used by users and some - // deprecated RPC views. - if (arg instanceof AggregationData.MeanData) { - builder.setDoubleValue(((AggregationData.MeanData) arg).getMean()); - return builder.build(); - } - throw new IllegalArgumentException("Unknown Aggregation"); - } - }; private static String generateDefaultTaskValue() { // Something like '@', at least in Oracle and OpenJdk JVMs @@ -200,27 +138,23 @@ private static String generateDefaultTaskValue() { return "java-" + jvmName; } - // Construct a MetricDescriptor using a View. - @javax.annotation.Nullable + // Convert a OpenCensus MetricDescriptor to a StackDriver MetricDescriptor static MetricDescriptor createMetricDescriptor( - View view, String projectId, String domain, String displayNamePrefix) { - if (!(view.getWindow() instanceof View.AggregationWindow.Cumulative)) { - // TODO(songya): Only Cumulative view will be exported to Stackdriver in this version. - return null; - } + io.opencensus.metrics.export.MetricDescriptor metricDescriptor, + String projectId, + String domain, + String displayNamePrefix) { MetricDescriptor.Builder builder = MetricDescriptor.newBuilder(); - String viewName = view.getName().asString(); - String type = generateType(viewName, domain); + String type = generateType(metricDescriptor.getName(), domain); // Name format refers to // cloud.google.com/monitoring/api/ref_v3/rest/v3/projects.metricDescriptors/create builder.setName(String.format("projects/%s/metricDescriptors/%s", projectId, type)); builder.setType(type); - builder.setDescription(view.getDescription()); - String displayName = createDisplayName(viewName, displayNamePrefix); - builder.setDisplayName(displayName); - for (TagKey tagKey : view.getColumns()) { - builder.addLabels(createLabelDescriptor(tagKey)); + builder.setDescription(metricDescriptor.getDescription()); + builder.setDisplayName(createDisplayName(metricDescriptor.getName(), displayNamePrefix)); + for (LabelKey labelKey : metricDescriptor.getLabelKeys()) { + builder.addLabels(createLabelDescriptor(labelKey)); } builder.addLabels( LabelDescriptor.newBuilder() @@ -228,221 +162,191 @@ static MetricDescriptor createMetricDescriptor( .setDescription(OPENCENSUS_TASK_DESCRIPTION) .setValueType(ValueType.STRING) .build()); - builder.setUnit(createUnit(view.getAggregation(), view.getMeasure())); - builder.setMetricKind(createMetricKind(view.getWindow(), view.getAggregation())); - builder.setValueType(createValueType(view.getAggregation(), view.getMeasure())); + + builder.setUnit(metricDescriptor.getUnit()); + builder.setMetricKind(createMetricKind(metricDescriptor.getType())); + builder.setValueType(createValueType(metricDescriptor.getType())); return builder.build(); } - private static String generateType(String viewName, String domain) { - return domain + viewName; + private static String generateType(String metricName, String domain) { + return domain + metricName; } - private static String createDisplayName(String viewName, String displayNamePrefix) { - return displayNamePrefix + viewName; + private static String createDisplayName(String metricName, String displayNamePrefix) { + return displayNamePrefix + metricName; } - // Construct a LabelDescriptor from a TagKey + // Construct a LabelDescriptor from a LabelKey @VisibleForTesting - static LabelDescriptor createLabelDescriptor(TagKey tagKey) { + static LabelDescriptor createLabelDescriptor(LabelKey labelKey) { LabelDescriptor.Builder builder = LabelDescriptor.newBuilder(); - builder.setKey(tagKey.getName()); - builder.setDescription(LABEL_DESCRIPTION); + builder.setKey(labelKey.getKey()); + builder.setDescription(labelKey.getDescription()); // Now we only support String tags builder.setValueType(ValueType.STRING); return builder.build(); } - // Construct a MetricKind from an AggregationWindow + // Convert a OpenCensus Type to a StackDriver MetricKind @VisibleForTesting - static MetricKind createMetricKind(View.AggregationWindow window, Aggregation aggregation) { - if (aggregation instanceof LastValue) { + static MetricKind createMetricKind(Type type) { + if (type == Type.GAUGE_INT64 || type == Type.GAUGE_DOUBLE) { return MetricKind.GAUGE; + } else if (type == Type.CUMULATIVE_INT64 + || type == Type.CUMULATIVE_DOUBLE + || type == Type.CUMULATIVE_DISTRIBUTION) { + return MetricKind.CUMULATIVE; } - return window.match( - METRIC_KIND_CUMULATIVE_FUNCTION, // Cumulative - // TODO(songya): We don't support exporting Interval stats to StackDriver in this version. - METRIC_KIND_UNRECOGNIZED_FUNCTION, // Interval - METRIC_KIND_UNRECOGNIZED_FUNCTION); + return MetricKind.UNRECOGNIZED; } - // Construct a MetricDescriptor.ValueType from an Aggregation and a Measure + // Convert a OpenCensus Type to a StackDriver ValueType @VisibleForTesting - static String createUnit(Aggregation aggregation, final Measure measure) { - if (aggregation instanceof Aggregation.Count) { - return "1"; + static MetricDescriptor.ValueType createValueType(Type type) { + if (type == Type.CUMULATIVE_DOUBLE || type == Type.GAUGE_DOUBLE) { + return MetricDescriptor.ValueType.DOUBLE; + } else if (type == Type.GAUGE_INT64 || type == Type.CUMULATIVE_INT64) { + return MetricDescriptor.ValueType.INT64; + } else if (type == Type.GAUGE_DISTRIBUTION || type == Type.CUMULATIVE_DISTRIBUTION) { + return MetricDescriptor.ValueType.DISTRIBUTION; } - return measure.getUnit(); - } - - // Construct a MetricDescriptor.ValueType from an Aggregation and a Measure - @VisibleForTesting - static MetricDescriptor.ValueType createValueType( - Aggregation aggregation, final Measure measure) { - return aggregation.match( - Functions.returnConstant( - measure.match( - VALUE_TYPE_DOUBLE_FUNCTION, // Sum Double - VALUE_TYPE_INT64_FUNCTION, // Sum Long - VALUE_TYPE_UNRECOGNIZED_FUNCTION)), - VALUE_TYPE_INT64_FUNCTION, // Count - VALUE_TYPE_DISTRIBUTION_FUNCTION, // Distribution - Functions.returnConstant( - measure.match( - VALUE_TYPE_DOUBLE_FUNCTION, // LastValue Double - VALUE_TYPE_INT64_FUNCTION, // LastValue Long - VALUE_TYPE_UNRECOGNIZED_FUNCTION)), - valueTypeMeanFunction); + return MetricDescriptor.ValueType.UNRECOGNIZED; } - // Convert ViewData to a list of TimeSeries, so that ViewData can be uploaded to Stackdriver. + // Convert metric's timeseries to a list of TimeSeries, so that metric can be uploaded to + // StackDriver. static List createTimeSeriesList( - @javax.annotation.Nullable ViewData viewData, + @javax.annotation.Nullable io.opencensus.metrics.export.Metric metric, MonitoredResource monitoredResource, String domain) { List timeSeriesList = Lists.newArrayList(); - if (viewData == null) { - return timeSeriesList; - } - View view = viewData.getView(); - if (!(view.getWindow() instanceof View.AggregationWindow.Cumulative)) { - // TODO(songya): Only Cumulative view will be exported to Stackdriver in this version. + if (metric == null) { return timeSeriesList; } - // Shared fields for all TimeSeries generated from the same ViewData + io.opencensus.metrics.export.MetricDescriptor metricDescriptor = metric.getMetricDescriptor(); + + // Shared fields for all TimeSeries generated from the same Metric TimeSeries.Builder shared = TimeSeries.newBuilder(); - shared.setMetricKind(createMetricKind(view.getWindow(), view.getAggregation())); + shared.setMetricKind(createMetricKind(metricDescriptor.getType())); shared.setResource(monitoredResource); - shared.setValueType(createValueType(view.getAggregation(), view.getMeasure())); + shared.setValueType(createValueType(metricDescriptor.getType())); - // Each entry in AggregationMap will be converted into an independent TimeSeries object - for (Entry, AggregationData> entry : - viewData.getAggregationMap().entrySet()) { + // Each entry in timeSeriesList will be converted into an independent TimeSeries object + for (io.opencensus.metrics.export.TimeSeries timeSeries : metric.getTimeSeriesList()) { TimeSeries.Builder builder = shared.clone(); - builder.setMetric(createMetric(view, entry.getKey(), domain)); - builder.addPoints( - createPoint(entry.getValue(), viewData.getWindowData(), view.getAggregation())); + builder.setMetric(createMetric(metricDescriptor, timeSeries.getLabelValues(), domain)); + + io.opencensus.common.Timestamp startTimeStamp = timeSeries.getStartTimestamp(); + for (io.opencensus.metrics.export.Point point : timeSeries.getPoints()) { + builder.addPoints(createPoint(point, startTimeStamp)); + } timeSeriesList.add(builder.build()); } - return timeSeriesList; } - // Create a Metric using the TagKeys and TagValues. + // Create a Metric using the LabelKeys and LabelValues. @VisibleForTesting - static Metric createMetric(View view, List tagValues, String domain) { + static Metric createMetric( + io.opencensus.metrics.export.MetricDescriptor metricDescriptor, + List labelValues, + String domain) { Metric.Builder builder = Metric.newBuilder(); - // TODO(songya): use pre-defined metrics for canonical views - builder.setType(generateType(view.getName().asString(), domain)); + builder.setType(generateType(metricDescriptor.getName(), domain)); Map stringTagMap = Maps.newHashMap(); - List columns = view.getColumns(); + List labelKeys = metricDescriptor.getLabelKeys(); + checkArgument( - tagValues.size() == columns.size(), "TagKeys and TagValues don't have same size."); - for (int i = 0; i < tagValues.size(); i++) { - TagKey key = columns.get(i); - TagValue value = tagValues.get(i); + labelKeys.size() == labelValues.size(), "LabelKeys and LabelValues don't have same size."); + + for (int i = 0; i < labelValues.size(); i++) { + String value = labelValues.get(i).getValue(); if (value == null) { continue; } - stringTagMap.put(key.getName(), value.asString()); + stringTagMap.put(labelKeys.get(i).getKey(), value); } stringTagMap.put(OPENCENSUS_TASK, OPENCENSUS_TASK_VALUE_DEFAULT); builder.putAllLabels(stringTagMap); return builder.build(); } - // Create Point from AggregationData, AggregationWindowData and Aggregation. + // Convert a OpenCensus Point to a StackDriver Point @VisibleForTesting static Point createPoint( - AggregationData aggregationData, - ViewData.AggregationWindowData windowData, - Aggregation aggregation) { + io.opencensus.metrics.export.Point point, + @javax.annotation.Nullable io.opencensus.common.Timestamp startTimestamp) { + TimeInterval.Builder timeIntervalBuilder = TimeInterval.newBuilder(); + timeIntervalBuilder.setEndTime(convertTimestamp(point.getTimestamp())); + if (startTimestamp != null) { + timeIntervalBuilder.setStartTime(convertTimestamp(startTimestamp)); + } + Point.Builder builder = Point.newBuilder(); - builder.setInterval(createTimeInterval(windowData, aggregation)); - builder.setValue(createTypedValue(aggregation, aggregationData)); + builder.setInterval(timeIntervalBuilder.build()); + builder.setValue(createTypedValue(point.getValue())); return builder.build(); } - // Convert AggregationWindowData to TimeInterval, currently only support CumulativeData. - @VisibleForTesting - static TimeInterval createTimeInterval( - ViewData.AggregationWindowData windowData, final Aggregation aggregation) { - return windowData.match( - new Function() { - @Override - public TimeInterval apply(ViewData.AggregationWindowData.CumulativeData arg) { - TimeInterval.Builder builder = TimeInterval.newBuilder(); - builder.setEndTime(convertTimestamp(arg.getEnd())); - if (!(aggregation instanceof LastValue)) { - builder.setStartTime(convertTimestamp(arg.getStart())); - } - return builder.build(); - } - }, - Functions.throwIllegalArgumentException(), - Functions.throwIllegalArgumentException()); - } - - // Create a TypedValue using AggregationData and Aggregation + // Convert a OpenCensus Value to a StackDriver TypedValue // Note TypedValue is "A single strongly-typed value", i.e only one field should be set. @VisibleForTesting - static TypedValue createTypedValue( - final Aggregation aggregation, AggregationData aggregationData) { - return aggregationData.match( - typedValueSumDoubleFunction, - typedValueSumLongFunction, - typedValueCountFunction, - new Function() { + static TypedValue createTypedValue(Value value) { + return value.match( + typedValueDoubleFunction, + typedValueLongFunction, + new Function() { @Override - public TypedValue apply(DistributionData arg) { + public TypedValue apply(io.opencensus.metrics.export.Distribution arg) { TypedValue.Builder builder = TypedValue.newBuilder(); - checkArgument( - aggregation instanceof Aggregation.Distribution, - "Aggregation and AggregationData mismatch."); - builder.setDistributionValue( - createDistribution( - arg, ((Aggregation.Distribution) aggregation).getBucketBoundaries())); - return builder.build(); + return builder.setDistributionValue(createDistribution(arg)).build(); } }, - typedValueLastValueDoubleFunction, - typedValueLastValueLongFunction, - typedValueMeanFunction); + typedValueSummaryFunction, + Functions.throwIllegalArgumentException()); } - // Create a StackDriver Distribution from DistributionData and BucketBoundaries + // Convert a OpenCensus Distribution to a StackDriver Distribution @VisibleForTesting - static Distribution createDistribution( - DistributionData distributionData, BucketBoundaries bucketBoundaries) { + static Distribution createDistribution(io.opencensus.metrics.export.Distribution distribution) { return Distribution.newBuilder() - .setBucketOptions(createBucketOptions(bucketBoundaries)) - .addAllBucketCounts(distributionData.getBucketCounts()) - .setCount(distributionData.getCount()) - .setMean(distributionData.getMean()) - // TODO(songya): uncomment this once Stackdriver supports setting max and min. - // .setRange( - // Range.newBuilder() - // .setMax(distributionData.getMax()) - // .setMin(distributionData.getMin()) - // .build()) - .setSumOfSquaredDeviation(distributionData.getSumOfSquaredDeviations()) + .setBucketOptions(createBucketOptions(distribution.getBucketOptions())) + .addAllBucketCounts(createBucketCounts(distribution.getBuckets())) + .setCount(distribution.getCount()) + .setSumOfSquaredDeviation(distribution.getSumOfSquaredDeviations()) .build(); } - // Create BucketOptions from BucketBoundaries + // Convert a OpenCensus BucketOptions to a StackDriver BucketOptions @VisibleForTesting - static BucketOptions createBucketOptions(BucketBoundaries bucketBoundaries) { - return BucketOptions.newBuilder() - .setExplicitBuckets(Explicit.newBuilder().addAllBounds(bucketBoundaries.getBoundaries())) - .build(); + static BucketOptions createBucketOptions( + @javax.annotation.Nullable + io.opencensus.metrics.export.Distribution.BucketOptions bucketOptions) { + final BucketOptions.Builder builder = BucketOptions.newBuilder(); + if (bucketOptions == null) { + return builder.build(); + } + + return bucketOptions.match( + bucketOptionsExplicitFunction, Functions.throwIllegalArgumentException()); + } + + // Convert a OpenCensus Buckets to a list of counts + private static List createBucketCounts(List buckets) { + List bucketCounts = new ArrayList<>(); + for (Bucket bucket : buckets) { + bucketCounts.add(bucket.getCount()); + } + return bucketCounts; } - // Convert a Census Timestamp to a StackDriver Timestamp + // Convert a OpenCensus Timestamp to a StackDriver Timestamp @VisibleForTesting static Timestamp convertTimestamp(io.opencensus.common.Timestamp censusTimestamp) { if (censusTimestamp.getSeconds() < 0) { - // Stackdriver doesn't handle negative timestamps. + // StackDriver doesn't handle negative timestamps. return Timestamp.newBuilder().build(); } return Timestamp.newBuilder() @@ -451,7 +355,7 @@ static Timestamp convertTimestamp(io.opencensus.common.Timestamp censusTimestamp .build(); } - /* Return a self-configured Stackdriver monitored resource. */ + /* Return a self-configured StackDriver monitored resource. */ static MonitoredResource getDefaultResource() { MonitoredResource.Builder builder = MonitoredResource.newBuilder(); io.opencensus.contrib.monitoredresource.util.MonitoredResource autoDetectedResource = diff --git a/exporters/stats/stackdriver/src/main/java/io/opencensus/exporter/stats/stackdriver/StackdriverExporterWorker.java b/exporters/stats/stackdriver/src/main/java/io/opencensus/exporter/stats/stackdriver/StackdriverExporterWorker.java index 5ffed9d5c5..713b687271 100644 --- a/exporters/stats/stackdriver/src/main/java/io/opencensus/exporter/stats/stackdriver/StackdriverExporterWorker.java +++ b/exporters/stats/stackdriver/src/main/java/io/opencensus/exporter/stats/stackdriver/StackdriverExporterWorker.java @@ -29,9 +29,9 @@ import com.google.monitoring.v3.TimeSeries; import io.opencensus.common.Duration; import io.opencensus.common.Scope; -import io.opencensus.stats.View; -import io.opencensus.stats.ViewData; -import io.opencensus.stats.ViewManager; +import io.opencensus.metrics.export.Metric; +import io.opencensus.metrics.export.MetricProducer; +import io.opencensus.metrics.export.MetricProducerManager; import io.opencensus.trace.Sampler; import io.opencensus.trace.Span; import io.opencensus.trace.Status; @@ -51,7 +51,7 @@ */ /** - * Worker {@code Runnable} that polls ViewData from Stats library and batch export to StackDriver. + * Worker {@code Runnable} that polls Metric from Metrics library and batch export to StackDriver. * *

{@code StackdriverExporterWorker} will be started in a daemon {@code Thread}. * @@ -76,11 +76,11 @@ final class StackdriverExporterWorker implements Runnable { private final String projectId; private final ProjectName projectName; private final MetricServiceClient metricServiceClient; - private final ViewManager viewManager; + private final MetricProducerManager metricProducerManager; private final MonitoredResource monitoredResource; private final String domain; private final String displayNamePrefix; - private final Map registeredViews = new HashMap(); + private final Map registeredMetrics = new HashMap(); private static final Tracer tracer = Tracing.getTracer(); private static final Sampler probabilitySampler = Samplers.probabilitySampler(0.0001); @@ -89,14 +89,14 @@ final class StackdriverExporterWorker implements Runnable { String projectId, MetricServiceClient metricServiceClient, Duration exportInterval, - ViewManager viewManager, + MetricProducerManager metricProducerManager, MonitoredResource monitoredResource, @javax.annotation.Nullable String metricNamePrefix) { this.scheduleDelayMillis = exportInterval.toMillis(); this.projectId = projectId; projectName = ProjectName.newBuilder().setProject(projectId).build(); this.metricServiceClient = metricServiceClient; - this.viewManager = viewManager; + this.metricProducerManager = metricProducerManager; this.monitoredResource = monitoredResource; this.domain = getDomain(metricNamePrefix); this.displayNamePrefix = getDisplayNamePrefix(metricNamePrefix); @@ -107,37 +107,30 @@ final class StackdriverExporterWorker implements Runnable { Collections.singletonList("ExportStatsToStackdriverMonitoring")); } - // Returns true if the given view is successfully registered to Stackdriver Monitoring, or the - // exact same view has already been registered. Returns false otherwise. + // Returns true if the given metric is successfully registered to Stackdriver Monitoring, or the + // exact same metric has already been registered. Returns false otherwise. @VisibleForTesting - boolean registerView(View view) { - View existing = registeredViews.get(view.getName()); - if (existing != null) { - if (existing.equals(view)) { - // Ignore views that are already registered. + boolean registerMetric(Metric metric) { + Metric existingMetric = registeredMetrics.get(metric.getMetricDescriptor().getName()); + if (existingMetric != null) { + if (existingMetric.getMetricDescriptor().equals(metric.getMetricDescriptor())) { + // Ignore metric that are already registered. return true; } else { - // If we upload a view that has the same name with a registered view but with different - // attributes, Stackdriver client will throw an exception. logger.log( Level.WARNING, - "A different view with the same name is already registered: " + existing); + "A different metric with the same name is already registered: " + + existingMetric.getMetricDescriptor()); return false; } } - registeredViews.put(view.getName(), view); + registeredMetrics.put(metric.getMetricDescriptor().getName(), metric); Span span = tracer.getCurrentSpan(); span.addAnnotation("Create Stackdriver Metric."); - // TODO(songya): don't need to create MetricDescriptor for RpcViewConstants once we defined - // canonical metrics. Registration is required only for custom view definitions. Canonical - // views should be pre-registered. MetricDescriptor metricDescriptor = - StackdriverExportUtils.createMetricDescriptor(view, projectId, domain, displayNamePrefix); - if (metricDescriptor == null) { - // Don't register interval views in this version. - return false; - } + StackdriverExportUtils.createMetricDescriptor( + metric.getMetricDescriptor(), projectId, domain, displayNamePrefix); CreateMetricDescriptorRequest request = CreateMetricDescriptorRequest.newBuilder() @@ -165,23 +158,25 @@ boolean registerView(View view) { } } - // Polls ViewData from Stats library for all exported views, and upload them as TimeSeries to - // StackDriver. + // Polls MetricProducerManager from Metrics library for all registered metrics, and upload them as + // TimeSeries to StackDriver. @VisibleForTesting void export() { - List viewDataList = Lists.newArrayList(); - for (View view : viewManager.getAllExportedViews()) { - if (registerView(view)) { - // Only upload stats for valid views. - viewDataList.add(viewManager.getView(view.getName())); + List metricsList = Lists.newArrayList(); + for (MetricProducer metricProducer : metricProducerManager.getAllMetricProducer()) { + for (Metric metric : metricProducer.getMetrics()) { + if (registerMetric(metric)) { + metricsList.add(metric); + } } } List timeSeriesList = Lists.newArrayList(); - for (/*@Nullable*/ ViewData viewData : viewDataList) { + for (/*@Nullable*/ Metric metric : metricsList) { timeSeriesList.addAll( - StackdriverExportUtils.createTimeSeriesList(viewData, monitoredResource, domain)); + StackdriverExportUtils.createTimeSeriesList(metric, monitoredResource, domain)); } + for (List batchedTimeSeries : Lists.partition(timeSeriesList, MAX_BATCH_EXPORT_SIZE)) { Span span = tracer.getCurrentSpan(); diff --git a/exporters/stats/stackdriver/src/main/java/io/opencensus/exporter/stats/stackdriver/StackdriverStatsExporter.java b/exporters/stats/stackdriver/src/main/java/io/opencensus/exporter/stats/stackdriver/StackdriverStatsExporter.java index 51c54916fa..7ad78f7bd9 100644 --- a/exporters/stats/stackdriver/src/main/java/io/opencensus/exporter/stats/stackdriver/StackdriverStatsExporter.java +++ b/exporters/stats/stackdriver/src/main/java/io/opencensus/exporter/stats/stackdriver/StackdriverStatsExporter.java @@ -30,8 +30,8 @@ import com.google.common.annotations.VisibleForTesting; import com.google.common.util.concurrent.MoreExecutors; import io.opencensus.common.Duration; -import io.opencensus.stats.Stats; -import io.opencensus.stats.ViewManager; +import io.opencensus.metrics.Metrics; +import io.opencensus.metrics.export.MetricProducerManager; import java.io.IOException; import java.util.concurrent.ThreadFactory; import javax.annotation.Nullable; @@ -78,7 +78,7 @@ public final class StackdriverStatsExporter { String projectId, MetricServiceClient metricServiceClient, Duration exportInterval, - ViewManager viewManager, + MetricProducerManager metricProducerManager, MonitoredResource monitoredResource, @Nullable String metricNamePrefix) { checkArgument(exportInterval.compareTo(ZERO) > 0, "Duration must be positive"); @@ -87,7 +87,7 @@ public final class StackdriverStatsExporter { projectId, metricServiceClient, exportInterval, - viewManager, + metricProducerManager, monitoredResource, metricNamePrefix); this.workerThread = new DaemonThreadFactory().newThread(worker); @@ -325,7 +325,7 @@ private static void createInternal( projectId, metricServiceClient, exportInterval, - Stats.getViewManager(), + Metrics.getExportComponent().getMetricProducerManager(), monitoredResource, metricNamePrefix); exporter.workerThread.start(); diff --git a/exporters/stats/stackdriver/src/test/java/io/opencensus/exporter/stats/stackdriver/StackdriverExportUtilsTest.java b/exporters/stats/stackdriver/src/test/java/io/opencensus/exporter/stats/stackdriver/StackdriverExportUtilsTest.java index cd536e8f09..ddbe258afb 100644 --- a/exporters/stats/stackdriver/src/test/java/io/opencensus/exporter/stats/stackdriver/StackdriverExportUtilsTest.java +++ b/exporters/stats/stackdriver/src/test/java/io/opencensus/exporter/stats/stackdriver/StackdriverExportUtilsTest.java @@ -28,41 +28,24 @@ import com.google.api.MetricDescriptor; import com.google.api.MetricDescriptor.MetricKind; import com.google.api.MonitoredResource; -import com.google.common.collect.ImmutableMap; -import com.google.monitoring.v3.Point; import com.google.monitoring.v3.TimeInterval; import com.google.monitoring.v3.TimeSeries; import com.google.monitoring.v3.TypedValue; -import io.opencensus.common.Duration; import io.opencensus.common.Timestamp; -import io.opencensus.stats.Aggregation.Count; -import io.opencensus.stats.Aggregation.Distribution; -import io.opencensus.stats.Aggregation.LastValue; -import io.opencensus.stats.Aggregation.Mean; -import io.opencensus.stats.Aggregation.Sum; -import io.opencensus.stats.AggregationData.CountData; -import io.opencensus.stats.AggregationData.DistributionData; -import io.opencensus.stats.AggregationData.LastValueDataDouble; -import io.opencensus.stats.AggregationData.LastValueDataLong; -import io.opencensus.stats.AggregationData.MeanData; -import io.opencensus.stats.AggregationData.SumDataDouble; -import io.opencensus.stats.AggregationData.SumDataLong; -import io.opencensus.stats.BucketBoundaries; -import io.opencensus.stats.Measure.MeasureDouble; -import io.opencensus.stats.Measure.MeasureLong; -import io.opencensus.stats.View; -import io.opencensus.stats.View.AggregationWindow.Cumulative; -import io.opencensus.stats.View.AggregationWindow.Interval; -import io.opencensus.stats.View.Name; -import io.opencensus.stats.ViewData; -import io.opencensus.stats.ViewData.AggregationWindowData.CumulativeData; -import io.opencensus.stats.ViewData.AggregationWindowData.IntervalData; -import io.opencensus.tags.TagKey; -import io.opencensus.tags.TagValue; +import io.opencensus.metrics.LabelKey; +import io.opencensus.metrics.LabelValue; +import io.opencensus.metrics.export.Distribution.Bucket; +import io.opencensus.metrics.export.MetricDescriptor.Type; +import io.opencensus.metrics.export.Point; +import io.opencensus.metrics.export.Summary; +import io.opencensus.metrics.export.Summary.Snapshot; +import io.opencensus.metrics.export.Summary.Snapshot.ValueAtPercentile; +import io.opencensus.metrics.export.Value; import java.lang.management.ManagementFactory; +import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.List; -import java.util.Map; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; @@ -72,178 +55,157 @@ /** Unit tests for {@link StackdriverExportUtils}. */ @RunWith(JUnit4.class) public class StackdriverExportUtilsTest { - @Rule public final ExpectedException thrown = ExpectedException.none(); - private static final TagKey KEY = TagKey.create("KEY"); - private static final TagKey KEY_2 = TagKey.create("KEY2"); - private static final TagKey KEY_3 = TagKey.create("KEY3"); - private static final TagValue VALUE_1 = TagValue.create("VALUE1"); - private static final TagValue VALUE_2 = TagValue.create("VALUE2"); - private static final String MEASURE_UNIT = "us"; - private static final String MEASURE_DESCRIPTION = "measure description"; - private static final MeasureDouble MEASURE_DOUBLE = - MeasureDouble.create("measure1", MEASURE_DESCRIPTION, MEASURE_UNIT); - private static final MeasureLong MEASURE_LONG = - MeasureLong.create("measure2", MEASURE_DESCRIPTION, MEASURE_UNIT); - private static final String VIEW_NAME = "view"; - private static final String VIEW_DESCRIPTION = "view description"; - private static final Duration TEN_SECONDS = Duration.create(10, 0); - private static final Cumulative CUMULATIVE = Cumulative.create(); - private static final Interval INTERVAL = Interval.create(TEN_SECONDS); - private static final BucketBoundaries BUCKET_BOUNDARIES = - BucketBoundaries.create(Arrays.asList(0.0, 1.0, 3.0, 5.0)); - private static final Sum SUM = Sum.create(); - private static final Count COUNT = Count.create(); - private static final Mean MEAN = Mean.create(); - private static final Distribution DISTRIBUTION = Distribution.create(BUCKET_BOUNDARIES); - private static final LastValue LAST_VALUE = LastValue.create(); + private static final String METRIC_NAME = "my measurement"; + private static final String METRIC_DESCRIPTION = "measure description"; + private static final String METRIC_UNIT = "us"; + private static final String METRIC_UNIT_2 = "1"; + private static final List LABEL_KEY = + Collections.singletonList(LabelKey.create("KEY1", "key description")); + private static final List LABEL_VALUE = + Collections.singletonList(LabelValue.create("VALUE1")); + private static final List LABEL_VALUE_2 = + Collections.singletonList(LabelValue.create("VALUE2")); + private static final List EMPTY_LABEL_KEY = new ArrayList<>(); + private static final List EMPTY_LABEL_VALUE = new ArrayList<>(); + private static final io.opencensus.metrics.export.MetricDescriptor METRIC_DESCRIPTOR = + io.opencensus.metrics.export.MetricDescriptor.create( + METRIC_NAME, METRIC_DESCRIPTION, METRIC_UNIT, Type.CUMULATIVE_DOUBLE, LABEL_KEY); + private static final io.opencensus.metrics.export.MetricDescriptor METRIC_DESCRIPTOR_2 = + io.opencensus.metrics.export.MetricDescriptor.create( + METRIC_NAME, METRIC_DESCRIPTION, METRIC_UNIT_2, Type.CUMULATIVE_INT64, EMPTY_LABEL_KEY); + private static final io.opencensus.metrics.export.MetricDescriptor GAUGE_METRIC_DESCRIPTOR = + io.opencensus.metrics.export.MetricDescriptor.create( + METRIC_NAME, METRIC_DESCRIPTION, METRIC_UNIT, Type.GAUGE_DOUBLE, LABEL_KEY); + + private static final List BUCKET_BOUNDARIES = Arrays.asList(1.0, 3.0, 5.0); + private static final io.opencensus.metrics.export.Distribution.BucketOptions BUCKET_OPTIONS = + io.opencensus.metrics.export.Distribution.BucketOptions.explicitOptions(BUCKET_BOUNDARIES); + private static final Value VALUE_DOUBLE = Value.doubleValue(12345678.2); + private static final Value VALUE_DOUBLE_2 = Value.doubleValue(133.79); + + private static final Timestamp TIMESTAMP = Timestamp.fromMillis(3000); + private static final Timestamp TIMESTAMP_2 = Timestamp.fromMillis(1000); + private static final Timestamp TIMESTAMP_3 = Timestamp.fromMillis(2000); + private static final Point POINT = Point.create(VALUE_DOUBLE, TIMESTAMP); + private static final Point POINT_2 = Point.create(VALUE_DOUBLE_2, TIMESTAMP_3); + private static final io.opencensus.metrics.export.TimeSeries CUMULATIVE_TIME_SERIES = + io.opencensus.metrics.export.TimeSeries.createWithOnePoint(LABEL_VALUE, POINT, TIMESTAMP_2); + private static final io.opencensus.metrics.export.TimeSeries GAUGE_TIME_SERIES = + io.opencensus.metrics.export.TimeSeries.createWithOnePoint(LABEL_VALUE, POINT, null); + private static final io.opencensus.metrics.export.TimeSeries GAUGE_TIME_SERIES_2 = + io.opencensus.metrics.export.TimeSeries.createWithOnePoint(LABEL_VALUE_2, POINT_2, null); + private static final io.opencensus.metrics.export.Metric METRIC = + io.opencensus.metrics.export.Metric.createWithOneTimeSeries( + METRIC_DESCRIPTOR, CUMULATIVE_TIME_SERIES); private static final String PROJECT_ID = "id"; private static final MonitoredResource DEFAULT_RESOURCE = MonitoredResource.newBuilder().setType("global").build(); private static final String DEFAULT_TASK_VALUE = "java-" + ManagementFactory.getRuntimeMXBean().getName(); - @Test - public void testConstant() { - assertThat(StackdriverExportUtils.LABEL_DESCRIPTION).isEqualTo("OpenCensus TagKey"); - } + private static final io.opencensus.metrics.export.Distribution DISTRIBUTION = + io.opencensus.metrics.export.Distribution.create( + 3, + 2, + 14, + BUCKET_OPTIONS, + Arrays.asList(Bucket.create(3), Bucket.create(1), Bucket.create(2), Bucket.create(4))); + private static final Summary SUMMARY = + Summary.create( + 10L, + 10.0, + Snapshot.create( + 10L, 87.07, Collections.singletonList(ValueAtPercentile.create(0.98, 10.2)))); + private static final Value DOUBLE_VALUE = Value.doubleValue(1.1); + private static final Value LONG_VALUE = Value.longValue(10000); + private static final Value DISTRIBUTION_VALUE = Value.distributionValue(DISTRIBUTION); + private static final Value SUMMARY_VALUE = Value.summaryValue(SUMMARY); @Test public void createLabelDescriptor() { - assertThat(StackdriverExportUtils.createLabelDescriptor(TagKey.create("string"))) + assertThat(StackdriverExportUtils.createLabelDescriptor(LabelKey.create("key", "desc"))) .isEqualTo( LabelDescriptor.newBuilder() - .setKey("string") - .setDescription(StackdriverExportUtils.LABEL_DESCRIPTION) + .setKey("key") + .setDescription("desc") .setValueType(ValueType.STRING) .build()); } @Test public void createMetricKind() { - assertThat(StackdriverExportUtils.createMetricKind(CUMULATIVE, SUM)) + assertThat(StackdriverExportUtils.createMetricKind(Type.CUMULATIVE_INT64)) .isEqualTo(MetricKind.CUMULATIVE); - assertThat(StackdriverExportUtils.createMetricKind(INTERVAL, COUNT)) + assertThat(StackdriverExportUtils.createMetricKind(Type.SUMMARY)) .isEqualTo(MetricKind.UNRECOGNIZED); - assertThat(StackdriverExportUtils.createMetricKind(CUMULATIVE, LAST_VALUE)) + assertThat(StackdriverExportUtils.createMetricKind(Type.GAUGE_INT64)) .isEqualTo(MetricKind.GAUGE); - assertThat(StackdriverExportUtils.createMetricKind(INTERVAL, LAST_VALUE)) + assertThat(StackdriverExportUtils.createMetricKind(Type.GAUGE_DOUBLE)) .isEqualTo(MetricKind.GAUGE); } @Test public void createValueType() { - assertThat(StackdriverExportUtils.createValueType(SUM, MEASURE_DOUBLE)) + assertThat(StackdriverExportUtils.createValueType(Type.GAUGE_DOUBLE)) .isEqualTo(MetricDescriptor.ValueType.DOUBLE); - assertThat(StackdriverExportUtils.createValueType(SUM, MEASURE_LONG)) - .isEqualTo(MetricDescriptor.ValueType.INT64); - assertThat(StackdriverExportUtils.createValueType(COUNT, MEASURE_DOUBLE)) + assertThat(StackdriverExportUtils.createValueType(Type.CUMULATIVE_INT64)) .isEqualTo(MetricDescriptor.ValueType.INT64); - assertThat(StackdriverExportUtils.createValueType(COUNT, MEASURE_LONG)) + assertThat(StackdriverExportUtils.createValueType(Type.GAUGE_INT64)) .isEqualTo(MetricDescriptor.ValueType.INT64); - assertThat(StackdriverExportUtils.createValueType(MEAN, MEASURE_DOUBLE)) + assertThat(StackdriverExportUtils.createValueType(Type.CUMULATIVE_DOUBLE)) .isEqualTo(MetricDescriptor.ValueType.DOUBLE); - assertThat(StackdriverExportUtils.createValueType(MEAN, MEASURE_LONG)) - .isEqualTo(MetricDescriptor.ValueType.DOUBLE); - assertThat(StackdriverExportUtils.createValueType(DISTRIBUTION, MEASURE_DOUBLE)) + assertThat(StackdriverExportUtils.createValueType(Type.GAUGE_DISTRIBUTION)) .isEqualTo(MetricDescriptor.ValueType.DISTRIBUTION); - assertThat(StackdriverExportUtils.createValueType(DISTRIBUTION, MEASURE_LONG)) + assertThat(StackdriverExportUtils.createValueType(Type.CUMULATIVE_DISTRIBUTION)) .isEqualTo(MetricDescriptor.ValueType.DISTRIBUTION); - assertThat(StackdriverExportUtils.createValueType(LAST_VALUE, MEASURE_DOUBLE)) - .isEqualTo(MetricDescriptor.ValueType.DOUBLE); - assertThat(StackdriverExportUtils.createValueType(LAST_VALUE, MEASURE_LONG)) - .isEqualTo(MetricDescriptor.ValueType.INT64); - } - - @Test - public void createUnit() { - assertThat(StackdriverExportUtils.createUnit(SUM, MEASURE_DOUBLE)).isEqualTo(MEASURE_UNIT); - assertThat(StackdriverExportUtils.createUnit(COUNT, MEASURE_DOUBLE)).isEqualTo("1"); - assertThat(StackdriverExportUtils.createUnit(MEAN, MEASURE_DOUBLE)).isEqualTo(MEASURE_UNIT); - assertThat(StackdriverExportUtils.createUnit(DISTRIBUTION, MEASURE_DOUBLE)) - .isEqualTo(MEASURE_UNIT); - assertThat(StackdriverExportUtils.createUnit(LAST_VALUE, MEASURE_DOUBLE)) - .isEqualTo(MEASURE_UNIT); } @Test public void createMetric() { - View view = - View.create( - Name.create(VIEW_NAME), - VIEW_DESCRIPTION, - MEASURE_DOUBLE, - DISTRIBUTION, - Arrays.asList(KEY), - CUMULATIVE); assertThat( StackdriverExportUtils.createMetric( - view, Arrays.asList(VALUE_1), CUSTOM_OPENCENSUS_DOMAIN)) + METRIC_DESCRIPTOR, LABEL_VALUE, CUSTOM_OPENCENSUS_DOMAIN)) .isEqualTo( Metric.newBuilder() - .setType("custom.googleapis.com/opencensus/" + VIEW_NAME) - .putLabels("KEY", "VALUE1") + .setType("custom.googleapis.com/opencensus/" + METRIC_NAME) + .putLabels("KEY1", "VALUE1") .putLabels(StackdriverExportUtils.OPENCENSUS_TASK, DEFAULT_TASK_VALUE) .build()); } @Test public void createMetric_WithExternalMetricDomain() { - View view = - View.create( - Name.create(VIEW_NAME), - VIEW_DESCRIPTION, - MEASURE_DOUBLE, - DISTRIBUTION, - Arrays.asList(KEY), - CUMULATIVE); String prometheusDomain = "external.googleapis.com/prometheus/"; - assertThat(StackdriverExportUtils.createMetric(view, Arrays.asList(VALUE_1), prometheusDomain)) + assertThat( + StackdriverExportUtils.createMetric(METRIC_DESCRIPTOR, LABEL_VALUE, prometheusDomain)) .isEqualTo( Metric.newBuilder() - .setType(prometheusDomain + VIEW_NAME) - .putLabels("KEY", "VALUE1") + .setType(prometheusDomain + METRIC_NAME) + .putLabels("KEY1", "VALUE1") .putLabels(StackdriverExportUtils.OPENCENSUS_TASK, DEFAULT_TASK_VALUE) .build()); } @Test - public void createMetric_skipNullTagValue() { - View view = - View.create( - Name.create(VIEW_NAME), - VIEW_DESCRIPTION, - MEASURE_DOUBLE, - DISTRIBUTION, - Arrays.asList(KEY, KEY_2, KEY_3), - CUMULATIVE); + public void createMetric_EmptyLabel() { assertThat( StackdriverExportUtils.createMetric( - view, Arrays.asList(VALUE_1, null, VALUE_2), CUSTOM_OPENCENSUS_DOMAIN)) + METRIC_DESCRIPTOR_2, EMPTY_LABEL_VALUE, CUSTOM_OPENCENSUS_DOMAIN)) .isEqualTo( Metric.newBuilder() - .setType("custom.googleapis.com/opencensus/" + VIEW_NAME) - .putLabels("KEY", "VALUE1") - .putLabels("KEY3", "VALUE2") + .setType("custom.googleapis.com/opencensus/" + METRIC_NAME) .putLabels(StackdriverExportUtils.OPENCENSUS_TASK, DEFAULT_TASK_VALUE) .build()); } @Test public void createMetric_throwWhenTagKeysAndValuesHaveDifferentSize() { - View view = - View.create( - Name.create(VIEW_NAME), - VIEW_DESCRIPTION, - MEASURE_DOUBLE, - DISTRIBUTION, - Arrays.asList(KEY, KEY_2, KEY_3), - CUMULATIVE); - List tagValues = Arrays.asList(VALUE_1, null); thrown.expect(IllegalArgumentException.class); - thrown.expectMessage("TagKeys and TagValues don't have same size."); - StackdriverExportUtils.createMetric(view, tagValues, CUSTOM_OPENCENSUS_DOMAIN); + thrown.expectMessage("LabelKeys and LabelValues don't have same size."); + StackdriverExportUtils.createMetric( + METRIC_DESCRIPTOR, EMPTY_LABEL_VALUE, CUSTOM_OPENCENSUS_DOMAIN); } @Test @@ -260,141 +222,114 @@ public void convertTimestamp() { .isEqualTo(com.google.protobuf.Timestamp.newBuilder().build()); } - @Test - public void createTimeInterval_cumulative() { - Timestamp censusTimestamp1 = Timestamp.create(100, 3000); - Timestamp censusTimestamp2 = Timestamp.create(200, 0); - assertThat( - StackdriverExportUtils.createTimeInterval( - CumulativeData.create(censusTimestamp1, censusTimestamp2), DISTRIBUTION)) - .isEqualTo( - TimeInterval.newBuilder() - .setStartTime(StackdriverExportUtils.convertTimestamp(censusTimestamp1)) - .setEndTime(StackdriverExportUtils.convertTimestamp(censusTimestamp2)) - .build()); - assertThat( - StackdriverExportUtils.createTimeInterval( - CumulativeData.create(censusTimestamp1, censusTimestamp2), LAST_VALUE)) - .isEqualTo( - TimeInterval.newBuilder() - .setEndTime(StackdriverExportUtils.convertTimestamp(censusTimestamp2)) - .build()); - } - - @Test - public void createTimeInterval_interval() { - IntervalData intervalData = IntervalData.create(Timestamp.create(200, 0)); - // Only Cumulative view will supported in this version. - thrown.expect(IllegalArgumentException.class); - StackdriverExportUtils.createTimeInterval(intervalData, SUM); - } - @Test public void createBucketOptions() { - assertThat(StackdriverExportUtils.createBucketOptions(BUCKET_BOUNDARIES)) + assertThat(StackdriverExportUtils.createBucketOptions(BUCKET_OPTIONS)) .isEqualTo( BucketOptions.newBuilder() .setExplicitBuckets( - Explicit.newBuilder().addAllBounds(Arrays.asList(0.0, 1.0, 3.0, 5.0))) + Explicit.newBuilder().addAllBounds(Arrays.asList(1.0, 3.0, 5.0))) .build()); } + @Test + public void createBucketOptions_Null() { + assertThat(StackdriverExportUtils.createBucketOptions(null)) + .isEqualTo(BucketOptions.newBuilder().build()); + } + @Test public void createDistribution() { - DistributionData distributionData = - DistributionData.create(2, 3, 0, 5, 14, Arrays.asList(0L, 1L, 1L, 0L, 1L)); - assertThat(StackdriverExportUtils.createDistribution(distributionData, BUCKET_BOUNDARIES)) + assertThat(StackdriverExportUtils.createDistribution(DISTRIBUTION)) .isEqualTo( com.google.api.Distribution.newBuilder() - .setMean(2) .setCount(3) - // TODO(songya): uncomment this once Stackdriver supports setting max and min. - // .setRange( - // com.google.api.Distribution.Range.newBuilder().setMin(0).setMax(5).build()) - .setBucketOptions(StackdriverExportUtils.createBucketOptions(BUCKET_BOUNDARIES)) - .addAllBucketCounts(Arrays.asList(0L, 1L, 1L, 0L, 1L)) + .setBucketOptions(StackdriverExportUtils.createBucketOptions(BUCKET_OPTIONS)) + .addAllBucketCounts(Arrays.asList(3L, 1L, 2L, 4L)) .setSumOfSquaredDeviation(14) .build()); } @Test public void createTypedValue() { - assertThat(StackdriverExportUtils.createTypedValue(SUM, SumDataDouble.create(1.1))) + assertThat(StackdriverExportUtils.createTypedValue(DOUBLE_VALUE)) .isEqualTo(TypedValue.newBuilder().setDoubleValue(1.1).build()); - assertThat(StackdriverExportUtils.createTypedValue(SUM, SumDataLong.create(10000))) + assertThat(StackdriverExportUtils.createTypedValue(LONG_VALUE)) .isEqualTo(TypedValue.newBuilder().setInt64Value(10000).build()); - assertThat(StackdriverExportUtils.createTypedValue(COUNT, CountData.create(55))) - .isEqualTo(TypedValue.newBuilder().setInt64Value(55).build()); - assertThat(StackdriverExportUtils.createTypedValue(MEAN, MeanData.create(7.7, 8))) - .isEqualTo(TypedValue.newBuilder().setDoubleValue(7.7).build()); - DistributionData distributionData = - DistributionData.create(2, 3, 0, 5, 14, Arrays.asList(0L, 1L, 1L, 0L, 1L)); - assertThat(StackdriverExportUtils.createTypedValue(DISTRIBUTION, distributionData)) + assertThat(StackdriverExportUtils.createTypedValue(DISTRIBUTION_VALUE)) .isEqualTo( TypedValue.newBuilder() - .setDistributionValue( - StackdriverExportUtils.createDistribution(distributionData, BUCKET_BOUNDARIES)) + .setDistributionValue(StackdriverExportUtils.createDistribution(DISTRIBUTION)) .build()); - assertThat(StackdriverExportUtils.createTypedValue(LAST_VALUE, LastValueDataDouble.create(9.9))) - .isEqualTo(TypedValue.newBuilder().setDoubleValue(9.9).build()); - assertThat(StackdriverExportUtils.createTypedValue(LAST_VALUE, LastValueDataLong.create(90000))) - .isEqualTo(TypedValue.newBuilder().setInt64Value(90000).build()); } @Test - public void createPoint_cumulative() { - Timestamp censusTimestamp1 = Timestamp.create(100, 3000); - Timestamp censusTimestamp2 = Timestamp.create(200, 0); - CumulativeData cumulativeData = CumulativeData.create(censusTimestamp1, censusTimestamp2); - SumDataDouble sumDataDouble = SumDataDouble.create(33.3); + public void createTypedValue_UnknownType() { + assertThat(StackdriverExportUtils.createTypedValue(SUMMARY_VALUE)) + .isEqualTo(TypedValue.newBuilder().build()); + } - assertThat(StackdriverExportUtils.createPoint(sumDataDouble, cumulativeData, SUM)) + @Test + public void createPoint() { + assertThat(StackdriverExportUtils.createPoint(POINT, null)) .isEqualTo( - Point.newBuilder() - .setInterval(StackdriverExportUtils.createTimeInterval(cumulativeData, SUM)) - .setValue(StackdriverExportUtils.createTypedValue(SUM, sumDataDouble)) + com.google.monitoring.v3.Point.newBuilder() + .setInterval( + TimeInterval.newBuilder() + .setEndTime(StackdriverExportUtils.convertTimestamp(TIMESTAMP)) + .build()) + .setValue(StackdriverExportUtils.createTypedValue(VALUE_DOUBLE)) .build()); } @Test - public void createPoint_interval() { - IntervalData intervalData = IntervalData.create(Timestamp.create(200, 0)); - SumDataDouble sumDataDouble = SumDataDouble.create(33.3); - // Only Cumulative view will supported in this version. - thrown.expect(IllegalArgumentException.class); - StackdriverExportUtils.createPoint(sumDataDouble, intervalData, SUM); + public void createPoint_Cumulative() { + assertThat(StackdriverExportUtils.createPoint(POINT, TIMESTAMP_2)) + .isEqualTo( + com.google.monitoring.v3.Point.newBuilder() + .setInterval( + TimeInterval.newBuilder() + .setStartTime(StackdriverExportUtils.convertTimestamp(TIMESTAMP_2)) + .setEndTime(StackdriverExportUtils.convertTimestamp(TIMESTAMP)) + .build()) + .setValue(StackdriverExportUtils.createTypedValue(VALUE_DOUBLE)) + .build()); } @Test - public void createMetricDescriptor_cumulative() { - View view = - View.create( - Name.create(VIEW_NAME), - VIEW_DESCRIPTION, - MEASURE_DOUBLE, - DISTRIBUTION, - Arrays.asList(KEY), - CUMULATIVE); + public void createMetricDescriptor_NotNull() { + assertThat( + StackdriverExportUtils.createMetricDescriptor( + METRIC_DESCRIPTOR, + PROJECT_ID, + CUSTOM_OPENCENSUS_DOMAIN, + DEFAULT_DISPLAY_NAME_PREFIX)) + .isNotNull(); + } + + @Test + public void createMetricDescriptor() { MetricDescriptor metricDescriptor = StackdriverExportUtils.createMetricDescriptor( - view, PROJECT_ID, "custom.googleapis.com/myorg/", "myorg/"); + METRIC_DESCRIPTOR, PROJECT_ID, "custom.googleapis.com/myorg/", "myorg/"); assertThat(metricDescriptor.getName()) .isEqualTo( "projects/" + PROJECT_ID + "/metricDescriptors/custom.googleapis.com/myorg/" - + VIEW_NAME); - assertThat(metricDescriptor.getDescription()).isEqualTo(VIEW_DESCRIPTION); - assertThat(metricDescriptor.getDisplayName()).isEqualTo("myorg/" + VIEW_NAME); - assertThat(metricDescriptor.getType()).isEqualTo("custom.googleapis.com/myorg/" + VIEW_NAME); - assertThat(metricDescriptor.getUnit()).isEqualTo(MEASURE_UNIT); + + METRIC_NAME); + assertThat(metricDescriptor.getDescription()).isEqualTo(METRIC_DESCRIPTION); + assertThat(metricDescriptor.getDisplayName()).isEqualTo("myorg/" + METRIC_NAME); + assertThat(metricDescriptor.getType()).isEqualTo("custom.googleapis.com/myorg/" + METRIC_NAME); + assertThat(metricDescriptor.getUnit()).isEqualTo(METRIC_UNIT); assertThat(metricDescriptor.getMetricKind()).isEqualTo(MetricKind.CUMULATIVE); - assertThat(metricDescriptor.getValueType()).isEqualTo(MetricDescriptor.ValueType.DISTRIBUTION); + + assertThat(metricDescriptor.getValueType()).isEqualTo(MetricDescriptor.ValueType.DOUBLE); assertThat(metricDescriptor.getLabelsList()) .containsExactly( LabelDescriptor.newBuilder() - .setKey(KEY.getName()) - .setDescription(StackdriverExportUtils.LABEL_DESCRIPTION) + .setKey(LABEL_KEY.get(0).getKey()) + .setDescription(LABEL_KEY.get(0).getDescription()) .setValueType(ValueType.STRING) .build(), LabelDescriptor.newBuilder() @@ -405,38 +340,25 @@ public void createMetricDescriptor_cumulative() { } @Test - public void createMetricDescriptor_cumulative_count() { - View view = - View.create( - Name.create(VIEW_NAME), - VIEW_DESCRIPTION, - MEASURE_DOUBLE, - COUNT, - Arrays.asList(KEY), - CUMULATIVE); + public void createMetricDescriptor_cumulative() { MetricDescriptor metricDescriptor = StackdriverExportUtils.createMetricDescriptor( - view, PROJECT_ID, CUSTOM_OPENCENSUS_DOMAIN, DEFAULT_DISPLAY_NAME_PREFIX); + METRIC_DESCRIPTOR_2, PROJECT_ID, CUSTOM_OPENCENSUS_DOMAIN, DEFAULT_DISPLAY_NAME_PREFIX); assertThat(metricDescriptor.getName()) .isEqualTo( "projects/" + PROJECT_ID + "/metricDescriptors/custom.googleapis.com/opencensus/" - + VIEW_NAME); - assertThat(metricDescriptor.getDescription()).isEqualTo(VIEW_DESCRIPTION); - assertThat(metricDescriptor.getDisplayName()).isEqualTo("OpenCensus/" + VIEW_NAME); + + METRIC_NAME); + assertThat(metricDescriptor.getDescription()).isEqualTo(METRIC_DESCRIPTION); + assertThat(metricDescriptor.getDisplayName()).isEqualTo("OpenCensus/" + METRIC_NAME); assertThat(metricDescriptor.getType()) - .isEqualTo("custom.googleapis.com/opencensus/" + VIEW_NAME); + .isEqualTo("custom.googleapis.com/opencensus/" + METRIC_NAME); assertThat(metricDescriptor.getUnit()).isEqualTo("1"); assertThat(metricDescriptor.getMetricKind()).isEqualTo(MetricKind.CUMULATIVE); assertThat(metricDescriptor.getValueType()).isEqualTo(MetricDescriptor.ValueType.INT64); assertThat(metricDescriptor.getLabelsList()) .containsExactly( - LabelDescriptor.newBuilder() - .setKey(KEY.getName()) - .setDescription(StackdriverExportUtils.LABEL_DESCRIPTION) - .setValueType(ValueType.STRING) - .build(), LabelDescriptor.newBuilder() .setKey(StackdriverExportUtils.OPENCENSUS_TASK) .setDescription(StackdriverExportUtils.OPENCENSUS_TASK_DESCRIPTION) @@ -445,114 +367,63 @@ public void createMetricDescriptor_cumulative_count() { } @Test - public void createMetricDescriptor_interval() { - View view = - View.create( - Name.create(VIEW_NAME), - VIEW_DESCRIPTION, - MEASURE_DOUBLE, - DISTRIBUTION, - Arrays.asList(KEY), - INTERVAL); - assertThat( - StackdriverExportUtils.createMetricDescriptor( - view, PROJECT_ID, CUSTOM_OPENCENSUS_DOMAIN, DEFAULT_DISPLAY_NAME_PREFIX)) - .isNull(); + public void createTimeSeriesList_Cumulative() { + List timeSeriesList = + StackdriverExportUtils.createTimeSeriesList( + METRIC, DEFAULT_RESOURCE, CUSTOM_OPENCENSUS_DOMAIN); + assertThat(timeSeriesList).hasSize(1); + TimeSeries expectedTimeSeries = + TimeSeries.newBuilder() + .setMetricKind(MetricKind.CUMULATIVE) + .setValueType(MetricDescriptor.ValueType.DOUBLE) + .setMetric( + StackdriverExportUtils.createMetric( + METRIC_DESCRIPTOR, LABEL_VALUE, CUSTOM_OPENCENSUS_DOMAIN)) + .setResource(MonitoredResource.newBuilder().setType("global")) + .addPoints(StackdriverExportUtils.createPoint(POINT, TIMESTAMP_2)) + .build(); + assertThat(timeSeriesList).containsExactly(expectedTimeSeries); } @Test - public void createTimeSeriesList_cumulative() { - View view = - View.create( - Name.create(VIEW_NAME), - VIEW_DESCRIPTION, - MEASURE_DOUBLE, - DISTRIBUTION, - Arrays.asList(KEY), - CUMULATIVE); - DistributionData distributionData1 = - DistributionData.create(2, 3, 0, 5, 14, Arrays.asList(0L, 1L, 1L, 0L, 1L)); - DistributionData distributionData2 = - DistributionData.create(-1, 1, -1, -1, 0, Arrays.asList(1L, 0L, 0L, 0L, 0L)); - Map, DistributionData> aggregationMap = - ImmutableMap.of( - Arrays.asList(VALUE_1), distributionData1, Arrays.asList(VALUE_2), distributionData2); - CumulativeData cumulativeData = - CumulativeData.create(Timestamp.fromMillis(1000), Timestamp.fromMillis(2000)); - ViewData viewData = ViewData.create(view, aggregationMap, cumulativeData); + public void createTimeSeriesList_Gauge() { + io.opencensus.metrics.export.Metric metric = + io.opencensus.metrics.export.Metric.create( + GAUGE_METRIC_DESCRIPTOR, Arrays.asList(GAUGE_TIME_SERIES, GAUGE_TIME_SERIES_2)); + List timeSeriesList = StackdriverExportUtils.createTimeSeriesList( - viewData, DEFAULT_RESOURCE, CUSTOM_OPENCENSUS_DOMAIN); + metric, DEFAULT_RESOURCE, CUSTOM_OPENCENSUS_DOMAIN); assertThat(timeSeriesList).hasSize(2); TimeSeries expected1 = TimeSeries.newBuilder() - .setMetricKind(MetricKind.CUMULATIVE) - .setValueType(MetricDescriptor.ValueType.DISTRIBUTION) + .setMetricKind(MetricKind.GAUGE) + .setValueType(MetricDescriptor.ValueType.DOUBLE) .setMetric( StackdriverExportUtils.createMetric( - view, Arrays.asList(VALUE_1), CUSTOM_OPENCENSUS_DOMAIN)) + GAUGE_METRIC_DESCRIPTOR, LABEL_VALUE, CUSTOM_OPENCENSUS_DOMAIN)) .setResource(MonitoredResource.newBuilder().setType("global")) - .addPoints( - StackdriverExportUtils.createPoint(distributionData1, cumulativeData, DISTRIBUTION)) + .addPoints(StackdriverExportUtils.createPoint(POINT, null)) .build(); TimeSeries expected2 = TimeSeries.newBuilder() - .setMetricKind(MetricKind.CUMULATIVE) - .setValueType(MetricDescriptor.ValueType.DISTRIBUTION) + .setMetricKind(MetricKind.GAUGE) + .setValueType(MetricDescriptor.ValueType.DOUBLE) .setMetric( StackdriverExportUtils.createMetric( - view, Arrays.asList(VALUE_2), CUSTOM_OPENCENSUS_DOMAIN)) + GAUGE_METRIC_DESCRIPTOR, LABEL_VALUE_2, CUSTOM_OPENCENSUS_DOMAIN)) .setResource(MonitoredResource.newBuilder().setType("global")) - .addPoints( - StackdriverExportUtils.createPoint(distributionData2, cumulativeData, DISTRIBUTION)) + .addPoints(StackdriverExportUtils.createPoint(POINT_2, null)) .build(); assertThat(timeSeriesList).containsExactly(expected1, expected2); } - @Test - public void createTimeSeriesList_interval() { - View view = - View.create( - Name.create(VIEW_NAME), - VIEW_DESCRIPTION, - MEASURE_DOUBLE, - DISTRIBUTION, - Arrays.asList(KEY), - INTERVAL); - Map, DistributionData> aggregationMap = - ImmutableMap.of( - Arrays.asList(VALUE_1), - DistributionData.create(2, 3, 0, 5, 14, Arrays.asList(0L, 1L, 1L, 0L, 1L)), - Arrays.asList(VALUE_2), - DistributionData.create(-1, 1, -1, -1, 0, Arrays.asList(1L, 0L, 0L, 0L, 0L))); - ViewData viewData = - ViewData.create(view, aggregationMap, IntervalData.create(Timestamp.fromMillis(2000))); - assertThat( - StackdriverExportUtils.createTimeSeriesList( - viewData, DEFAULT_RESOURCE, CUSTOM_OPENCENSUS_DOMAIN)) - .isEmpty(); - } - @Test public void createTimeSeriesList_withCustomMonitoredResource() { MonitoredResource resource = MonitoredResource.newBuilder().setType("global").putLabels("key", "value").build(); - View view = - View.create( - Name.create(VIEW_NAME), - VIEW_DESCRIPTION, - MEASURE_DOUBLE, - SUM, - Arrays.asList(KEY), - CUMULATIVE); - SumDataDouble sumData = SumDataDouble.create(55.5); - Map, SumDataDouble> aggregationMap = - ImmutableMap.of(Arrays.asList(VALUE_1), sumData); - CumulativeData cumulativeData = - CumulativeData.create(Timestamp.fromMillis(1000), Timestamp.fromMillis(2000)); - ViewData viewData = ViewData.create(view, aggregationMap, cumulativeData); List timeSeriesList = - StackdriverExportUtils.createTimeSeriesList(viewData, resource, CUSTOM_OPENCENSUS_DOMAIN); + StackdriverExportUtils.createTimeSeriesList(METRIC, resource, CUSTOM_OPENCENSUS_DOMAIN); assertThat(timeSeriesList) .containsExactly( TimeSeries.newBuilder() @@ -560,9 +431,9 @@ public void createTimeSeriesList_withCustomMonitoredResource() { .setValueType(MetricDescriptor.ValueType.DOUBLE) .setMetric( StackdriverExportUtils.createMetric( - view, Arrays.asList(VALUE_1), CUSTOM_OPENCENSUS_DOMAIN)) + METRIC_DESCRIPTOR, LABEL_VALUE, CUSTOM_OPENCENSUS_DOMAIN)) .setResource(resource) - .addPoints(StackdriverExportUtils.createPoint(sumData, cumulativeData, SUM)) + .addPoints(StackdriverExportUtils.createPoint(POINT, TIMESTAMP_2)) .build()); } } diff --git a/exporters/stats/stackdriver/src/test/java/io/opencensus/exporter/stats/stackdriver/StackdriverExporterWorkerTest.java b/exporters/stats/stackdriver/src/test/java/io/opencensus/exporter/stats/stackdriver/StackdriverExporterWorkerTest.java index 27593829e6..c4cb50e6b9 100644 --- a/exporters/stats/stackdriver/src/test/java/io/opencensus/exporter/stats/stackdriver/StackdriverExporterWorkerTest.java +++ b/exporters/stats/stackdriver/src/test/java/io/opencensus/exporter/stats/stackdriver/StackdriverExporterWorkerTest.java @@ -31,7 +31,6 @@ import com.google.api.gax.rpc.UnaryCallable; import com.google.cloud.monitoring.v3.MetricServiceClient; import com.google.cloud.monitoring.v3.stub.MetricServiceStub; -import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.monitoring.v3.CreateMetricDescriptorRequest; import com.google.monitoring.v3.CreateTimeSeriesRequest; @@ -39,21 +38,15 @@ import com.google.protobuf.Empty; import io.opencensus.common.Duration; import io.opencensus.common.Timestamp; -import io.opencensus.stats.Aggregation.Sum; -import io.opencensus.stats.AggregationData; -import io.opencensus.stats.AggregationData.SumDataLong; -import io.opencensus.stats.Measure.MeasureLong; -import io.opencensus.stats.View; -import io.opencensus.stats.View.AggregationWindow.Cumulative; -import io.opencensus.stats.View.AggregationWindow.Interval; -import io.opencensus.stats.View.Name; -import io.opencensus.stats.ViewData; -import io.opencensus.stats.ViewData.AggregationWindowData.CumulativeData; -import io.opencensus.stats.ViewManager; -import io.opencensus.tags.TagKey; -import io.opencensus.tags.TagValue; +import io.opencensus.metrics.LabelKey; +import io.opencensus.metrics.LabelValue; +import io.opencensus.metrics.export.Metric; +import io.opencensus.metrics.export.MetricDescriptor.Type; +import io.opencensus.metrics.export.MetricProducer; +import io.opencensus.metrics.export.MetricProducerManager; +import io.opencensus.metrics.export.Point; +import io.opencensus.metrics.export.Value; import java.io.IOException; -import java.util.Arrays; import java.util.Collections; import java.util.List; import org.junit.Before; @@ -66,25 +59,45 @@ /** Unit tests for {@link StackdriverExporterWorker}. */ @RunWith(JUnit4.class) public class StackdriverExporterWorkerTest { - private static final String PROJECT_ID = "projectId"; private static final Duration ONE_SECOND = Duration.create(1, 0); - private static final TagKey KEY = TagKey.create("KEY"); - private static final TagValue VALUE = TagValue.create("VALUE"); - private static final String MEASURE_NAME = "my measurement"; - private static final String MEASURE_UNIT = "us"; - private static final String MEASURE_DESCRIPTION = "measure description"; - private static final MeasureLong MEASURE = - MeasureLong.create(MEASURE_NAME, MEASURE_DESCRIPTION, MEASURE_UNIT); - private static final Name VIEW_NAME = Name.create("my view"); - private static final String VIEW_DESCRIPTION = "view description"; - private static final Cumulative CUMULATIVE = Cumulative.create(); - private static final Interval INTERVAL = Interval.create(ONE_SECOND); - private static final Sum SUM = Sum.create(); + + private static final String METRIC_NAME = "my metric"; + private static final String METRIC_DESCRIPTION = "metric description"; + private static final String METRIC_DESCRIPTION_2 = "metric description2"; + private static final String METRIC_UNIT = "us"; + private static final List LABEL_KEY = + Collections.singletonList(LabelKey.create("KEY", "key description")); + private static final List LABEL_VALUE = + Collections.singletonList(LabelValue.create("VALUE")); + + private static final io.opencensus.metrics.export.MetricDescriptor METRIC_DESCRIPTOR = + io.opencensus.metrics.export.MetricDescriptor.create( + METRIC_NAME, METRIC_DESCRIPTION, METRIC_UNIT, Type.CUMULATIVE_INT64, LABEL_KEY); + + private static final io.opencensus.metrics.export.MetricDescriptor METRIC_DESCRIPTOR_2 = + io.opencensus.metrics.export.MetricDescriptor.create( + METRIC_NAME, METRIC_DESCRIPTION_2, METRIC_UNIT, Type.CUMULATIVE_INT64, LABEL_KEY); + + private static final Value VALUE_LONG = Value.longValue(12345678); + private static final Timestamp TIMESTAMP = Timestamp.fromMillis(3000); + private static final Timestamp TIMESTAMP_2 = Timestamp.fromMillis(1000); + private static final Point POINT = Point.create(VALUE_LONG, TIMESTAMP); + + private static final io.opencensus.metrics.export.TimeSeries CUMULATIVE_TIME_SERIES = + io.opencensus.metrics.export.TimeSeries.createWithOnePoint(LABEL_VALUE, POINT, TIMESTAMP_2); + + private static final Metric METRIC = + Metric.createWithOneTimeSeries(METRIC_DESCRIPTOR, CUMULATIVE_TIME_SERIES); + private static final Metric METRIC_2 = + Metric.createWithOneTimeSeries(METRIC_DESCRIPTOR_2, CUMULATIVE_TIME_SERIES); + private static final MonitoredResource DEFAULT_RESOURCE = MonitoredResource.newBuilder().setType("global").build(); - @Mock private ViewManager mockViewManager; + @Mock private MetricProducerManager metricProducerManager; + + @Mock private MetricProducer metricProducer; @Mock private MetricServiceStub mockStub; @@ -116,23 +129,16 @@ public void testConstants() { } @Test - public void export() throws IOException { - View view = - View.create(VIEW_NAME, VIEW_DESCRIPTION, MEASURE, SUM, Arrays.asList(KEY), CUMULATIVE); - ViewData viewData = - ViewData.create( - view, - ImmutableMap.of(Arrays.asList(VALUE), SumDataLong.create(1)), - CumulativeData.create(Timestamp.fromMillis(100), Timestamp.fromMillis(200))); - doReturn(ImmutableSet.of(view)).when(mockViewManager).getAllExportedViews(); - doReturn(viewData).when(mockViewManager).getView(VIEW_NAME); + public void export() { + doReturn(ImmutableSet.of(metricProducer)).when(metricProducerManager).getAllMetricProducer(); + doReturn(Collections.singletonList(METRIC)).when(metricProducer).getMetrics(); StackdriverExporterWorker worker = new StackdriverExporterWorker( PROJECT_ID, new FakeMetricServiceClient(mockStub), ONE_SECOND, - mockViewManager, + metricProducerManager, DEFAULT_RESOURCE, null); worker.export(); @@ -142,10 +148,10 @@ public void export() throws IOException { MetricDescriptor descriptor = StackdriverExportUtils.createMetricDescriptor( - view, PROJECT_ID, CUSTOM_OPENCENSUS_DOMAIN, DEFAULT_DISPLAY_NAME_PREFIX); + METRIC_DESCRIPTOR, PROJECT_ID, CUSTOM_OPENCENSUS_DOMAIN, DEFAULT_DISPLAY_NAME_PREFIX); List timeSeries = StackdriverExportUtils.createTimeSeriesList( - viewData, DEFAULT_RESOURCE, CUSTOM_OPENCENSUS_DOMAIN); + METRIC, DEFAULT_RESOURCE, CUSTOM_OPENCENSUS_DOMAIN); verify(mockCreateMetricDescriptorCallable, times(1)) .call( eq( @@ -163,112 +169,92 @@ public void export() throws IOException { } @Test - public void doNotExportForEmptyViewData() { - View view = - View.create(VIEW_NAME, VIEW_DESCRIPTION, MEASURE, SUM, Arrays.asList(KEY), CUMULATIVE); - ViewData empty = - ViewData.create( - view, - Collections., AggregationData>emptyMap(), - CumulativeData.create(Timestamp.fromMillis(100), Timestamp.fromMillis(200))); - doReturn(ImmutableSet.of(view)).when(mockViewManager).getAllExportedViews(); - doReturn(empty).when(mockViewManager).getView(VIEW_NAME); + public void doNotExportForEmptyMetrics() { + doReturn(ImmutableSet.of(metricProducer)).when(metricProducerManager).getAllMetricProducer(); + doReturn(Collections.EMPTY_LIST).when(metricProducer).getMetrics(); StackdriverExporterWorker worker = new StackdriverExporterWorker( PROJECT_ID, new FakeMetricServiceClient(mockStub), ONE_SECOND, - mockViewManager, + metricProducerManager, DEFAULT_RESOURCE, null); worker.export(); - verify(mockStub, times(1)).createMetricDescriptorCallable(); + verify(mockStub, times(0)).createMetricDescriptorCallable(); verify(mockStub, times(0)).createTimeSeriesCallable(); } @Test - public void doNotExportIfFailedToRegisterView() { - View view = - View.create(VIEW_NAME, VIEW_DESCRIPTION, MEASURE, SUM, Arrays.asList(KEY), CUMULATIVE); - doReturn(ImmutableSet.of(view)).when(mockViewManager).getAllExportedViews(); + public void doNotExportIfFailedToRegisterMetric() { + doReturn(ImmutableSet.of(metricProducer)).when(metricProducerManager).getAllMetricProducer(); doThrow(new IllegalArgumentException()).when(mockStub).createMetricDescriptorCallable(); StackdriverExporterWorker worker = new StackdriverExporterWorker( PROJECT_ID, new FakeMetricServiceClient(mockStub), ONE_SECOND, - mockViewManager, + metricProducerManager, DEFAULT_RESOURCE, null); - assertThat(worker.registerView(view)).isFalse(); + assertThat(worker.registerMetric(METRIC)).isFalse(); worker.export(); verify(mockStub, times(1)).createMetricDescriptorCallable(); verify(mockStub, times(0)).createTimeSeriesCallable(); } @Test - public void skipDifferentViewWithSameName() throws IOException { + public void skipDifferentMetricWithSameName() throws IOException { StackdriverExporterWorker worker = new StackdriverExporterWorker( PROJECT_ID, new FakeMetricServiceClient(mockStub), ONE_SECOND, - mockViewManager, + metricProducerManager, DEFAULT_RESOURCE, null); - View view1 = - View.create(VIEW_NAME, VIEW_DESCRIPTION, MEASURE, SUM, Arrays.asList(KEY), CUMULATIVE); - assertThat(worker.registerView(view1)).isTrue(); + assertThat(worker.registerMetric(METRIC)).isTrue(); verify(mockStub, times(1)).createMetricDescriptorCallable(); - View view2 = - View.create( - VIEW_NAME, - "This is a different description.", - MEASURE, - SUM, - Arrays.asList(KEY), - CUMULATIVE); - assertThat(worker.registerView(view2)).isFalse(); + assertThat(worker.registerMetric(METRIC_2)).isFalse(); verify(mockStub, times(1)).createMetricDescriptorCallable(); } @Test - public void doNotCreateMetricDescriptorForRegisteredView() { + public void skipSameMetricWithSameName() throws IOException { StackdriverExporterWorker worker = new StackdriverExporterWorker( PROJECT_ID, new FakeMetricServiceClient(mockStub), ONE_SECOND, - mockViewManager, + metricProducerManager, DEFAULT_RESOURCE, null); - View view = - View.create(VIEW_NAME, VIEW_DESCRIPTION, MEASURE, SUM, Arrays.asList(KEY), CUMULATIVE); - assertThat(worker.registerView(view)).isTrue(); + assertThat(worker.registerMetric(METRIC)).isTrue(); verify(mockStub, times(1)).createMetricDescriptorCallable(); - assertThat(worker.registerView(view)).isTrue(); + assertThat(worker.registerMetric(METRIC)).isTrue(); verify(mockStub, times(1)).createMetricDescriptorCallable(); } @Test - public void doNotCreateMetricDescriptorForIntervalView() { + public void doNotCreateMetricDescriptorForRegisteredeMetric() { StackdriverExporterWorker worker = new StackdriverExporterWorker( PROJECT_ID, new FakeMetricServiceClient(mockStub), ONE_SECOND, - mockViewManager, + metricProducerManager, DEFAULT_RESOURCE, null); - View view = - View.create(VIEW_NAME, VIEW_DESCRIPTION, MEASURE, SUM, Arrays.asList(KEY), INTERVAL); - assertThat(worker.registerView(view)).isFalse(); - verify(mockStub, times(0)).createMetricDescriptorCallable(); + assertThat(worker.registerMetric(METRIC)).isTrue(); + verify(mockStub, times(1)).createMetricDescriptorCallable(); + + assertThat(worker.registerMetric(METRIC)).isTrue(); + verify(mockStub, times(1)).createMetricDescriptorCallable(); } @Test From bf815c618c2ba81ef906bb301a56ec996cc17325 Mon Sep 17 00:00:00 2001 From: Mayur Kale Date: Wed, 17 Oct 2018 10:19:40 -0700 Subject: [PATCH 2/3] Fix review comments --- buildscripts/import-control.xml | 2 +- .../stackdriver/StackdriverExportUtils.java | 27 +++++++------ .../StackdriverExporterWorker.java | 39 ++++++++++--------- .../StackdriverExportUtilsTest.java | 14 +------ .../StackdriverExporterWorkerTest.java | 21 ++++------ 5 files changed, 45 insertions(+), 58 deletions(-) diff --git a/buildscripts/import-control.xml b/buildscripts/import-control.xml index fbf217d099..b3de25a59b 100644 --- a/buildscripts/import-control.xml +++ b/buildscripts/import-control.xml @@ -148,7 +148,6 @@ General guidelines on imports: - @@ -164,6 +163,7 @@ General guidelines on imports: + diff --git a/exporters/stats/stackdriver/src/main/java/io/opencensus/exporter/stats/stackdriver/StackdriverExportUtils.java b/exporters/stats/stackdriver/src/main/java/io/opencensus/exporter/stats/stackdriver/StackdriverExportUtils.java index 4079ded719..dbf67c378d 100644 --- a/exporters/stats/stackdriver/src/main/java/io/opencensus/exporter/stats/stackdriver/StackdriverExportUtils.java +++ b/exporters/stats/stackdriver/src/main/java/io/opencensus/exporter/stats/stackdriver/StackdriverExportUtils.java @@ -100,6 +100,15 @@ public TypedValue apply(Long arg) { return builder.build(); } }; + private static final Function + typedValueDistributionFunction = + new Function() { + @Override + public TypedValue apply(io.opencensus.metrics.export.Distribution arg) { + TypedValue.Builder builder = TypedValue.newBuilder(); + return builder.setDistributionValue(createDistribution(arg)).build(); + } + }; private static final Function typedValueSummaryFunction = new Function() { @Override @@ -217,14 +226,10 @@ static MetricDescriptor.ValueType createValueType(Type type) { // Convert metric's timeseries to a list of TimeSeries, so that metric can be uploaded to // StackDriver. static List createTimeSeriesList( - @javax.annotation.Nullable io.opencensus.metrics.export.Metric metric, + io.opencensus.metrics.export.Metric metric, MonitoredResource monitoredResource, String domain) { List timeSeriesList = Lists.newArrayList(); - if (metric == null) { - return timeSeriesList; - } - io.opencensus.metrics.export.MetricDescriptor metricDescriptor = metric.getMetricDescriptor(); // Shared fields for all TimeSeries generated from the same Metric @@ -258,8 +263,7 @@ static Metric createMetric( Map stringTagMap = Maps.newHashMap(); List labelKeys = metricDescriptor.getLabelKeys(); - checkArgument( - labelKeys.size() == labelValues.size(), "LabelKeys and LabelValues don't have same size."); + checkArgument(labelKeys.size() == labelValues.size(), "Keys and Values don't have same size."); for (int i = 0; i < labelValues.size(); i++) { String value = labelValues.get(i).getValue(); @@ -297,13 +301,7 @@ static TypedValue createTypedValue(Value value) { return value.match( typedValueDoubleFunction, typedValueLongFunction, - new Function() { - @Override - public TypedValue apply(io.opencensus.metrics.export.Distribution arg) { - TypedValue.Builder builder = TypedValue.newBuilder(); - return builder.setDistributionValue(createDistribution(arg)).build(); - } - }, + typedValueDistributionFunction, typedValueSummaryFunction, Functions.throwIllegalArgumentException()); } @@ -315,6 +313,7 @@ static Distribution createDistribution(io.opencensus.metrics.export.Distribution .setBucketOptions(createBucketOptions(distribution.getBucketOptions())) .addAllBucketCounts(createBucketCounts(distribution.getBuckets())) .setCount(distribution.getCount()) + .setMean(distribution.getCount() == 0 ? 0 : distribution.getSum() / distribution.getCount()) .setSumOfSquaredDeviation(distribution.getSumOfSquaredDeviations()) .build(); } diff --git a/exporters/stats/stackdriver/src/main/java/io/opencensus/exporter/stats/stackdriver/StackdriverExporterWorker.java b/exporters/stats/stackdriver/src/main/java/io/opencensus/exporter/stats/stackdriver/StackdriverExporterWorker.java index 713b687271..8958906399 100644 --- a/exporters/stats/stackdriver/src/main/java/io/opencensus/exporter/stats/stackdriver/StackdriverExporterWorker.java +++ b/exporters/stats/stackdriver/src/main/java/io/opencensus/exporter/stats/stackdriver/StackdriverExporterWorker.java @@ -39,7 +39,7 @@ import io.opencensus.trace.Tracing; import io.opencensus.trace.samplers.Samplers; import java.util.Collections; -import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.logging.Level; @@ -80,7 +80,8 @@ final class StackdriverExporterWorker implements Runnable { private final MonitoredResource monitoredResource; private final String domain; private final String displayNamePrefix; - private final Map registeredMetrics = new HashMap(); + private final Map + registeredMetricDescriptors = new LinkedHashMap<>(); private static final Tracer tracer = Tracing.getTracer(); private static final Sampler probabilitySampler = Samplers.probabilitySampler(0.0001); @@ -107,35 +108,37 @@ final class StackdriverExporterWorker implements Runnable { Collections.singletonList("ExportStatsToStackdriverMonitoring")); } - // Returns true if the given metric is successfully registered to Stackdriver Monitoring, or the + // Returns true if the given metricDescriptor is successfully registered to Stackdriver + // Monitoring, or the // exact same metric has already been registered. Returns false otherwise. @VisibleForTesting - boolean registerMetric(Metric metric) { - Metric existingMetric = registeredMetrics.get(metric.getMetricDescriptor().getName()); - if (existingMetric != null) { - if (existingMetric.getMetricDescriptor().equals(metric.getMetricDescriptor())) { - // Ignore metric that are already registered. + boolean registerMetricDescriptor(io.opencensus.metrics.export.MetricDescriptor metricDescriptor) { + io.opencensus.metrics.export.MetricDescriptor existingMetricDescriptor = + registeredMetricDescriptors.get(metricDescriptor.getName()); + if (existingMetricDescriptor != null) { + if (existingMetricDescriptor.equals(metricDescriptor)) { + // Ignore metricDescriptor that are already registered. return true; } else { logger.log( Level.WARNING, "A different metric with the same name is already registered: " - + existingMetric.getMetricDescriptor()); + + existingMetricDescriptor); return false; } } - registeredMetrics.put(metric.getMetricDescriptor().getName(), metric); + registeredMetricDescriptors.put(metricDescriptor.getName(), metricDescriptor); Span span = tracer.getCurrentSpan(); span.addAnnotation("Create Stackdriver Metric."); - MetricDescriptor metricDescriptor = + MetricDescriptor stackDriverMetricDescriptor = StackdriverExportUtils.createMetricDescriptor( - metric.getMetricDescriptor(), projectId, domain, displayNamePrefix); + metricDescriptor, projectId, domain, displayNamePrefix); CreateMetricDescriptorRequest request = CreateMetricDescriptorRequest.newBuilder() .setName(projectName.toString()) - .setMetricDescriptor(metricDescriptor) + .setMetricDescriptor(stackDriverMetricDescriptor) .build(); try { metricServiceClient.createMetricDescriptor(request); @@ -158,21 +161,21 @@ boolean registerMetric(Metric metric) { } } - // Polls MetricProducerManager from Metrics library for all registered metrics, and upload them as - // TimeSeries to StackDriver. + // Polls MetricProducerManager from Metrics library for all registered MetricDescriptors, and + // upload them as TimeSeries to StackDriver. @VisibleForTesting void export() { - List metricsList = Lists.newArrayList(); + List metricsList = Lists.newArrayList(); for (MetricProducer metricProducer : metricProducerManager.getAllMetricProducer()) { for (Metric metric : metricProducer.getMetrics()) { - if (registerMetric(metric)) { + if (registerMetricDescriptor(metric.getMetricDescriptor())) { metricsList.add(metric); } } } List timeSeriesList = Lists.newArrayList(); - for (/*@Nullable*/ Metric metric : metricsList) { + for (Metric metric : metricsList) { timeSeriesList.addAll( StackdriverExportUtils.createTimeSeriesList(metric, monitoredResource, domain)); } diff --git a/exporters/stats/stackdriver/src/test/java/io/opencensus/exporter/stats/stackdriver/StackdriverExportUtilsTest.java b/exporters/stats/stackdriver/src/test/java/io/opencensus/exporter/stats/stackdriver/StackdriverExportUtilsTest.java index ddbe258afb..dc60b4b8e6 100644 --- a/exporters/stats/stackdriver/src/test/java/io/opencensus/exporter/stats/stackdriver/StackdriverExportUtilsTest.java +++ b/exporters/stats/stackdriver/src/test/java/io/opencensus/exporter/stats/stackdriver/StackdriverExportUtilsTest.java @@ -203,7 +203,7 @@ public void createMetric_EmptyLabel() { @Test public void createMetric_throwWhenTagKeysAndValuesHaveDifferentSize() { thrown.expect(IllegalArgumentException.class); - thrown.expectMessage("LabelKeys and LabelValues don't have same size."); + thrown.expectMessage("Keys and Values don't have same size."); StackdriverExportUtils.createMetric( METRIC_DESCRIPTOR, EMPTY_LABEL_VALUE, CUSTOM_OPENCENSUS_DOMAIN); } @@ -244,6 +244,7 @@ public void createDistribution() { .isEqualTo( com.google.api.Distribution.newBuilder() .setCount(3) + .setMean(0.6666666666666666) .setBucketOptions(StackdriverExportUtils.createBucketOptions(BUCKET_OPTIONS)) .addAllBucketCounts(Arrays.asList(3L, 1L, 2L, 4L)) .setSumOfSquaredDeviation(14) @@ -296,17 +297,6 @@ public void createPoint_Cumulative() { .build()); } - @Test - public void createMetricDescriptor_NotNull() { - assertThat( - StackdriverExportUtils.createMetricDescriptor( - METRIC_DESCRIPTOR, - PROJECT_ID, - CUSTOM_OPENCENSUS_DOMAIN, - DEFAULT_DISPLAY_NAME_PREFIX)) - .isNotNull(); - } - @Test public void createMetricDescriptor() { MetricDescriptor metricDescriptor = diff --git a/exporters/stats/stackdriver/src/test/java/io/opencensus/exporter/stats/stackdriver/StackdriverExporterWorkerTest.java b/exporters/stats/stackdriver/src/test/java/io/opencensus/exporter/stats/stackdriver/StackdriverExporterWorkerTest.java index c4cb50e6b9..46f0bc7fdd 100644 --- a/exporters/stats/stackdriver/src/test/java/io/opencensus/exporter/stats/stackdriver/StackdriverExporterWorkerTest.java +++ b/exporters/stats/stackdriver/src/test/java/io/opencensus/exporter/stats/stackdriver/StackdriverExporterWorkerTest.java @@ -117,6 +117,7 @@ public void setUp() { .when(mockCreateMetricDescriptorCallable) .call(any(CreateMetricDescriptorRequest.class)); doReturn(null).when(mockCreateTimeSeriesCallable).call(any(CreateTimeSeriesRequest.class)); + doReturn(ImmutableSet.of(metricProducer)).when(metricProducerManager).getAllMetricProducer(); } @Test @@ -130,9 +131,7 @@ public void testConstants() { @Test public void export() { - doReturn(ImmutableSet.of(metricProducer)).when(metricProducerManager).getAllMetricProducer(); doReturn(Collections.singletonList(METRIC)).when(metricProducer).getMetrics(); - StackdriverExporterWorker worker = new StackdriverExporterWorker( PROJECT_ID, @@ -170,9 +169,7 @@ public void export() { @Test public void doNotExportForEmptyMetrics() { - doReturn(ImmutableSet.of(metricProducer)).when(metricProducerManager).getAllMetricProducer(); doReturn(Collections.EMPTY_LIST).when(metricProducer).getMetrics(); - StackdriverExporterWorker worker = new StackdriverExporterWorker( PROJECT_ID, @@ -181,7 +178,6 @@ public void doNotExportForEmptyMetrics() { metricProducerManager, DEFAULT_RESOURCE, null); - worker.export(); verify(mockStub, times(0)).createMetricDescriptorCallable(); verify(mockStub, times(0)).createTimeSeriesCallable(); @@ -189,7 +185,6 @@ public void doNotExportForEmptyMetrics() { @Test public void doNotExportIfFailedToRegisterMetric() { - doReturn(ImmutableSet.of(metricProducer)).when(metricProducerManager).getAllMetricProducer(); doThrow(new IllegalArgumentException()).when(mockStub).createMetricDescriptorCallable(); StackdriverExporterWorker worker = new StackdriverExporterWorker( @@ -200,7 +195,7 @@ public void doNotExportIfFailedToRegisterMetric() { DEFAULT_RESOURCE, null); - assertThat(worker.registerMetric(METRIC)).isFalse(); + assertThat(worker.registerMetricDescriptor(METRIC_DESCRIPTOR)).isFalse(); worker.export(); verify(mockStub, times(1)).createMetricDescriptorCallable(); verify(mockStub, times(0)).createTimeSeriesCallable(); @@ -216,10 +211,10 @@ public void skipDifferentMetricWithSameName() throws IOException { metricProducerManager, DEFAULT_RESOURCE, null); - assertThat(worker.registerMetric(METRIC)).isTrue(); + assertThat(worker.registerMetricDescriptor(METRIC_DESCRIPTOR)).isTrue(); verify(mockStub, times(1)).createMetricDescriptorCallable(); - assertThat(worker.registerMetric(METRIC_2)).isFalse(); + assertThat(worker.registerMetricDescriptor(METRIC_DESCRIPTOR_2)).isFalse(); verify(mockStub, times(1)).createMetricDescriptorCallable(); } @@ -233,10 +228,10 @@ public void skipSameMetricWithSameName() throws IOException { metricProducerManager, DEFAULT_RESOURCE, null); - assertThat(worker.registerMetric(METRIC)).isTrue(); + assertThat(worker.registerMetricDescriptor(METRIC_DESCRIPTOR)).isTrue(); verify(mockStub, times(1)).createMetricDescriptorCallable(); - assertThat(worker.registerMetric(METRIC)).isTrue(); + assertThat(worker.registerMetricDescriptor(METRIC_DESCRIPTOR)).isTrue(); verify(mockStub, times(1)).createMetricDescriptorCallable(); } @@ -250,10 +245,10 @@ public void doNotCreateMetricDescriptorForRegisteredeMetric() { metricProducerManager, DEFAULT_RESOURCE, null); - assertThat(worker.registerMetric(METRIC)).isTrue(); + assertThat(worker.registerMetricDescriptor(METRIC_DESCRIPTOR)).isTrue(); verify(mockStub, times(1)).createMetricDescriptorCallable(); - assertThat(worker.registerMetric(METRIC)).isTrue(); + assertThat(worker.registerMetricDescriptor(METRIC_DESCRIPTOR)).isTrue(); verify(mockStub, times(1)).createMetricDescriptorCallable(); } From 998d0539ff574df176bcfd1688870a69b346e071 Mon Sep 17 00:00:00 2001 From: Mayur Kale Date: Wed, 24 Oct 2018 08:36:08 -0700 Subject: [PATCH 3/3] Fix review comments --- .../stats/stackdriver/StackdriverExportUtils.java | 10 ++++------ .../stats/stackdriver/StackdriverExporterWorker.java | 8 ++++++-- .../stackdriver/StackdriverExportUtilsTest.java | 12 ------------ 3 files changed, 10 insertions(+), 20 deletions(-) diff --git a/exporters/stats/stackdriver/src/main/java/io/opencensus/exporter/stats/stackdriver/StackdriverExportUtils.java b/exporters/stats/stackdriver/src/main/java/io/opencensus/exporter/stats/stackdriver/StackdriverExportUtils.java index dbf67c378d..400b1156e2 100644 --- a/exporters/stats/stackdriver/src/main/java/io/opencensus/exporter/stats/stackdriver/StackdriverExportUtils.java +++ b/exporters/stats/stackdriver/src/main/java/io/opencensus/exporter/stats/stackdriver/StackdriverExportUtils.java @@ -16,8 +16,6 @@ package io.opencensus.exporter.stats.stackdriver; -import static com.google.common.base.Preconditions.checkArgument; - import com.google.api.Distribution; import com.google.api.Distribution.BucketOptions; import com.google.api.Distribution.BucketOptions.Explicit; @@ -114,6 +112,7 @@ public TypedValue apply(io.opencensus.metrics.export.Distribution arg) { @Override public TypedValue apply(Summary arg) { // StackDriver doesn't handle Summary value. + // TODO(mayurkale): decide what to do with Summary value. Builder builder = TypedValue.newBuilder(); return builder.build(); } @@ -158,7 +157,7 @@ static MetricDescriptor createMetricDescriptor( String type = generateType(metricDescriptor.getName(), domain); // Name format refers to // cloud.google.com/monitoring/api/ref_v3/rest/v3/projects.metricDescriptors/create - builder.setName(String.format("projects/%s/metricDescriptors/%s", projectId, type)); + builder.setName("projects/" + projectId + "/metricDescriptors/" + type); builder.setType(type); builder.setDescription(metricDescriptor.getDescription()); builder.setDisplayName(createDisplayName(metricDescriptor.getName(), displayNamePrefix)); @@ -213,6 +212,7 @@ static MetricKind createMetricKind(Type type) { // Convert a OpenCensus Type to a StackDriver ValueType @VisibleForTesting static MetricDescriptor.ValueType createValueType(Type type) { + // TODO(mayurkale): decide what to do with Summary type. if (type == Type.CUMULATIVE_DOUBLE || type == Type.GAUGE_DOUBLE) { return MetricDescriptor.ValueType.DOUBLE; } else if (type == Type.GAUGE_INT64 || type == Type.CUMULATIVE_INT64) { @@ -240,6 +240,7 @@ static List createTimeSeriesList( // Each entry in timeSeriesList will be converted into an independent TimeSeries object for (io.opencensus.metrics.export.TimeSeries timeSeries : metric.getTimeSeriesList()) { + // TODO(mayurkale): Consider using setPoints instead of builder clone and addPoints. TimeSeries.Builder builder = shared.clone(); builder.setMetric(createMetric(metricDescriptor, timeSeries.getLabelValues(), domain)); @@ -262,9 +263,6 @@ static Metric createMetric( builder.setType(generateType(metricDescriptor.getName(), domain)); Map stringTagMap = Maps.newHashMap(); List labelKeys = metricDescriptor.getLabelKeys(); - - checkArgument(labelKeys.size() == labelValues.size(), "Keys and Values don't have same size."); - for (int i = 0; i < labelValues.size(); i++) { String value = labelValues.get(i).getValue(); if (value == null) { diff --git a/exporters/stats/stackdriver/src/main/java/io/opencensus/exporter/stats/stackdriver/StackdriverExporterWorker.java b/exporters/stats/stackdriver/src/main/java/io/opencensus/exporter/stats/stackdriver/StackdriverExporterWorker.java index 8958906399..e493803cef 100644 --- a/exporters/stats/stackdriver/src/main/java/io/opencensus/exporter/stats/stackdriver/StackdriverExporterWorker.java +++ b/exporters/stats/stackdriver/src/main/java/io/opencensus/exporter/stats/stackdriver/StackdriverExporterWorker.java @@ -38,6 +38,8 @@ import io.opencensus.trace.Tracer; import io.opencensus.trace.Tracing; import io.opencensus.trace.samplers.Samplers; +import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.LinkedHashMap; import java.util.List; @@ -165,9 +167,11 @@ boolean registerMetricDescriptor(io.opencensus.metrics.export.MetricDescriptor m // upload them as TimeSeries to StackDriver. @VisibleForTesting void export() { - List metricsList = Lists.newArrayList(); + ArrayList metricsList = Lists.newArrayList(); for (MetricProducer metricProducer : metricProducerManager.getAllMetricProducer()) { - for (Metric metric : metricProducer.getMetrics()) { + Collection producerMetricsList = metricProducer.getMetrics(); + metricsList.ensureCapacity(metricsList.size() + producerMetricsList.size()); + for (Metric metric : producerMetricsList) { if (registerMetricDescriptor(metric.getMetricDescriptor())) { metricsList.add(metric); } diff --git a/exporters/stats/stackdriver/src/test/java/io/opencensus/exporter/stats/stackdriver/StackdriverExportUtilsTest.java b/exporters/stats/stackdriver/src/test/java/io/opencensus/exporter/stats/stackdriver/StackdriverExportUtilsTest.java index dc60b4b8e6..8b8cd5b0aa 100644 --- a/exporters/stats/stackdriver/src/test/java/io/opencensus/exporter/stats/stackdriver/StackdriverExportUtilsTest.java +++ b/exporters/stats/stackdriver/src/test/java/io/opencensus/exporter/stats/stackdriver/StackdriverExportUtilsTest.java @@ -46,17 +46,13 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; -import org.junit.Rule; import org.junit.Test; -import org.junit.rules.ExpectedException; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; /** Unit tests for {@link StackdriverExportUtils}. */ @RunWith(JUnit4.class) public class StackdriverExportUtilsTest { - @Rule public final ExpectedException thrown = ExpectedException.none(); - private static final String METRIC_NAME = "my measurement"; private static final String METRIC_DESCRIPTION = "measure description"; private static final String METRIC_UNIT = "us"; @@ -200,14 +196,6 @@ public void createMetric_EmptyLabel() { .build()); } - @Test - public void createMetric_throwWhenTagKeysAndValuesHaveDifferentSize() { - thrown.expect(IllegalArgumentException.class); - thrown.expectMessage("Keys and Values don't have same size."); - StackdriverExportUtils.createMetric( - METRIC_DESCRIPTOR, EMPTY_LABEL_VALUE, CUSTOM_OPENCENSUS_DOMAIN); - } - @Test public void convertTimestamp() { Timestamp censusTimestamp1 = Timestamp.create(100, 3000);