Skip to content

Commit

Permalink
feat: Update opencensus metrics to include bigtable resource ids and …
Browse files Browse the repository at this point in the history
…rpc level metrics

This PR refactors opencensus metrics integration to use gax's ApiTracers.
Which allows this client to instrument individual attempts and tag everything
with bigtable resource ids
  • Loading branch information
igorbernstein2 committed Apr 2, 2020
1 parent 712d829 commit 7f5df26
Show file tree
Hide file tree
Showing 19 changed files with 1,215 additions and 1,025 deletions.
57 changes: 32 additions & 25 deletions README.md
Expand Up @@ -176,13 +176,13 @@ If you are using Maven, add this to your pom.xml file
<dependency>
<groupId>io.opencensus</groupId>
<artifactId>opencensus-impl</artifactId>
<version>0.24.0</version>
<version>0.26.0</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.opencensus</groupId>
<artifactId>opencensus-exporter-trace-stackdriver</artifactId>
<version>0.24.0</version>
<version>0.26.0</version>
<exclusions>
<exclusion>
<groupId>io.grpc</groupId>
Expand All @@ -197,13 +197,13 @@ If you are using Maven, add this to your pom.xml file
```
If you are using Gradle, add this to your dependencies
```Groovy
compile 'io.opencensus:opencensus-impl:0.24.0'
compile 'io.opencensus:opencensus-exporter-trace-stackdriver:0.24.0'
compile 'io.opencensus:opencensus-impl:0.26.0'
compile 'io.opencensus:opencensus-exporter-trace-stackdriver:0.26.0'
```
If you are using SBT, add this to your dependencies
```Scala
libraryDependencies += "io.opencensus" % "opencensus-impl" % "0.24.0"
libraryDependencies += "io.opencensus" % "opencensus-exporter-trace-stackdriver" % "0.24.0"
libraryDependencies += "io.opencensus" % "opencensus-impl" % "0.26.0"
libraryDependencies += "io.opencensus" % "opencensus-exporter-trace-stackdriver" % "0.26.0"
```

At the start of your application configure the exporter:
Expand Down Expand Up @@ -236,30 +236,37 @@ Tracing.getTraceConfig().updateActiveTraceParams(

Cloud Bigtable client supports [Opencensus Metrics](https://opencensus.io/stats/),
which gives insight into the client internals and aids in debugging production issues.
Metrics prefixed with `cloud.google.com/java/bigtable/` focus on operation level
metrics across all of the retry attempts that occurred during that operation. RPC
level metrics can be gleaned from gRPC's metrics, which are prefixed with
`grpc.io/client/`.
All Cloud Bigtable Metrics are prefixed with `cloud.google.com/java/bigtable/`. The
metrics will be tagged with:
* `bigtable_project_id`: the project that contains the target Bigtable instance.
Please note that this id could be different from project that the client is running
in and different from the project where the metrics are exported to.
* `bigtable_instance_id`: the instance id of the target Bigtable instance
* `bigtable_app_profile_id`: the app profile id that is being used to access the target
Bigtable instance

### Available operation level metric views:

* `cloud.google.com/java/bigtable/op_latency`: A distribution latency of
* `cloud.google.com/java/bigtable/op_latency`: A distribution of latency of
each client method call, across all of it's RPC attempts. Tagged by
method name and final response status.
operation name and final response status.

* `cloud.google.com/java/bigtable/completed_ops`: The total count of
method invocations. Tagged by method name. Can be compared to
`grpc.io/client/completed_rpcs` to visualize retry attempts.
method invocations. Tagged by operation name and final response status.

* `cloud.google.com/java/bigtable/read_rows_first_row_latency`: A
distribution of the latency of receiving the first row in a ReadRows
operation.

* `cloud.google.com/java/bigtable/rows_per_op`: A distribution of rows
read per ReadRows operation across all retry attempts.
* `cloud.google.com/java/bigtable/attempt_latency`: A distribution of latency of
each client RPC, tagged by operation name and the attempt status. Under normal
circumstances, this will be identical to op_latency. However, when the client
receives transient errors, op_latency will be the sum of all attempt_latencies
and the exponential delays

* `cloud.google.com/java/bigtable/mutations_per_batch`: A distribution
of mutations per BulkMutation.
* `cloud.google.com/java/bigtable/attempts_per_op`: A distribution of attempts that
each operation required, tagged by operation name and final operation status.
Under normal circumstances, this will be 1.


By default, the functionality is disabled. For example to enable metrics using
Expand All @@ -273,13 +280,13 @@ If you are using Maven, add this to your pom.xml file
<dependency>
<groupId>io.opencensus</groupId>
<artifactId>opencensus-impl</artifactId>
<version>0.24.0</version>
<version>0.26.0</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.opencensus</groupId>
<artifactId>opencensus-exporter-stats-stackdriver</artifactId>
<version>0.24.0</version>
<version>0.26.0</version>
<exclusions>
<exclusion>
<groupId>io.grpc</groupId>
Expand All @@ -294,13 +301,13 @@ If you are using Maven, add this to your pom.xml file
```
If you are using Gradle, add this to your dependencies
```Groovy
compile 'io.opencensus:opencensus-impl:0.24.0'
compile 'io.opencensus:opencensus-exporter-stats-stackdriver:0.24.0'
compile 'io.opencensus:opencensus-impl:0.26.0'
compile 'io.opencensus:opencensus-exporter-stats-stackdriver:0.26.0'
```
If you are using SBT, add this to your dependencies
```Scala
libraryDependencies += "io.opencensus" % "opencensus-impl" % "0.24.0"
libraryDependencies += "io.opencensus" % "opencensus-exporter-stats-stackdriver" % "0.24.0"
libraryDependencies += "io.opencensus" % "opencensus-impl" % "0.26.0"
libraryDependencies += "io.opencensus" % "opencensus-exporter-stats-stackdriver" % "0.26.0"
```

