diff --git a/google-cloud-bigtable-stats/src/main/java/com/google/cloud/bigtable/stats/BuiltinMeasureConstants.java b/google-cloud-bigtable-stats/src/main/java/com/google/cloud/bigtable/stats/BuiltinMeasureConstants.java index 0f6a879ab3..b60eaf6181 100644 --- a/google-cloud-bigtable-stats/src/main/java/com/google/cloud/bigtable/stats/BuiltinMeasureConstants.java +++ b/google-cloud-bigtable-stats/src/main/java/com/google/cloud/bigtable/stats/BuiltinMeasureConstants.java @@ -17,25 +17,24 @@ import static io.opencensus.stats.Measure.MeasureLong; -import com.google.api.core.InternalApi; import io.opencensus.tags.TagKey; -@InternalApi("For internal use only") -public class BuiltinMeasureConstants { +/** Built-in metrics that will be readable under bigtable.googleapis.com/client namespace */ +class BuiltinMeasureConstants { // TagKeys - public static final TagKey PROJECT_ID = TagKey.create("project_id"); - public static final TagKey INSTANCE_ID = TagKey.create("instance_id"); - public static final TagKey APP_PROFILE = TagKey.create("app_profile"); - public static final TagKey METHOD = TagKey.create("method"); - public static final TagKey STREAMING = TagKey.create("streaming"); - public static final TagKey STATUS = TagKey.create("status"); - public static final TagKey CLIENT_NAME = TagKey.create("client_name"); - public static final TagKey CLIENT_ID = TagKey.create("client_id"); + static final TagKey PROJECT_ID = TagKey.create("project_id"); + static final TagKey INSTANCE_ID = TagKey.create("instance_id"); + static final TagKey APP_PROFILE = TagKey.create("app_profile"); + static final TagKey METHOD = TagKey.create("method"); + static final TagKey STREAMING = TagKey.create("streaming"); + static final TagKey STATUS = TagKey.create("status"); + static final TagKey CLIENT_NAME = TagKey.create("client_name"); + static final TagKey CLIENT_ID = TagKey.create("client_id"); // Monitored resource TagKeys - public static final TagKey TABLE = TagKey.create("table"); - public static final TagKey CLUSTER = TagKey.create("cluster"); - public static final TagKey ZONE = TagKey.create("zone"); + static final TagKey TABLE = TagKey.create("table"); + static final TagKey CLUSTER = TagKey.create("cluster"); + static final TagKey ZONE = TagKey.create("zone"); // Units private static final String COUNT = "1"; diff --git a/google-cloud-bigtable-stats/src/main/java/com/google/cloud/bigtable/stats/BuiltinMetricsRecorder.java b/google-cloud-bigtable-stats/src/main/java/com/google/cloud/bigtable/stats/BuiltinMetricsRecorder.java deleted file mode 100644 index a66da11d0b..0000000000 --- a/google-cloud-bigtable-stats/src/main/java/com/google/cloud/bigtable/stats/BuiltinMetricsRecorder.java +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Copyright 2022 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.google.cloud.bigtable.stats; - -import com.google.api.core.InternalApi; -import com.google.api.gax.tracing.ApiTracerFactory.OperationType; -import com.google.api.gax.tracing.SpanName; -import io.opencensus.stats.MeasureMap; -import io.opencensus.stats.StatsRecorder; -import io.opencensus.tags.TagContext; -import io.opencensus.tags.TagContextBuilder; -import io.opencensus.tags.TagKey; -import io.opencensus.tags.TagValue; -import io.opencensus.tags.Tagger; -import io.opencensus.tags.Tags; -import java.util.Map; - -/** Add built-in metrics to the measure map * */ -@InternalApi("For internal use only") -public class BuiltinMetricsRecorder { - - private final OperationType operationType; - - private final Tagger tagger; - private final StatsRecorder statsRecorder; - private final TagContext parentContext; - private final SpanName spanName; - private final Map statsAttributes; - - private MeasureMap attemptLevelNoStreaming; - private MeasureMap attemptLevelWithStreaming; - private MeasureMap operationLevelNoStreaming; - private MeasureMap operationLevelWithStreaming; - - public BuiltinMetricsRecorder( - OperationType operationType, - SpanName spanName, - Map statsAttributes, - StatsWrapper builtinMetricsWrapper) { - this.operationType = operationType; - this.tagger = Tags.getTagger(); - this.statsRecorder = builtinMetricsWrapper.getStatsRecorder(); - this.spanName = spanName; - this.parentContext = tagger.getCurrentTagContext(); - this.statsAttributes = statsAttributes; - - this.attemptLevelNoStreaming = statsRecorder.newMeasureMap(); - this.attemptLevelWithStreaming = statsRecorder.newMeasureMap(); - this.operationLevelNoStreaming = statsRecorder.newMeasureMap(); - this.operationLevelWithStreaming = statsRecorder.newMeasureMap(); - } - - public void recordAttemptLevelWithoutStreaming( - String status, String tableId, String zone, String cluster) { - TagContextBuilder tagCtx = - newTagContextBuilder(tableId, zone, cluster) - .putLocal(BuiltinMeasureConstants.STATUS, TagValue.create(status)); - - attemptLevelNoStreaming.record(tagCtx.build()); - } - - public void recordAttemptLevelWithStreaming( - String status, String tableId, String zone, String cluster) { - TagContextBuilder tagCtx = - newTagContextBuilder(tableId, zone, cluster) - .putLocal(BuiltinMeasureConstants.STATUS, TagValue.create(status)); - - if (operationType == OperationType.ServerStreaming - && spanName.getMethodName().equals("ReadRows")) { - tagCtx.putLocal(BuiltinMeasureConstants.STREAMING, TagValue.create("true")); - } else { - tagCtx.putLocal(BuiltinMeasureConstants.STREAMING, TagValue.create("false")); - } - - attemptLevelWithStreaming.record(tagCtx.build()); - } - - public void recordOperationLevelWithoutStreaming( - String status, String tableId, String zone, String cluster) { - TagContextBuilder tagCtx = - newTagContextBuilder(tableId, zone, cluster) - .putLocal(BuiltinMeasureConstants.STATUS, TagValue.create(status)); - - operationLevelNoStreaming.record(tagCtx.build()); - } - - public void recordOperationLevelWithStreaming( - String status, String tableId, String zone, String cluster) { - TagContextBuilder tagCtx = - newTagContextBuilder(tableId, zone, cluster) - .putLocal(BuiltinMeasureConstants.STATUS, TagValue.create(status)); - - if (operationType == OperationType.ServerStreaming - && spanName.getMethodName().equals("ReadRows")) { - tagCtx.putLocal(BuiltinMeasureConstants.STREAMING, TagValue.create("true")); - } else { - tagCtx.putLocal(BuiltinMeasureConstants.STREAMING, TagValue.create("false")); - } - - operationLevelWithStreaming.record(tagCtx.build()); - } - - public void recordOperationLatencies(long operationLatency) { - operationLevelWithStreaming.put(BuiltinMeasureConstants.OPERATION_LATENCIES, operationLatency); - } - - public void recordAttemptLatency(long attemptLatency) { - attemptLevelWithStreaming.put(BuiltinMeasureConstants.ATTEMPT_LATENCIES, attemptLatency); - } - - public void recordRetryCount(int attemptCount) { - operationLevelNoStreaming.put(BuiltinMeasureConstants.RETRY_COUNT, attemptCount); - } - - public void recordApplicationLatency( - long applicationLatency, String tableId, String zone, String cluster) { - MeasureMap measures = - statsRecorder - .newMeasureMap() - .put(BuiltinMeasureConstants.APPLICATION_LATENCIES, applicationLatency); - - TagContextBuilder tagCtx = newTagContextBuilder(tableId, zone, cluster); - if (operationType == OperationType.ServerStreaming - && spanName.getMethodName().equals("ReadRows")) { - tagCtx.putLocal(BuiltinMeasureConstants.STREAMING, TagValue.create("true")); - } else { - tagCtx.putLocal(BuiltinMeasureConstants.STREAMING, TagValue.create("false")); - } - - measures.record(tagCtx.build()); - } - - public void recordFirstResponseLatency(long firstResponseLatency) { - operationLevelNoStreaming.put( - BuiltinMeasureConstants.FIRST_RESPONSE_LATENCIES, firstResponseLatency); - } - - public void recordGfeLatencies(long serverLatency) { - attemptLevelWithStreaming.put(BuiltinMeasureConstants.SERVER_LATENCIES, serverLatency); - } - - public void recordGfeMissingHeaders(long connectivityErrors) { - attemptLevelNoStreaming.put( - BuiltinMeasureConstants.CONNECTIVITY_ERROR_COUNT, connectivityErrors); - } - - public void recordBatchRequestThrottled( - long throttledTimeMs, String tableId, String zone, String cluster) { - MeasureMap measures = - statsRecorder - .newMeasureMap() - .put(BuiltinMeasureConstants.THROTTLING_LATENCIES, throttledTimeMs); - measures.record(newTagContextBuilder(tableId, zone, cluster).build()); - } - - private TagContextBuilder newTagContextBuilder(String tableId, String zone, String cluster) { - TagContextBuilder tagContextBuilder = - tagger - .toBuilder(parentContext) - .putLocal(BuiltinMeasureConstants.CLIENT_NAME, TagValue.create("bigtable-java")) - .putLocal(BuiltinMeasureConstants.METHOD, TagValue.create(spanName.toString())) - .putLocal(BuiltinMeasureConstants.TABLE, TagValue.create(tableId)) - .putLocal(BuiltinMeasureConstants.ZONE, TagValue.create(zone)) - .putLocal(BuiltinMeasureConstants.CLUSTER, TagValue.create(cluster)); - for (Map.Entry entry : statsAttributes.entrySet()) { - tagContextBuilder.putLocal(TagKey.create(entry.getKey()), TagValue.create(entry.getValue())); - } - return tagContextBuilder; - } -} diff --git a/google-cloud-bigtable-stats/src/main/java/com/google/cloud/bigtable/stats/BuiltinViewConstants.java b/google-cloud-bigtable-stats/src/main/java/com/google/cloud/bigtable/stats/BuiltinViewConstants.java index c1ef763aeb..3d65de1820 100644 --- a/google-cloud-bigtable-stats/src/main/java/com/google/cloud/bigtable/stats/BuiltinViewConstants.java +++ b/google-cloud-bigtable-stats/src/main/java/com/google/cloud/bigtable/stats/BuiltinViewConstants.java @@ -35,14 +35,13 @@ import static com.google.cloud.bigtable.stats.BuiltinMeasureConstants.ZONE; import static io.opencensus.stats.Aggregation.Distribution; -import com.google.api.core.InternalApi; import com.google.common.collect.ImmutableList; import io.opencensus.stats.Aggregation; import io.opencensus.stats.BucketBoundaries; import io.opencensus.stats.View; -@InternalApi("For internal use only") -public class BuiltinViewConstants { +/** Create built-in metrics views under bigtable.googleapis.com/internal/client namespace */ +class BuiltinViewConstants { private static final Aggregation AGGREGATION_WITH_MILLIS_HISTOGRAM = Distribution.create( BucketBoundaries.create( @@ -67,8 +66,7 @@ public class BuiltinViewConstants { 100.0, 150.0, 200.0, 250.0, 300.0, 400.0, 500.0, 650.0, 800.0, 1000.0, 2000.0, 5000.0, 10000.0, 20000.0, 50000.0, 75000.0, 100000.0))); - // TODO: move project id, instance id to monitored resource - public static final View OPERATION_LATENCIES_VIEW = + static final View OPERATION_LATENCIES_VIEW = View.create( View.Name.create("bigtable.googleapis.com/internal/client/operation_latencies"), "Total time until final operation success or failure, including retries and backoff.", @@ -86,7 +84,7 @@ public class BuiltinViewConstants { ZONE, TABLE)); - public static final View ATTEMPT_LATENCIES_VIEW = + static final View ATTEMPT_LATENCIES_VIEW = View.create( View.Name.create("bigtable.googleapis.com/internal/client/attempt_latencies"), "Client observed latency per RPC attempt.", @@ -104,7 +102,7 @@ public class BuiltinViewConstants { ZONE, TABLE)); - public static final View RETRY_COUNT_VIEW = + static final View RETRY_COUNT_VIEW = View.create( View.Name.create("bigtable.googleapis.com/internal/client/retry_count"), "The number of additional RPCs sent after the initial attempt.", @@ -121,7 +119,7 @@ public class BuiltinViewConstants { ZONE, TABLE)); - public static final View FIRST_RESPONSE_LATENCIES_VIEW = + static final View FIRST_RESPONSE_LATENCIES_VIEW = View.create( View.Name.create("bigtable.googleapis.com/internal/client/first_response_latencies"), "Latency from operation start until the response headers were received. The publishing of the measurement will be delayed until the attempt response has been received.", @@ -138,7 +136,7 @@ public class BuiltinViewConstants { ZONE, TABLE)); - public static final View SERVER_LATENCIES_VIEW = + static final View SERVER_LATENCIES_VIEW = View.create( View.Name.create("bigtable.googleapis.com/internal/client/server_latencies"), "The latency measured from the moment that the RPC entered the Google data center until the RPC was completed.", @@ -156,7 +154,7 @@ public class BuiltinViewConstants { ZONE, TABLE)); - public static final View CONNECTIVITY_ERROR_COUNT_VIEW = + static final View CONNECTIVITY_ERROR_COUNT_VIEW = View.create( View.Name.create("bigtable.googleapis.com/internal/client/connectivity_error_count"), "Number of requests that failed to reach the Google datacenter. (Requests without google response headers).", @@ -173,7 +171,7 @@ public class BuiltinViewConstants { ZONE, TABLE)); - public static final View APPLICATION_LATENCIES_VIEW = + static final View APPLICATION_LATENCIES_VIEW = View.create( View.Name.create("bigtable.googleapis.com/internal/client/application_latencies"), "The latency of the client application consuming available response data.", @@ -190,7 +188,7 @@ public class BuiltinViewConstants { ZONE, TABLE)); - public static final View THROTTLING_LATENCIES_VIEW = + static final View THROTTLING_LATENCIES_VIEW = View.create( View.Name.create("bigtable.googleapis.com/internal/client/throttling_latencies"), "The artificial latency introduced by the client to limit the number of outstanding requests. The publishing of the measurement will be delayed until the attempt trailers have been received.", diff --git a/google-cloud-bigtable-stats/src/main/java/com/google/cloud/bigtable/stats/BuiltinViews.java b/google-cloud-bigtable-stats/src/main/java/com/google/cloud/bigtable/stats/BuiltinViews.java index b37fa25715..cc90faed74 100644 --- a/google-cloud-bigtable-stats/src/main/java/com/google/cloud/bigtable/stats/BuiltinViews.java +++ b/google-cloud-bigtable-stats/src/main/java/com/google/cloud/bigtable/stats/BuiltinViews.java @@ -20,6 +20,7 @@ import io.opencensus.stats.View; import io.opencensus.stats.ViewManager; +/** For registering built-in metric views */ @InternalApi("For internal use only") public class BuiltinViews { private static StatsWrapper statsWrapper; diff --git a/google-cloud-bigtable-stats/src/main/java/com/google/cloud/bigtable/stats/StatsRecorderWrapper.java b/google-cloud-bigtable-stats/src/main/java/com/google/cloud/bigtable/stats/StatsRecorderWrapper.java new file mode 100644 index 0000000000..5c47119608 --- /dev/null +++ b/google-cloud-bigtable-stats/src/main/java/com/google/cloud/bigtable/stats/StatsRecorderWrapper.java @@ -0,0 +1,121 @@ +/* + * Copyright 2022 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.cloud.bigtable.stats; + +import com.google.api.core.InternalApi; +import com.google.api.gax.tracing.ApiTracerFactory.OperationType; +import com.google.api.gax.tracing.SpanName; +import io.opencensus.stats.MeasureMap; +import io.opencensus.stats.StatsRecorder; +import io.opencensus.tags.TagContext; +import io.opencensus.tags.TagContextBuilder; +import io.opencensus.tags.TagKey; +import io.opencensus.tags.TagValue; +import io.opencensus.tags.Tagger; +import io.opencensus.tags.Tags; +import java.util.Map; + +/** A wrapper to record built-in metrics */ +@InternalApi("For internal use only") +public class StatsRecorderWrapper { + + private final OperationType operationType; + + private final Tagger tagger; + private final StatsRecorder statsRecorder; + private final TagContext parentContext; + private final SpanName spanName; + private final Map statsAttributes; + + private MeasureMap measureMap; + + public StatsRecorderWrapper( + OperationType operationType, + SpanName spanName, + Map statsAttributes, + StatsWrapper statsRecorderWrapper) { + this.operationType = operationType; + this.tagger = Tags.getTagger(); + this.statsRecorder = statsRecorderWrapper.getStatsRecorder(); + this.spanName = spanName; + this.parentContext = tagger.getCurrentTagContext(); + this.statsAttributes = statsAttributes; + + this.measureMap = statsRecorder.newMeasureMap(); + } + + public void record(String status, String tableId, String zone, String cluster) { + TagContextBuilder tagCtx = + newTagContextBuilder(tableId, zone, cluster) + .putLocal(BuiltinMeasureConstants.STATUS, TagValue.create(status)); + + if (operationType == OperationType.ServerStreaming + && spanName.getMethodName().equals("ReadRows")) { + tagCtx.putLocal(BuiltinMeasureConstants.STREAMING, TagValue.create("true")); + } else { + tagCtx.putLocal(BuiltinMeasureConstants.STREAMING, TagValue.create("false")); + } + + measureMap.record(tagCtx.build()); + } + + public void putOperationLatencies(long operationLatency) { + measureMap.put(BuiltinMeasureConstants.OPERATION_LATENCIES, operationLatency); + } + + public void putAttemptLatencies(long attemptLatency) { + measureMap.put(BuiltinMeasureConstants.ATTEMPT_LATENCIES, attemptLatency); + } + + public void putRetryCount(int attemptCount) { + measureMap.put(BuiltinMeasureConstants.RETRY_COUNT, attemptCount); + } + + public void putApplicationLatencies(long applicationLatency) { + measureMap.put(BuiltinMeasureConstants.APPLICATION_LATENCIES, applicationLatency); + } + + public void putFirstResponseLatencies(long firstResponseLatency) { + measureMap.put(BuiltinMeasureConstants.FIRST_RESPONSE_LATENCIES, firstResponseLatency); + } + + public void putGfeLatencies(long serverLatency) { + measureMap.put(BuiltinMeasureConstants.SERVER_LATENCIES, serverLatency); + } + + public void putGfeMissingHeaders(long connectivityErrors) { + measureMap.put(BuiltinMeasureConstants.CONNECTIVITY_ERROR_COUNT, connectivityErrors); + } + + public void putBatchRequestThrottled(long throttledTimeMs) { + measureMap.put(BuiltinMeasureConstants.THROTTLING_LATENCIES, throttledTimeMs); + } + + private TagContextBuilder newTagContextBuilder(String tableId, String zone, String cluster) { + TagContextBuilder tagContextBuilder = + tagger + .toBuilder(parentContext) + .putLocal(BuiltinMeasureConstants.CLIENT_NAME, TagValue.create("bigtable-java")) + .putLocal(BuiltinMeasureConstants.METHOD, TagValue.create(spanName.toString())) + .putLocal(BuiltinMeasureConstants.TABLE, TagValue.create(tableId)) + .putLocal(BuiltinMeasureConstants.ZONE, TagValue.create(zone)) + .putLocal(BuiltinMeasureConstants.CLUSTER, TagValue.create(cluster)); + for (Map.Entry entry : statsAttributes.entrySet()) { + tagContextBuilder.putLocal(TagKey.create(entry.getKey()), TagValue.create(entry.getValue())); + } + return tagContextBuilder; + } +} diff --git a/google-cloud-bigtable-stats/src/main/java/com/google/cloud/bigtable/stats/StatsWrapper.java b/google-cloud-bigtable-stats/src/main/java/com/google/cloud/bigtable/stats/StatsWrapper.java index 160e16d8eb..4c72f170fd 100644 --- a/google-cloud-bigtable-stats/src/main/java/com/google/cloud/bigtable/stats/StatsWrapper.java +++ b/google-cloud-bigtable-stats/src/main/java/com/google/cloud/bigtable/stats/StatsWrapper.java @@ -16,118 +16,43 @@ package com.google.cloud.bigtable.stats; import com.google.api.core.InternalApi; -import com.google.common.collect.ImmutableMap; +import com.google.common.annotations.VisibleForTesting; import io.opencensus.impl.stats.StatsComponentImpl; -import io.opencensus.stats.AggregationData; import io.opencensus.stats.Stats; import io.opencensus.stats.StatsComponent; import io.opencensus.stats.StatsRecorder; -import io.opencensus.stats.View; -import io.opencensus.stats.ViewData; import io.opencensus.stats.ViewManager; -import io.opencensus.tags.TagKey; -import io.opencensus.tags.TagValue; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Objects; -/** Wrapper class for accessing opencensus * */ +/** + * Wrapper class for accessing opencensus. We use a shaded version of opencensus to avoid polluting + * the global opencensus namespace. And this provides a facade that will not be relocated. + */ @InternalApi("For internal use only") public class StatsWrapper { - private final StatsComponent component; - private final boolean useLocalRecorder; + private final ViewManager viewManager; + private final StatsRecorder statsRecorder; - public StatsWrapper(boolean useLocalRecorder) { - this.component = new StatsComponentImpl(); - this.useLocalRecorder = useLocalRecorder; + private StatsWrapper(ViewManager viewManager, StatsRecorder statsRecorder) { + this.viewManager = viewManager; + this.statsRecorder = statsRecorder; } - StatsRecorder getStatsRecorder() { - if (!useLocalRecorder) { - return Stats.getStatsRecorder(); - } else { - return component.getStatsRecorder(); - } + public static StatsWrapper get() { + return new StatsWrapper(Stats.getViewManager(), Stats.getStatsRecorder()); } - ViewManager getViewManager() { - if (!useLocalRecorder) { - return Stats.getViewManager(); - } else { - return component.getViewManager(); - } + @VisibleForTesting + static StatsWrapper createPrivateInstance() { + StatsComponent component = new StatsComponentImpl(); + return new StatsWrapper(component.getViewManager(), component.getStatsRecorder()); } - long getAggregationValueAsLong( - View view, - ImmutableMap tags, - String projectId, - String instanceId, - String appProfileId) { - ViewData viewData = getViewManager().getView(view.getName()); - Map, AggregationData> aggregationMap = - Objects.requireNonNull(viewData).getAggregationMap(); - - List tagValues = new ArrayList<>(); - - for (TagKey column : view.getColumns()) { - if (BuiltinMeasureConstants.PROJECT_ID == column) { - tagValues.add(TagValue.create(projectId)); - } else if (BuiltinMeasureConstants.INSTANCE_ID == column) { - tagValues.add(TagValue.create(instanceId)); - } else if (BuiltinMeasureConstants.APP_PROFILE == column) { - tagValues.add(TagValue.create(appProfileId)); - } else { - tagValues.add(TagValue.create(tags.get(column))); - } - } - - AggregationData aggregationData = aggregationMap.get(tagValues); + ViewManager getViewManager() { + return viewManager; + } - return aggregationData.match( - new io.opencensus.common.Function() { - @Override - public Long apply(AggregationData.SumDataDouble arg) { - return (long) arg.getSum(); - } - }, - new io.opencensus.common.Function() { - @Override - public Long apply(AggregationData.SumDataLong arg) { - return arg.getSum(); - } - }, - new io.opencensus.common.Function() { - @Override - public Long apply(AggregationData.CountData arg) { - return arg.getCount(); - } - }, - new io.opencensus.common.Function() { - @Override - public Long apply(AggregationData.DistributionData arg) { - return (long) arg.getMean(); - } - }, - new io.opencensus.common.Function() { - @Override - public Long apply(AggregationData.LastValueDataDouble arg) { - return (long) arg.getLastValue(); - } - }, - new io.opencensus.common.Function() { - @Override - public Long apply(AggregationData.LastValueDataLong arg) { - return arg.getLastValue(); - } - }, - new io.opencensus.common.Function() { - @Override - public Long apply(AggregationData arg) { - throw new UnsupportedOperationException(); - } - }); + StatsRecorder getStatsRecorder() { + return statsRecorder; } } diff --git a/google-cloud-bigtable-stats/src/test/java/com/google/cloud/bigtable/stats/BuiltinMetricsRecorderTest.java b/google-cloud-bigtable-stats/src/test/java/com/google/cloud/bigtable/stats/StatsRecorderWrapperTest.java similarity index 72% rename from google-cloud-bigtable-stats/src/test/java/com/google/cloud/bigtable/stats/BuiltinMetricsRecorderTest.java rename to google-cloud-bigtable-stats/src/test/java/com/google/cloud/bigtable/stats/StatsRecorderWrapperTest.java index ce0cb0e011..55276f5a38 100644 --- a/google-cloud-bigtable-stats/src/test/java/com/google/cloud/bigtable/stats/BuiltinMetricsRecorderTest.java +++ b/google-cloud-bigtable-stats/src/test/java/com/google/cloud/bigtable/stats/StatsRecorderWrapperTest.java @@ -21,10 +21,19 @@ import com.google.api.gax.tracing.SpanName; import com.google.common.collect.ImmutableMap; import io.grpc.Status; +import io.opencensus.stats.AggregationData; +import io.opencensus.stats.View; +import io.opencensus.stats.ViewData; +import io.opencensus.tags.TagKey; +import io.opencensus.tags.TagValue; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Objects; import org.junit.Before; import org.junit.Test; -public class BuiltinMetricsRecorderTest { +public class StatsRecorderWrapperTest { private final String PROJECT_ID = "fake-project"; private final String INSTANCE_ID = "fake-instance"; @@ -38,15 +47,15 @@ public class BuiltinMetricsRecorderTest { @Before public void setup() { - this.wrapper = new StatsWrapper(true); + this.wrapper = StatsWrapper.createPrivateInstance(); BuiltinViews views = new BuiltinViews(wrapper); views.registerBigtableBuiltinViews(); } @Test public void testStreamingOperation() throws InterruptedException { - BuiltinMetricsRecorder tracer = - new BuiltinMetricsRecorder( + StatsRecorderWrapper tracer = + new StatsRecorderWrapper( ApiTracerFactory.OperationType.ServerStreaming, SpanName.of("Bigtable", "ReadRows"), ImmutableMap.of( @@ -64,25 +73,21 @@ public void testStreamingOperation() throws InterruptedException { long throttlingLatency = 50; long firstResponseLatency = 90; - tracer.recordOperationLatencies(operationLatency); - tracer.recordRetryCount(attemptCount); - tracer.recordAttemptLatency(attemptLatency); - tracer.recordApplicationLatency(applicationLatency, TABLE_ID, ZONE, CLUSTER); - tracer.recordGfeLatencies(serverLatency); - tracer.recordGfeMissingHeaders(connectivityErrorCount); - tracer.recordFirstResponseLatency(firstResponseLatency); - tracer.recordBatchRequestThrottled(throttlingLatency, TABLE_ID, ZONE, CLUSTER); + tracer.putOperationLatencies(operationLatency); + tracer.putRetryCount(attemptCount); + tracer.putAttemptLatencies(attemptLatency); + tracer.putApplicationLatencies(applicationLatency); + tracer.putGfeLatencies(serverLatency); + tracer.putGfeMissingHeaders(connectivityErrorCount); + tracer.putFirstResponseLatencies(firstResponseLatency); + tracer.putBatchRequestThrottled(throttlingLatency); - tracer.recordAttemptLevelWithoutStreaming( - Status.UNAVAILABLE.toString(), TABLE_ID, ZONE, CLUSTER); - tracer.recordAttemptLevelWithStreaming(Status.ABORTED.toString(), TABLE_ID, ZONE, CLUSTER); - tracer.recordOperationLevelWithoutStreaming("OK", TABLE_ID, ZONE, CLUSTER); - tracer.recordOperationLevelWithStreaming("OK", TABLE_ID, ZONE, CLUSTER); + tracer.record("OK", TABLE_ID, ZONE, CLUSTER); Thread.sleep(100); assertThat( - wrapper.getAggregationValueAsLong( + getAggregationValueAsLong( BuiltinViewConstants.OPERATION_LATENCIES_VIEW, ImmutableMap.of( BuiltinMeasureConstants.METHOD, "Bigtable.ReadRows", @@ -97,13 +102,13 @@ public void testStreamingOperation() throws InterruptedException { APP_PROFILE_ID)) .isEqualTo(operationLatency); assertThat( - wrapper.getAggregationValueAsLong( + getAggregationValueAsLong( BuiltinViewConstants.ATTEMPT_LATENCIES_VIEW, ImmutableMap.of( BuiltinMeasureConstants.METHOD, "Bigtable.ReadRows", BuiltinMeasureConstants.STATUS, - Status.ABORTED.toString(), + "OK", BuiltinMeasureConstants.TABLE, TABLE_ID, BuiltinMeasureConstants.ZONE, @@ -119,7 +124,7 @@ public void testStreamingOperation() throws InterruptedException { APP_PROFILE_ID)) .isEqualTo(attemptLatency); assertThat( - wrapper.getAggregationValueAsLong( + getAggregationValueAsLong( BuiltinViewConstants.RETRY_COUNT_VIEW, ImmutableMap.of( BuiltinMeasureConstants.METHOD, @@ -139,13 +144,13 @@ public void testStreamingOperation() throws InterruptedException { APP_PROFILE_ID)) .isEqualTo(attemptCount); assertThat( - wrapper.getAggregationValueAsLong( + getAggregationValueAsLong( BuiltinViewConstants.SERVER_LATENCIES_VIEW, ImmutableMap.of( BuiltinMeasureConstants.METHOD, "Bigtable.ReadRows", BuiltinMeasureConstants.STATUS, - Status.ABORTED.toString(), + "OK", BuiltinMeasureConstants.CLIENT_NAME, "bigtable-java", BuiltinMeasureConstants.STREAMING, @@ -161,7 +166,7 @@ public void testStreamingOperation() throws InterruptedException { APP_PROFILE_ID)) .isEqualTo(serverLatency); assertThat( - wrapper.getAggregationValueAsLong( + getAggregationValueAsLong( BuiltinViewConstants.APPLICATION_LATENCIES_VIEW, ImmutableMap.of( BuiltinMeasureConstants.METHOD, @@ -183,13 +188,13 @@ public void testStreamingOperation() throws InterruptedException { APP_PROFILE_ID)) .isEqualTo(applicationLatency); assertThat( - wrapper.getAggregationValueAsLong( + getAggregationValueAsLong( BuiltinViewConstants.CONNECTIVITY_ERROR_COUNT_VIEW, ImmutableMap.of( BuiltinMeasureConstants.METHOD, "Bigtable.ReadRows", BuiltinMeasureConstants.STATUS, - Status.UNAVAILABLE.toString(), + "OK", BuiltinMeasureConstants.CLIENT_NAME, "bigtable-java", BuiltinMeasureConstants.TABLE, @@ -203,7 +208,7 @@ public void testStreamingOperation() throws InterruptedException { APP_PROFILE_ID)) .isEqualTo(connectivityErrorCount); assertThat( - wrapper.getAggregationValueAsLong( + getAggregationValueAsLong( BuiltinViewConstants.THROTTLING_LATENCIES_VIEW, ImmutableMap.of( BuiltinMeasureConstants.METHOD, "Bigtable.ReadRows", @@ -216,7 +221,7 @@ public void testStreamingOperation() throws InterruptedException { APP_PROFILE_ID)) .isEqualTo(throttlingLatency); assertThat( - wrapper.getAggregationValueAsLong( + getAggregationValueAsLong( BuiltinViewConstants.FIRST_RESPONSE_LATENCIES_VIEW, ImmutableMap.of( BuiltinMeasureConstants.METHOD, @@ -239,8 +244,8 @@ public void testStreamingOperation() throws InterruptedException { @Test public void testUnaryOperations() throws InterruptedException { - BuiltinMetricsRecorder tracer = - new BuiltinMetricsRecorder( + StatsRecorderWrapper tracer = + new StatsRecorderWrapper( ApiTracerFactory.OperationType.ServerStreaming, SpanName.of("Bigtable", "MutateRow"), ImmutableMap.of( @@ -258,46 +263,49 @@ public void testUnaryOperations() throws InterruptedException { long throttlingLatency = 50; long firstResponseLatency = 90; - tracer.recordOperationLatencies(operationLatency); - tracer.recordRetryCount(attemptCount); - tracer.recordAttemptLatency(attemptLatency); - tracer.recordApplicationLatency(applicationLatency, TABLE_ID, ZONE, CLUSTER); - tracer.recordGfeLatencies(serverLatency); - tracer.recordGfeMissingHeaders(connectivityErrorCount); - tracer.recordFirstResponseLatency(firstResponseLatency); - tracer.recordBatchRequestThrottled(throttlingLatency, TABLE_ID, ZONE, CLUSTER); + tracer.putOperationLatencies(operationLatency); + tracer.putRetryCount(attemptCount); + tracer.putAttemptLatencies(attemptLatency); + tracer.putApplicationLatencies(applicationLatency); + tracer.putGfeLatencies(serverLatency); + tracer.putGfeMissingHeaders(connectivityErrorCount); + tracer.putFirstResponseLatencies(firstResponseLatency); + tracer.putBatchRequestThrottled(throttlingLatency); - tracer.recordOperationLevelWithStreaming("OK", TABLE_ID, ZONE, CLUSTER); - tracer.recordOperationLevelWithoutStreaming("OK", TABLE_ID, ZONE, CLUSTER); - tracer.recordAttemptLevelWithoutStreaming( - Status.UNAVAILABLE.toString(), TABLE_ID, ZONE, CLUSTER); - tracer.recordAttemptLevelWithStreaming(Status.ABORTED.toString(), TABLE_ID, ZONE, CLUSTER); + tracer.record(Status.UNAVAILABLE.toString(), TABLE_ID, ZONE, CLUSTER); Thread.sleep(100); assertThat( - wrapper.getAggregationValueAsLong( + getAggregationValueAsLong( BuiltinViewConstants.OPERATION_LATENCIES_VIEW, ImmutableMap.of( - BuiltinMeasureConstants.METHOD, "Bigtable.MutateRow", - BuiltinMeasureConstants.STATUS, "OK", - BuiltinMeasureConstants.TABLE, TABLE_ID, - BuiltinMeasureConstants.ZONE, ZONE, - BuiltinMeasureConstants.CLUSTER, CLUSTER, - BuiltinMeasureConstants.CLIENT_NAME, "bigtable-java", - BuiltinMeasureConstants.STREAMING, "false"), + BuiltinMeasureConstants.METHOD, + "Bigtable.MutateRow", + BuiltinMeasureConstants.STATUS, + Status.UNAVAILABLE.toString(), + BuiltinMeasureConstants.TABLE, + TABLE_ID, + BuiltinMeasureConstants.ZONE, + ZONE, + BuiltinMeasureConstants.CLUSTER, + CLUSTER, + BuiltinMeasureConstants.CLIENT_NAME, + "bigtable-java", + BuiltinMeasureConstants.STREAMING, + "false"), PROJECT_ID, INSTANCE_ID, APP_PROFILE_ID)) .isEqualTo(operationLatency); assertThat( - wrapper.getAggregationValueAsLong( + getAggregationValueAsLong( BuiltinViewConstants.ATTEMPT_LATENCIES_VIEW, ImmutableMap.of( BuiltinMeasureConstants.METHOD, "Bigtable.MutateRow", BuiltinMeasureConstants.STATUS, - Status.ABORTED.toString(), + Status.UNAVAILABLE.toString(), BuiltinMeasureConstants.TABLE, TABLE_ID, BuiltinMeasureConstants.ZONE, @@ -313,13 +321,13 @@ public void testUnaryOperations() throws InterruptedException { APP_PROFILE_ID)) .isEqualTo(attemptLatency); assertThat( - wrapper.getAggregationValueAsLong( + getAggregationValueAsLong( BuiltinViewConstants.RETRY_COUNT_VIEW, ImmutableMap.of( BuiltinMeasureConstants.METHOD, "Bigtable.MutateRow", BuiltinMeasureConstants.STATUS, - "OK", + Status.UNAVAILABLE.toString(), BuiltinMeasureConstants.TABLE, TABLE_ID, BuiltinMeasureConstants.ZONE, @@ -333,13 +341,13 @@ public void testUnaryOperations() throws InterruptedException { APP_PROFILE_ID)) .isEqualTo(attemptCount); assertThat( - wrapper.getAggregationValueAsLong( + getAggregationValueAsLong( BuiltinViewConstants.SERVER_LATENCIES_VIEW, ImmutableMap.of( BuiltinMeasureConstants.METHOD, "Bigtable.MutateRow", BuiltinMeasureConstants.STATUS, - Status.ABORTED.toString(), + Status.UNAVAILABLE.toString(), BuiltinMeasureConstants.CLIENT_NAME, "bigtable-java", BuiltinMeasureConstants.STREAMING, @@ -355,13 +363,13 @@ public void testUnaryOperations() throws InterruptedException { APP_PROFILE_ID)) .isEqualTo(serverLatency); assertThat( - wrapper.getAggregationValueAsLong( + getAggregationValueAsLong( BuiltinViewConstants.APPLICATION_LATENCIES_VIEW, ImmutableMap.of( BuiltinMeasureConstants.METHOD, "Bigtable.MutateRow", BuiltinMeasureConstants.STATUS, - "OK", + Status.UNAVAILABLE.toString(), BuiltinMeasureConstants.TABLE, TABLE_ID, BuiltinMeasureConstants.ZONE, @@ -377,7 +385,7 @@ public void testUnaryOperations() throws InterruptedException { APP_PROFILE_ID)) .isEqualTo(applicationLatency); assertThat( - wrapper.getAggregationValueAsLong( + getAggregationValueAsLong( BuiltinViewConstants.CONNECTIVITY_ERROR_COUNT_VIEW, ImmutableMap.of( BuiltinMeasureConstants.METHOD, @@ -397,7 +405,7 @@ public void testUnaryOperations() throws InterruptedException { APP_PROFILE_ID)) .isEqualTo(connectivityErrorCount); assertThat( - wrapper.getAggregationValueAsLong( + getAggregationValueAsLong( BuiltinViewConstants.THROTTLING_LATENCIES_VIEW, ImmutableMap.of( BuiltinMeasureConstants.METHOD, "Bigtable.MutateRow", @@ -410,7 +418,7 @@ public void testUnaryOperations() throws InterruptedException { APP_PROFILE_ID)) .isEqualTo(throttlingLatency); assertThat( - wrapper.getAggregationValueAsLong( + getAggregationValueAsLong( BuiltinViewConstants.FIRST_RESPONSE_LATENCIES_VIEW, ImmutableMap.of( BuiltinMeasureConstants.METHOD, @@ -422,7 +430,7 @@ public void testUnaryOperations() throws InterruptedException { BuiltinMeasureConstants.CLUSTER, CLUSTER, BuiltinMeasureConstants.STATUS, - "OK", + Status.UNAVAILABLE.toString(), BuiltinMeasureConstants.CLIENT_NAME, "bigtable-java"), PROJECT_ID, @@ -430,4 +438,75 @@ public void testUnaryOperations() throws InterruptedException { APP_PROFILE_ID)) .isEqualTo(firstResponseLatency); } + + long getAggregationValueAsLong( + View view, + ImmutableMap tags, + String projectId, + String instanceId, + String appProfileId) { + ViewData viewData = wrapper.getViewManager().getView(view.getName()); + Map, AggregationData> aggregationMap = + Objects.requireNonNull(viewData).getAggregationMap(); + + List tagValues = new ArrayList<>(); + + for (TagKey column : view.getColumns()) { + if (BuiltinMeasureConstants.PROJECT_ID == column) { + tagValues.add(TagValue.create(projectId)); + } else if (BuiltinMeasureConstants.INSTANCE_ID == column) { + tagValues.add(TagValue.create(instanceId)); + } else if (BuiltinMeasureConstants.APP_PROFILE == column) { + tagValues.add(TagValue.create(appProfileId)); + } else { + tagValues.add(TagValue.create(tags.get(column))); + } + } + + AggregationData aggregationData = aggregationMap.get(tagValues); + + return aggregationData.match( + new io.opencensus.common.Function() { + @Override + public Long apply(AggregationData.SumDataDouble arg) { + return (long) arg.getSum(); + } + }, + new io.opencensus.common.Function() { + @Override + public Long apply(AggregationData.SumDataLong arg) { + return arg.getSum(); + } + }, + new io.opencensus.common.Function() { + @Override + public Long apply(AggregationData.CountData arg) { + return arg.getCount(); + } + }, + new io.opencensus.common.Function() { + @Override + public Long apply(AggregationData.DistributionData arg) { + return (long) arg.getMean(); + } + }, + new io.opencensus.common.Function() { + @Override + public Long apply(AggregationData.LastValueDataDouble arg) { + return (long) arg.getLastValue(); + } + }, + new io.opencensus.common.Function() { + @Override + public Long apply(AggregationData.LastValueDataLong arg) { + return arg.getLastValue(); + } + }, + new io.opencensus.common.Function() { + @Override + public Long apply(AggregationData arg) { + throw new UnsupportedOperationException(); + } + }); + } }