Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Introducing OpentelemetryMetricsRecorder #2433

Closed
wants to merge 79 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
79 commits
Select commit Hold shift + click to select a range
fab2ce0
feat: OpentelemetryMetricsRecorder Implementation
ddixit14 Jan 31, 2024
1fc2e9a
chore: showcase test setup
ddixit14 Feb 1, 2024
b08e849
chore: setup otel collector
ddixit14 Feb 7, 2024
bfcfb87
chore: fix
ddixit14 Feb 7, 2024
254fb38
chore: lint error
ddixit14 Feb 7, 2024
db4f772
chore: lint error
ddixit14 Feb 7, 2024
1772d42
chore: ignore linter for now
ddixit14 Feb 7, 2024
93b744f
chore: test setup
ddixit14 Feb 7, 2024
fb7fd5d
otel-collector-setup
ddixit14 Feb 7, 2024
166fc61
chore: fix lint
ddixit14 Feb 7, 2024
3fcdd5d
chore: fix
ddixit14 Feb 7, 2024
d908c28
chore: otel install
ddixit14 Feb 7, 2024
0382056
chore: otel install
ddixit14 Feb 7, 2024
4a8cdc9
chore: otel-setup
ddixit14 Feb 7, 2024
27f308b
chore: run-otel-background
ddixit14 Feb 7, 2024
e877bcf
cleanup
ddixit14 Feb 9, 2024
cfde7f6
chore: run test on gha
ddixit14 Feb 9, 2024
c4f3547
chore: lint
ddixit14 Feb 9, 2024
1b80dfa
chore: fix lint
ddixit14 Feb 9, 2024
0f7b6dd
lint
ddixit14 Feb 9, 2024
3217611
chore: test if logs exist
ddixit14 Feb 9, 2024
36f7cd3
chore: let's see if 2 tests run ok
ddixit14 Feb 9, 2024
beb91f1
chore: let's see if 2 tests run ok
ddixit14 Feb 9, 2024
5a33a4f
chore: will this work?
ddixit14 Feb 9, 2024
ae99154
chore: run 3 tests together
ddixit14 Feb 9, 2024
52f5abe
adding all tests
ddixit14 Feb 12, 2024
fb3757f
fix lint
ddixit14 Feb 12, 2024
de437c1
chore: fix time
ddixit14 Feb 12, 2024
6024d4d
refactoring tests + adding verify logic for metrics
ddixit14 Feb 13, 2024
a9c003a
chore: work on comments
ddixit14 Feb 13, 2024
759d0da
Merge branch 'main' into otel-MR-ddixit
ddixit14 Feb 13, 2024
a0d6856
comments
ddixit14 Feb 13, 2024
03d3159
Merge branch 'otel-MR-ddixit' of github.com:googleapis/sdk-platform-j…
ddixit14 Feb 13, 2024
1e8a82a
chore: parallel run
ddixit14 Feb 13, 2024
a281fc2
remove all yamls
ddixit14 Feb 13, 2024
b3ba6b9
using in-memory reader
ddixit14 Feb 15, 2024
61128ff
Merge branch 'main' into otel-MR-ddixit
ddixit14 Feb 15, 2024
494d53e
feat: autopopulate fields in the request (#2353)
alicejli Jan 31, 2024
8f28fff
chore(main): release 2.34.0 (#2417)
release-please[bot] Feb 1, 2024
09c1c72
chore(main): release 2.34.1-SNAPSHOT (#2434)
release-please[bot] Feb 1, 2024
bc8e285
test: increase timeout testCancelOuterFutureAfterStart to 60s (#2437)
suztomo Feb 1, 2024
b4c9659
chore: change header year (#2438)
JoeWang1127 Feb 2, 2024
58d2cc3
test: fix flakes in HttpJsonDirectServerStreamingCallableTest (#2432)
meltsufin Feb 6, 2024
1a34a99
chore: Update showcase protos (#2445)
lqiu96 Feb 7, 2024
7716446
test: fix flaky HttpJsonDirectServerStreamingCallableTest.testOnRespo…
meltsufin Feb 7, 2024
aae5f09
feat: add `generate_repo.py` (#2431)
JoeWang1127 Feb 7, 2024
00be453
chore: add `setup.py` for `library_generation` (#2447)
diegomarquezp Feb 8, 2024
cac115e
chore: format python code (#2452)
JoeWang1127 Feb 8, 2024
cef5002
chore: update instructions on `generate_repo.py` (#2449)
JoeWang1127 Feb 8, 2024
edfa9ad
feat: move synthtool templates to `library_generation/owlbot` (#2443)
diegomarquezp Feb 8, 2024
6c0aae0
chore: update dev guide to get version of gapic-showcase to install. …
zhumin8 Feb 8, 2024
903c1f6
chore: refactor golden tests for autopopulation feature (#2446)
alicejli Feb 8, 2024
fc84ee9
chore: use template excludes in generation config (#2453)
JoeWang1127 Feb 9, 2024
dc4039a
fix: Apiary Host returns user set host if set (#2455)
lqiu96 Feb 9, 2024
2e50f2a
chore: remove beta api annotation from client header customization su…
diegomarquezp Feb 12, 2024
45a8e50
chore: parallel run
ddixit14 Feb 13, 2024
62d1670
remove all yamls
ddixit14 Feb 13, 2024
d5c99a1
using in-memory reader
ddixit14 Feb 15, 2024
8b0bd4e
deps: update grpc dependencies to v1.61.1 (#2463)
renovate-bot Feb 13, 2024
a3d3345
chore: [common-protos,common-protos] set packed = false on field_beha…
gcf-owl-bot[bot] Feb 13, 2024
47b6ed7
deps: update google auth library dependencies to v1.23.0 (#2466)
renovate-bot Feb 13, 2024
9ec415c
chore: [iam,iam] set packed = false on field_behavior extension (#2435)
gcf-owl-bot[bot] Feb 13, 2024
68666e7
deps: update google http client dependencies to v1.44.1 (#2467)
renovate-bot Feb 13, 2024
119fba8
chore: remove unused files from showcase. (#2464)
zhumin8 Feb 13, 2024
2ac2e4b
deps: update google api dependencies (#2469)
renovate-bot Feb 13, 2024
4920536
chore: move owlbot requirements to library_generation/reqs.in (#2471)
diegomarquezp Feb 13, 2024
e6cb020
chore: add opentelemery to shared dependencies (#2456)
JoeWang1127 Feb 13, 2024
c66bc55
deps: update dependency commons-codec:commons-codec to v1.16.1 (#2473)
renovate-bot Feb 13, 2024
93fefb0
deps: update google auth library dependencies to v1.23.0 (#2476)
renovate-bot Feb 13, 2024
5a60665
fix: Cancel the Timeout Task for HttpJson (#2360)
lqiu96 Feb 13, 2024
54b798b
deps: update googleapis/java-cloud-bom digest to ac9893c (#2472)
renovate-bot Feb 13, 2024
a9b73c3
chore(main): release 2.35.0 (#2448)
release-please[bot] Feb 13, 2024
cd9e69b
chore(main): release 2.35.1-SNAPSHOT (#2482)
release-please[bot] Feb 13, 2024
5dd96f1
chore: add library params (#2457)
JoeWang1127 Feb 14, 2024
402f32c
chore: fix workflow to create additional tags (#2487)
JoeWang1127 Feb 15, 2024
01c0dc2
chore: remove beta httpjson (#2358)
JoeWang1127 Feb 15, 2024
f206c89
Merge branch 'otel-MR-ddixit' of github.com:googleapis/sdk-platform-j…
ddixit14 Feb 15, 2024
643733a
chore: cleanup
ddixit14 Feb 15, 2024
f3df697
chore: cleanup
ddixit14 Feb 15, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions gax-java/gax/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,18 @@
<artifactId>graal-sdk</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-api</artifactId>
</dependency>
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-sdk</artifactId>
</dependency>
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-exporter-otlp</artifactId>
</dependency>
</dependencies>

<build>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import com.google.api.core.ApiFunction;
import com.google.api.gax.core.CredentialsProvider;
import com.google.api.gax.core.ExecutorProvider;
import com.google.api.gax.tracing.ApiTracerFactory;
import com.google.common.base.MoreObjects;
import java.io.IOException;
import java.util.concurrent.Executor;
Expand Down Expand Up @@ -284,6 +285,16 @@ public B setGdchApiAudience(@Nullable String gdchApiAudience) {
return self();
}

/**
* Sets the ApiTracerFactory for the client instance. To enable default metrics, users need to
* create an instance of metricsRecorder and pass it to the metricsTracerFactory, and set it
* here.
*/
public B setTracerFactory(@Nullable ApiTracerFactory tracerFactory) {
stubSettings.setTracerFactory(tracerFactory);
return self();
}

/**
* Gets the ExecutorProvider that was previously set on this Builder. This ExecutorProvider is
* to use for running asynchronous API call logic (such as retries and long-running operations),
Expand Down Expand Up @@ -351,6 +362,11 @@ public Duration getWatchdogCheckInterval() {
return stubSettings.getStreamWatchdogCheckInterval();
}

/** Gets the TracerFactory that was previously set in this Builder */
public ApiTracerFactory getTracerFactory() {
return stubSettings.getTracerFactory();
}

/** Gets the GDCH API audience that was previously set in this Builder */
@Nullable
public String getGdchApiAudience() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,14 @@
* This class computes generic metrics that can be observed in the lifecycle of an RPC operation.
* The responsibility of recording metrics should delegate to {@link MetricsRecorder}, hence this
* class should not have any knowledge about the observability framework used for metrics recording.
* method_name and language will be autopopulated attributes. Default value of language is 'Java'.
*/
@BetaApi
@InternalApi
public class MetricsTracer implements ApiTracer {

private static final String STATUS_ATTRIBUTE = "status";
private static final String LANGUAGE = "Java";

private Stopwatch attemptTimer;

Expand All @@ -64,6 +66,7 @@ public class MetricsTracer implements ApiTracer {

public MetricsTracer(MethodName methodName, MetricsRecorder metricsRecorder) {
this.attributes.put("method_name", methodName.toString());
this.attributes.put("language", LANGUAGE);
ddixit14 marked this conversation as resolved.
Show resolved Hide resolved
this.metricsRecorder = metricsRecorder;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
/*
* Copyright 2024 Google LLC
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google LLC nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

package com.google.api.gax.tracing;

import com.google.common.annotations.VisibleForTesting;
import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.api.common.AttributesBuilder;
import io.opentelemetry.api.metrics.DoubleHistogram;
import io.opentelemetry.api.metrics.LongCounter;
import io.opentelemetry.api.metrics.Meter;
import java.util.Map;

public class OpentelemetryMetricsRecorder implements MetricsRecorder {

private Meter meter;

private DoubleHistogram attemptLatencyRecorder;

private DoubleHistogram operationLatencyRecorder;

private LongCounter operationCountRecorder;

private LongCounter attemptCountRecorder;

public OpentelemetryMetricsRecorder(Meter meter) {
this.meter = meter;
this.attemptLatencyRecorder =
meter
.histogramBuilder("attempt_latency")
ddixit14 marked this conversation as resolved.
Show resolved Hide resolved
.setDescription("Duration of an individual attempt")
.setUnit("ms")
.build();
this.operationLatencyRecorder =
meter
.histogramBuilder("operation_latency")
.setDescription(
"Total time until final operation success or failure, including retries and backoff.")
.setUnit("ms")
.build();
this.operationCountRecorder =
meter
.counterBuilder("operation_count")
.setDescription("Count of Operations")
.setUnit("1")
.build();
this.attemptCountRecorder =
meter
.counterBuilder("attempt_count")
.setDescription("Count of Attempts")
.setUnit("1")
.build();
}

public void recordAttemptLatency(double attemptLatency, Map<String, String> attributes) {
attemptLatencyRecorder.record(attemptLatency, toOtelAttributes(attributes));
}

public void recordAttemptCount(long count, Map<String, String> attributes) {
attemptCountRecorder.add(count, toOtelAttributes(attributes));
}

public void recordOperationLatency(double operationLatency, Map<String, String> attributes) {
operationLatencyRecorder.record(operationLatency, toOtelAttributes(attributes));
}

public void recordOperationCount(long count, Map<String, String> attributes) {
operationCountRecorder.add(count, toOtelAttributes(attributes));
}

@VisibleForTesting
Attributes toOtelAttributes(Map<String, String> attributes) {

if (attributes == null) {
blakeli0 marked this conversation as resolved.
Show resolved Hide resolved
throw new IllegalArgumentException("Input attributes map cannot be null");
}

AttributesBuilder attributesBuilder = Attributes.builder();
attributes.forEach(attributesBuilder::put);
return attributesBuilder.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,8 @@ public void testOperationSucceeded_recordsAttributes() {
Map<String, String> attributes =
ImmutableMap.of(
"status", "OK",
"method_name", "fake_service.fake_method");
"method_name", "fake_service.fake_method",
"language", "Java");

verify(metricsRecorder).recordOperationCount(1, attributes);
verify(metricsRecorder).recordOperationLatency(anyDouble(), eq(attributes));
Expand All @@ -96,7 +97,8 @@ public void testOperationFailed_recordsAttributes() {
Map<String, String> attributes =
ImmutableMap.of(
"status", "INVALID_ARGUMENT",
"method_name", "fake_service.fake_method");
"method_name", "fake_service.fake_method",
"language", "Java");

verify(metricsRecorder).recordOperationCount(1, attributes);
verify(metricsRecorder).recordOperationLatency(anyDouble(), eq(attributes));
Expand All @@ -112,7 +114,8 @@ public void testOperationCancelled_recordsAttributes() {
Map<String, String> attributes =
ImmutableMap.of(
"status", "CANCELLED",
"method_name", "fake_service.fake_method");
"method_name", "fake_service.fake_method",
"language", "Java");

verify(metricsRecorder).recordOperationCount(1, attributes);
verify(metricsRecorder).recordOperationLatency(anyDouble(), eq(attributes));
Expand All @@ -132,7 +135,8 @@ public void testAttemptSucceeded_recordsAttributes() {
Map<String, String> attributes =
ImmutableMap.of(
"status", "OK",
"method_name", "fake_service.fake_method");
"method_name", "fake_service.fake_method",
"language", "Java");

verify(metricsRecorder).recordAttemptCount(1, attributes);
verify(metricsRecorder).recordAttemptLatency(anyDouble(), eq(attributes));
Expand All @@ -155,7 +159,8 @@ public void testAttemptFailed_recordsAttributes() {
Map<String, String> attributes =
ImmutableMap.of(
"status", "INVALID_ARGUMENT",
"method_name", "fake_service.fake_method");
"method_name", "fake_service.fake_method",
"language", "Java");

verify(metricsRecorder).recordAttemptCount(1, attributes);
verify(metricsRecorder).recordAttemptLatency(anyDouble(), eq(attributes));
Expand All @@ -174,7 +179,8 @@ public void testAttemptCancelled_recordsAttributes() {
Map<String, String> attributes =
ImmutableMap.of(
"status", "CANCELLED",
"method_name", "fake_service.fake_method");
"method_name", "fake_service.fake_method",
"language", "Java");

verify(metricsRecorder).recordAttemptCount(1, attributes);
verify(metricsRecorder).recordAttemptLatency(anyDouble(), eq(attributes));
Expand All @@ -196,7 +202,8 @@ public void testAttemptFailedRetriesExhausted_recordsAttributes() {
Map<String, String> attributes =
ImmutableMap.of(
"status", "DEADLINE_EXCEEDED",
"method_name", "fake_service.fake_method");
"method_name", "fake_service.fake_method",
"language", "Java");

verify(metricsRecorder).recordAttemptCount(1, attributes);
verify(metricsRecorder).recordAttemptLatency(anyDouble(), eq(attributes));
Expand All @@ -218,7 +225,8 @@ public void testAttemptPermanentFailure_recordsAttributes() {
Map<String, String> attributes =
ImmutableMap.of(
"status", "NOT_FOUND",
"method_name", "fake_service.fake_method");
"method_name", "fake_service.fake_method",
"language", "Java");

verify(metricsRecorder).recordAttemptCount(1, attributes);
verify(metricsRecorder).recordAttemptLatency(anyDouble(), eq(attributes));
Expand Down
Loading
Loading