At the start of your application configure the exporter and enable the Bigtable stats views:
Expand Down Expand Up @@ -337,7 +344,7 @@ Add the following to your project's pom.xml.
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-bom</artifactId>
<version>1.27.0</version>
<version>1.28.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
Expand Down
11 changes: 5 additions & 6 deletions google-cloud-bigtable/pom.xml
Expand Up @@ -172,12 +172,6 @@
<groupId>org.threeten</groupId>
<artifactId>threetenbp</artifactId>
</dependency>
<!-- // TODO(igorbernstein): Enable grpc views once we upgrade to grpc-java 1.24.0 -->
<!-- <dependency>-->
<!-- <groupId>io.opencensus</groupId>-->
<!-- <artifactId>opencensus-contrib-grpc-metrics</artifactId>-->
<!-- <version>${opencensus.version}</version>-->
<!-- </dependency>-->

<!-- Test dependencies -->
<dependency>
Expand Down Expand Up @@ -218,6 +212,11 @@
<artifactId>grpc-testing</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.opencensus</groupId>
<artifactId>opencensus-impl</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
Expand Down
Expand Up @@ -19,6 +19,8 @@
import com.google.api.gax.batching.Batcher;
import com.google.api.gax.batching.BatcherImpl;
import com.google.api.gax.core.BackgroundResource;
import com.google.api.gax.core.GaxProperties;
import com.google.api.gax.grpc.GaxGrpcProperties;
import com.google.api.gax.grpc.GrpcCallSettings;
import com.google.api.gax.grpc.GrpcRawCallableFactory;
import com.google.api.gax.retrying.ExponentialRetryAlgorithm;
Expand All @@ -31,6 +33,7 @@
import com.google.api.gax.rpc.ServerStreamingCallSettings;
import com.google.api.gax.rpc.ServerStreamingCallable;
import com.google.api.gax.rpc.UnaryCallable;
import com.google.api.gax.tracing.OpencensusTracerFactory;
import com.google.api.gax.tracing.SpanName;
import com.google.api.gax.tracing.TracedServerStreamingCallable;
import com.google.api.gax.tracing.TracedUnaryCallable;
Expand Down Expand Up @@ -58,9 +61,9 @@
import com.google.cloud.bigtable.data.v2.models.RowAdapter;
import com.google.cloud.bigtable.data.v2.models.RowMutation;
import com.google.cloud.bigtable.data.v2.models.RowMutationEntry;
import com.google.cloud.bigtable.data.v2.stub.metrics.MeasuredMutateRowsCallable;
import com.google.cloud.bigtable.data.v2.stub.metrics.MeasuredReadRowsCallable;
import com.google.cloud.bigtable.data.v2.stub.metrics.MeasuredUnaryCallable;
import com.google.cloud.bigtable.data.v2.stub.metrics.CompositeTracerFactory;
import com.google.cloud.bigtable.data.v2.stub.metrics.MetricsTracerFactory;
import com.google.cloud.bigtable.data.v2.stub.metrics.RpcMeasureConstants;
import com.google.cloud.bigtable.data.v2.stub.mutaterows.BulkMutateRowsUserFacingCallable;
import com.google.cloud.bigtable.data.v2.stub.mutaterows.MutateRowsBatchingDescriptor;
import com.google.cloud.bigtable.data.v2.stub.mutaterows.MutateRowsRetryingCallable;
Expand All @@ -72,10 +75,13 @@
import com.google.cloud.bigtable.data.v2.stub.readrows.RowMergingCallable;
import com.google.cloud.bigtable.gaxx.retrying.ApiResultRetryAlgorithm;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.protobuf.ByteString;
import io.opencensus.stats.Stats;
import io.opencensus.stats.StatsRecorder;
import io.opencensus.tags.TagKey;
import io.opencensus.tags.TagValue;
import io.opencensus.tags.Tagger;
import io.opencensus.tags.Tags;
import java.io.IOException;
Expand All @@ -97,16 +103,12 @@
*/
@InternalApi
public class EnhancedBigtableStub implements AutoCloseable {
private static final String TRACING_OUTER_CLIENT_NAME = "Bigtable";
private static final String CLIENT_NAME = "Bigtable";

private final EnhancedBigtableStubSettings settings;
private final ClientContext clientContext;
private final RequestContext requestContext;

// TODO: This should probably move to ClientContext
private final Tagger tagger;
private final StatsRecorder statsRecorder;

private final ServerStreamingCallable<Query, Row> readRowsCallable;
private final UnaryCallable<Query, Row> readRowCallable;
private final UnaryCallable<String, List<KeyOffset>> sampleRowKeysCallable;
Expand All @@ -117,22 +119,64 @@ public class EnhancedBigtableStub implements AutoCloseable {

public static EnhancedBigtableStub create(EnhancedBigtableStubSettings settings)
throws IOException {
ClientContext clientContext = ClientContext.create(settings);

return new EnhancedBigtableStub(
settings, clientContext, Tags.getTagger(), Stats.getStatsRecorder());
settings, ClientContext.create(settings), Tags.getTagger(), Stats.getStatsRecorder());
}

@InternalApi("Visible for testing")
private EnhancedBigtableStub(
public EnhancedBigtableStub(
EnhancedBigtableStubSettings settings,
ClientContext clientContext,
Tagger tagger,
StatsRecorder statsRecorder) {
this.settings = settings;
this.clientContext = clientContext;
this.tagger = tagger;
this.statsRecorder = statsRecorder;

this.clientContext =
clientContext
.toBuilder()
.setTracerFactory(
new CompositeTracerFactory(
ImmutableList.of(
// Ad OpenCensus Tracing
new OpencensusTracerFactory(
ImmutableMap.<String, String>builder()
// Annotate traces with the same tags as metrics
.put(
RpcMeasureConstants.BIGTABLE_PROJECT_ID.getName(),
settings.getProjectId())
.put(
RpcMeasureConstants.BIGTABLE_INSTANCE_ID.getName(),
settings.getInstanceId())
.put(
RpcMeasureConstants.BIGTABLE_APP_PROFILE_ID.getName(),
settings.getAppProfileId())
// Also annotate traces with library versions
.put("gax", GaxGrpcProperties.getGaxGrpcVersion())
.put("grpc", GaxGrpcProperties.getGrpcVersion())
.put(
"gapic",
GaxProperties.getLibraryVersion(
EnhancedBigtableStubSettings.class))
.build()),
// Add OpenCensus Metrics
MetricsTracerFactory.create(
tagger,
statsRecorder,
ImmutableMap.<TagKey, TagValue>builder()
.put(
RpcMeasureConstants.BIGTABLE_PROJECT_ID,
TagValue.create(settings.getProjectId()))
.put(
RpcMeasureConstants.BIGTABLE_INSTANCE_ID,
TagValue.create(settings.getInstanceId()))
.put(
RpcMeasureConstants.BIGTABLE_APP_PROFILE_ID,
TagValue.create(settings.getAppProfileId()))
.build()),
// Add user configured tracer
clientContext.getTracerFactory())))
.build();
this.requestContext =
RequestContext.create(
settings.getProjectId(), settings.getInstanceId(), settings.getAppProfileId());
Expand Down Expand Up @@ -164,24 +208,16 @@ private EnhancedBigtableStub(
*/
public <RowT> ServerStreamingCallable<Query, RowT> createReadRowsCallable(
RowAdapter<RowT> rowAdapter) {
ServerStreamingCallable<Query, RowT> readRowsCallable =
final ServerStreamingCallable<Query, RowT> readRowsCallable =
createReadRowsBaseCallable(settings.readRowsSettings(), rowAdapter);

ServerStreamingCallable<Query, RowT> traced =
final ServerStreamingCallable<Query, RowT> traced =
new TracedServerStreamingCallable<>(
readRowsCallable,
clientContext.getTracerFactory(),
SpanName.of(TRACING_OUTER_CLIENT_NAME, "ReadRows"));

ServerStreamingCallable<Query, RowT> measured =
new MeasuredReadRowsCallable<>(
traced,
TRACING_OUTER_CLIENT_NAME + ".ReadRows",
tagger,
statsRecorder,
clientContext.getClock());
SpanName.of(CLIENT_NAME, "ReadRows"));

return measured.withDefaultCallContext(clientContext.getDefaultCallContext());
return traced.withDefaultCallContext(clientContext.getDefaultCallContext());
}

/**
Expand Down Expand Up @@ -364,19 +400,9 @@ private UnaryCallable<BulkMutation, Void> createBulkMutateRowsCallable() {

UnaryCallable<BulkMutation, Void> traced =
new TracedUnaryCallable<>(
userFacing,
clientContext.getTracerFactory(),
SpanName.of(TRACING_OUTER_CLIENT_NAME, "MutateRows"));

UnaryCallable<BulkMutation, Void> measured =
new MeasuredMutateRowsCallable(
traced,
TRACING_OUTER_CLIENT_NAME + ".MutateRows",
tagger,
statsRecorder,
clientContext.getClock());
userFacing, clientContext.getTracerFactory(), SpanName.of(CLIENT_NAME, "MutateRows"));

return measured.withDefaultCallContext(clientContext.getDefaultCallContext());
return traced.withDefaultCallContext(clientContext.getDefaultCallContext());
}

/**
Expand Down Expand Up @@ -544,19 +570,9 @@ private <RequestT, ResponseT> UnaryCallable<RequestT, ResponseT> createUserFacin

UnaryCallable<RequestT, ResponseT> traced =
new TracedUnaryCallable<>(
inner,
clientContext.getTracerFactory(),
SpanName.of(TRACING_OUTER_CLIENT_NAME, methodName));

UnaryCallable<RequestT, ResponseT> measured =
new MeasuredUnaryCallable<>(
traced,
TRACING_OUTER_CLIENT_NAME + "." + methodName,
tagger,
statsRecorder,
clientContext.getClock());
inner, clientContext.getTracerFactory(), SpanName.of(CLIENT_NAME, methodName));

return measured.withDefaultCallContext(clientContext.getDefaultCallContext());
return traced.withDefaultCallContext(clientContext.getDefaultCallContext());
}
// </editor-fold>

Expand Down
Expand Up @@ -20,17 +20,14 @@
import com.google.api.gax.batching.BatchingSettings;
import com.google.api.gax.batching.FlowControlSettings;
import com.google.api.gax.batching.FlowController.LimitExceededBehavior;
import com.google.api.gax.core.GaxProperties;
import com.google.api.gax.core.GoogleCredentialsProvider;
import com.google.api.gax.grpc.GaxGrpcProperties;
import com.google.api.gax.grpc.InstantiatingGrpcChannelProvider;
import com.google.api.gax.retrying.RetrySettings;
import com.google.api.gax.rpc.ServerStreamingCallSettings;
import com.google.api.gax.rpc.StatusCode.Code;
import com.google.api.gax.rpc.StubSettings;
import com.google.api.gax.rpc.TransportChannelProvider;
import com.google.api.gax.rpc.UnaryCallSettings;
import com.google.api.gax.tracing.OpencensusTracerFactory;
import com.google.cloud.bigtable.data.v2.internal.RefreshChannel;
import com.google.cloud.bigtable.data.v2.models.ConditionalRowMutation;
import com.google.cloud.bigtable.data.v2.models.KeyOffset;
Expand All @@ -42,7 +39,6 @@
import com.google.cloud.bigtable.data.v2.stub.readrows.ReadRowsBatchingDescriptor;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import java.util.List;
import java.util.Set;
Expand Down Expand Up @@ -520,13 +516,6 @@ private Builder() {
setStreamWatchdogCheckInterval(baseDefaults.getStreamWatchdogCheckInterval());
setStreamWatchdogProvider(baseDefaults.getStreamWatchdogProvider());

setTracerFactory(
new OpencensusTracerFactory(
ImmutableMap.of(
"gax", GaxGrpcProperties.getGaxGrpcVersion(),
"grpc", GaxGrpcProperties.getGrpcVersion(),
"gapic", GaxProperties.getLibraryVersion(EnhancedBigtableStubSettings.class))));

// Per-method settings using baseSettings for defaults.
readRowsSettings = ServerStreamingCallSettings.newBuilder();

Expand Down

0 comments on commit 7f5df26

Please sign in to comment.