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 (#214)

* feat: Update opencensus metrics to include bigtable resource ids and 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

* fix deps

* typo

* remove unused param

* add clirr

* review feedback

* code formatting

* fix deps

Co-authored-by: Kristen O'Leary <kaoleary@google.com>
  • Loading branch information
igorbernstein2 and kolea2 committed May 18, 2020
1 parent 00f6d2d commit 7214ef6
Show file tree
Hide file tree
Showing 21 changed files with 1,236 additions and 1,021 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
5 changes: 5 additions & 0 deletions google-cloud-bigtable-deps-bom/pom.xml
Expand Up @@ -190,6 +190,11 @@
<artifactId>opencensus-api</artifactId>
<version>${opencensus.version}</version>
</dependency>
<dependency>
<groupId>io.opencensus</groupId>
<artifactId>opencensus-impl-core</artifactId>
<version>${opencensus.version}</version>
</dependency>
<dependency>
<groupId>io.opencensus</groupId>
<artifactId>opencensus-contrib-grpc-util</artifactId>
Expand Down
16 changes: 16 additions & 0 deletions google-cloud-bigtable/clirr-ignored-differences.xml
Expand Up @@ -7,4 +7,20 @@
<method>*snapshot*</method>
<to>*snapshot*</to>
</difference>
<difference>
<differenceType>8001</differenceType>
<className>com/google/cloud/bigtable/data/v2/stub/metrics/MeasuredMutateRowsCallable*</className>
</difference>
<difference>
<differenceType>8001</differenceType>
<className>com/google/cloud/bigtable/data/v2/stub/metrics/MeasuredReadRowsCallable*</className>
</difference>
<difference>
<differenceType>8001</differenceType>
<className>com/google/cloud/bigtable/data/v2/stub/metrics/MeasuredUnaryCallable*</className>
</difference>
<difference>
<differenceType>8001</differenceType>
<className>com/google/cloud/bigtable/gaxx/tracing/WrappedTracerFactory*</className>
</difference>
</differences>
15 changes: 9 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 @@ -385,8 +384,12 @@
<!--
grpc-grpclb is used at runtime using reflection
grpc-auth is not directly used transitively, but is pulled to align with other grpc parts
opencensus-impl-core is brought in transitively through opencensus-impl
-->
<usedDependencies>io.grpc:grpc-auth,io.grpc:grpc-grpclb,com.google.auto.value:auto-value</usedDependencies>
<ignoredUsedUndeclaredDependencies>
<ignoredUsedUndeclaredDependency>io.opencensus:opencensus-impl-core</ignoredUsedUndeclaredDependency>
</ignoredUsedUndeclaredDependencies>
</configuration>
</plugin>

Expand Down
Expand Up @@ -20,6 +20,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 @@ -32,6 +34,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 @@ -59,9 +62,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 @@ -73,10 +76,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 @@ -98,16 +104,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 @@ -125,15 +127,58 @@ public static EnhancedBigtableStub create(EnhancedBigtableStubSettings settings)
}

@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(
// Add 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 @@ -196,17 +241,9 @@ public <RowT> ServerStreamingCallable<Query, RowT> createReadRowsCallable(
new TracedServerStreamingCallable<>(
readRowsUserCallable,
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 @@ -393,19 +430,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 @@ -578,19 +605,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

0 comments on commit 7214ef6

Please sign in to comment.