Skip to content

Commit bc82dcb

Browse files
authored
feat: Add more attributes to golden signals metrics. (#4135)
This PR adds more attributes to metrics by introducing a [getMetricsAttributes()](https://github.com/googleapis/sdk-platform-java/blob/c0622b53d3741be8fa273bd90b61d7dccf9c473a/gax-java/gax/src/main/java/com/google/api/gax/tracing/ApiTracerContext.java#L180) in ApiTracerContext. It does not only add all known attributes, but also adds three new attributes to ApiTracerContext: serviceName(), urlDomain() and urlTemplate(). These three attributes are always empty for now and will be populated in future PRs.
1 parent 69c3132 commit bc82dcb

14 files changed

+260
-62
lines changed

sdk-platform-java/gax-java/gax/src/main/java/com/google/api/gax/rpc/LibraryMetadata.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,9 @@ public abstract class LibraryMetadata {
6565
@Nullable
6666
public abstract String artifactName();
6767

68+
@Nullable
69+
public abstract String version();
70+
6871
public static LibraryMetadata empty() {
6972
return newBuilder().build();
7073
}
@@ -83,6 +86,8 @@ public abstract static class Builder {
8386

8487
public abstract Builder setArtifactName(@Nullable String artifactName);
8588

89+
public abstract Builder setVersion(@Nullable String version);
90+
8691
public abstract LibraryMetadata build();
8792
}
8893
}

sdk-platform-java/gax-java/gax/src/main/java/com/google/api/gax/tracing/ApiTracerContext.java

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,18 @@ String rpcSystemName() {
136136
@Nullable
137137
public abstract OperationType operationType();
138138

139+
/** The service name of a client (e.g. "bigtable", "spanner"). */
140+
@Nullable
141+
public abstract String serviceName();
142+
143+
/** The url domain of the request (e.g. "pubsub.googleapis.com"). */
144+
@Nullable
145+
public abstract String urlDomain();
146+
147+
/** The url template of the request (e.g. /v1/{name}:access). */
148+
@Nullable
149+
public abstract String urlTemplate();
150+
139151
/**
140152
* @return a map of attributes to be included in attempt-level spans
141153
*/
@@ -165,6 +177,34 @@ public Map<String, Object> getAttemptAttributes() {
165177
return attributes;
166178
}
167179

180+
Map<String, Object> getMetricsAttributes() {
181+
Map<String, Object> attributes = new HashMap<>();
182+
if (!Strings.isNullOrEmpty(serverAddress())) {
183+
attributes.put(ObservabilityAttributes.SERVER_ADDRESS_ATTRIBUTE, serverAddress());
184+
}
185+
if (serverPort() != null) {
186+
attributes.put(ObservabilityAttributes.SERVER_PORT_ATTRIBUTE, serverPort());
187+
}
188+
if (!Strings.isNullOrEmpty(serviceName())) {
189+
attributes.put(ObservabilityAttributes.GCP_CLIENT_SERVICE_ATTRIBUTE, serviceName());
190+
}
191+
if (!Strings.isNullOrEmpty(rpcSystemName())) {
192+
attributes.put(ObservabilityAttributes.RPC_SYSTEM_NAME_ATTRIBUTE, rpcSystemName());
193+
}
194+
if (!Strings.isNullOrEmpty(fullMethodName())) {
195+
attributes.put(ObservabilityAttributes.GRPC_RPC_METHOD_ATTRIBUTE, fullMethodName());
196+
}
197+
if (transport() == Transport.HTTP) {
198+
if (!Strings.isNullOrEmpty(urlDomain())) {
199+
attributes.put(ObservabilityAttributes.URL_DOMAIN_ATTRIBUTE, urlDomain());
200+
}
201+
if (!Strings.isNullOrEmpty(urlTemplate())) {
202+
attributes.put(ObservabilityAttributes.URL_TEMPLATE_ATTRIBUTE, urlTemplate());
203+
}
204+
}
205+
return attributes;
206+
}
207+
168208
/**
169209
* Merges this context with another context. The values in the other context take precedence.
170210
*
@@ -191,6 +231,15 @@ ApiTracerContext merge(ApiTracerContext other) {
191231
if (other.operationType() != null) {
192232
builder.setOperationType(other.operationType());
193233
}
234+
if (other.serviceName() != null) {
235+
builder.setServiceName(other.serviceName());
236+
}
237+
if (other.urlDomain() != null) {
238+
builder.setUrlDomain(other.urlDomain());
239+
}
240+
if (other.urlTemplate() != null) {
241+
builder.setUrlTemplate(other.urlTemplate());
242+
}
194243
return builder.build();
195244
}
196245

@@ -218,6 +267,12 @@ public abstract static class Builder {
218267

219268
public abstract Builder setServerPort(@Nullable Integer serverPort);
220269

270+
public abstract Builder setServiceName(@Nullable String serviceName);
271+
272+
public abstract Builder setUrlDomain(@Nullable String urlDomain);
273+
274+
public abstract Builder setUrlTemplate(@Nullable String urlTemplate);
275+
221276
public abstract ApiTracerContext build();
222277
}
223278
}

sdk-platform-java/gax-java/gax/src/main/java/com/google/api/gax/tracing/GoldenSignalsMetricsRecorder.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ class GoldenSignalsMetricsRecorder {
6565
.build();
6666
}
6767

68-
void recordOperationLatency(double operationLatency, Map<String, String> attributes) {
68+
void recordOperationLatency(double operationLatency, Map<String, Object> attributes) {
6969
clientRequestDurationRecorder.record(
7070
operationLatency, ObservabilityUtils.toOtelAttributes(attributes));
7171
}

sdk-platform-java/gax-java/gax/src/main/java/com/google/api/gax/tracing/GoldenSignalsMetricsTracer.java

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -48,26 +48,23 @@
4848
class GoldenSignalsMetricsTracer implements ApiTracer {
4949
private final Stopwatch clientRequestTimer;
5050
private final GoldenSignalsMetricsRecorder metricsRecorder;
51-
private final Map<String, String> attributes = new HashMap<>();
51+
private final Map<String, Object> attributes;
5252

53-
/**
54-
* Creates the following instruments for the following metrics:
55-
*
56-
* <ul>
57-
* <li>Client Request Duration: Histogram
58-
* </ul>
59-
*
60-
* @param metricsRecorder OpenTelemetry
61-
*/
62-
GoldenSignalsMetricsTracer(GoldenSignalsMetricsRecorder metricsRecorder) {
53+
GoldenSignalsMetricsTracer(
54+
GoldenSignalsMetricsRecorder metricsRecorder, ApiTracerContext apiTracerContext) {
6355
this.clientRequestTimer = Stopwatch.createStarted();
6456
this.metricsRecorder = metricsRecorder;
57+
this.attributes = apiTracerContext.getMetricsAttributes();
6558
}
6659

6760
@VisibleForTesting
68-
GoldenSignalsMetricsTracer(GoldenSignalsMetricsRecorder metricsRecorder, Ticker ticker) {
61+
GoldenSignalsMetricsTracer(
62+
GoldenSignalsMetricsRecorder metricsRecorder,
63+
ApiTracerContext apiTracerContext,
64+
Ticker ticker) {
6965
this.clientRequestTimer = Stopwatch.createStarted(ticker);
7066
this.metricsRecorder = metricsRecorder;
67+
this.attributes = new HashMap<>(apiTracerContext.getMetricsAttributes());
7168
}
7269

7370
/**

sdk-platform-java/gax-java/gax/src/main/java/com/google/api/gax/tracing/GoldenSignalsMetricsTracerFactory.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ public class GoldenSignalsMetricsTracerFactory implements ApiTracerFactory {
4848

4949
public GoldenSignalsMetricsTracerFactory(OpenTelemetry openTelemetry) {
5050
this.openTelemetry = openTelemetry;
51+
this.apiTracerContext = ApiTracerContext.empty();
5152
}
5253

5354
@Override
@@ -57,7 +58,7 @@ public ApiTracer newTracer(ApiTracer parent, SpanName spanName, OperationType op
5758
// regular requests.
5859
return new BaseApiTracer();
5960
}
60-
return new GoldenSignalsMetricsTracer(metricsRecorder);
61+
return new GoldenSignalsMetricsTracer(metricsRecorder, apiTracerContext);
6162
}
6263

6364
@Override

sdk-platform-java/gax-java/gax/src/main/java/com/google/api/gax/tracing/ObservabilityAttributes.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,4 +64,13 @@ public class ObservabilityAttributes {
6464
* gRPC status code (e.g., "OK", "INTERNAL").
6565
*/
6666
public static final String RPC_RESPONSE_STATUS_ATTRIBUTE = "rpc.response.status_code";
67+
68+
/** The service name of a client (e.g. "bigtable", "spanner"). */
69+
public static final String GCP_CLIENT_SERVICE_ATTRIBUTE = "gcp.client.service";
70+
71+
/** The url domain of the request (e.g. "pubsub.googleapis.com"). */
72+
public static final String URL_DOMAIN_ATTRIBUTE = "url.domain";
73+
74+
/** The url template of the request (e.g. /v1/{name}:access). */
75+
public static final String URL_TEMPLATE_ATTRIBUTE = "url.template";
6776
}

sdk-platform-java/gax-java/gax/src/main/java/com/google/api/gax/tracing/ObservabilityUtils.java

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@
3131

3232
import com.google.api.gax.rpc.ApiException;
3333
import com.google.api.gax.rpc.StatusCode;
34-
import com.google.common.base.Preconditions;
3534
import io.opentelemetry.api.common.Attributes;
3635
import io.opentelemetry.api.common.AttributesBuilder;
3736
import java.util.Map;
@@ -57,10 +56,19 @@ static String extractStatus(@Nullable Throwable error) {
5756
return statusString;
5857
}
5958

60-
static Attributes toOtelAttributes(Map<String, String> attributes) {
61-
Preconditions.checkNotNull(attributes, "Attributes map cannot be null");
59+
static Attributes toOtelAttributes(Map<String, Object> attributes) {
6260
AttributesBuilder attributesBuilder = Attributes.builder();
63-
attributes.forEach(attributesBuilder::put);
61+
if (attributes == null) {
62+
return attributesBuilder.build();
63+
}
64+
attributes.forEach(
65+
(k, v) -> {
66+
if (v instanceof String) {
67+
attributesBuilder.put(k, (String) v);
68+
} else if (v instanceof Integer) {
69+
attributesBuilder.put(k, (long) (Integer) v);
70+
}
71+
});
6472
return attributesBuilder.build();
6573
}
6674
}

sdk-platform-java/gax-java/gax/src/main/java/com/google/api/gax/tracing/OpenTelemetryMetricsRecorder.java

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,10 @@
3333
import com.google.api.core.BetaApi;
3434
import com.google.api.core.InternalApi;
3535
import com.google.api.gax.core.GaxProperties;
36+
import com.google.common.base.Preconditions;
3637
import io.opentelemetry.api.OpenTelemetry;
38+
import io.opentelemetry.api.common.Attributes;
39+
import io.opentelemetry.api.common.AttributesBuilder;
3740
import io.opentelemetry.api.metrics.DoubleHistogram;
3841
import io.opentelemetry.api.metrics.LongCounter;
3942
import io.opentelemetry.api.metrics.Meter;
@@ -112,7 +115,7 @@ public OpenTelemetryMetricsRecorder(OpenTelemetry openTelemetry, String serviceN
112115
*/
113116
@Override
114117
public void recordAttemptLatency(double attemptLatency, Map<String, String> attributes) {
115-
attemptLatencyRecorder.record(attemptLatency, ObservabilityUtils.toOtelAttributes(attributes));
118+
attemptLatencyRecorder.record(attemptLatency, toOtelAttributes(attributes));
116119
}
117120

118121
/**
@@ -125,7 +128,7 @@ public void recordAttemptLatency(double attemptLatency, Map<String, String> attr
125128
*/
126129
@Override
127130
public void recordAttemptCount(long count, Map<String, String> attributes) {
128-
attemptCountRecorder.add(count, ObservabilityUtils.toOtelAttributes(attributes));
131+
attemptCountRecorder.add(count, toOtelAttributes(attributes));
129132
}
130133

131134
/**
@@ -137,8 +140,7 @@ public void recordAttemptCount(long count, Map<String, String> attributes) {
137140
*/
138141
@Override
139142
public void recordOperationLatency(double operationLatency, Map<String, String> attributes) {
140-
operationLatencyRecorder.record(
141-
operationLatency, ObservabilityUtils.toOtelAttributes(attributes));
143+
operationLatencyRecorder.record(operationLatency, toOtelAttributes(attributes));
142144
}
143145

144146
/**
@@ -151,6 +153,13 @@ public void recordOperationLatency(double operationLatency, Map<String, String>
151153
*/
152154
@Override
153155
public void recordOperationCount(long count, Map<String, String> attributes) {
154-
operationCountRecorder.add(count, ObservabilityUtils.toOtelAttributes(attributes));
156+
operationCountRecorder.add(count, toOtelAttributes(attributes));
157+
}
158+
159+
static Attributes toOtelAttributes(Map<String, String> attributes) {
160+
Preconditions.checkNotNull(attributes, "Attributes map cannot be null");
161+
AttributesBuilder attributesBuilder = Attributes.builder();
162+
attributes.forEach(attributesBuilder::put);
163+
return attributesBuilder.build();
155164
}
156165
}

sdk-platform-java/gax-java/gax/src/main/java/com/google/api/gax/tracing/OpenTelemetryTraceManager.java

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -57,16 +57,7 @@ public Span createSpan(String name, Map<String, Object> attributes) {
5757
// Attempt spans are of the CLIENT kind
5858
spanBuilder.setSpanKind(SpanKind.CLIENT);
5959

60-
if (attributes != null) {
61-
attributes.forEach(
62-
(k, v) -> {
63-
if (v instanceof String) {
64-
spanBuilder.setAttribute(k, (String) v);
65-
} else if (v instanceof Integer) {
66-
spanBuilder.setAttribute(k, (long) (Integer) v);
67-
}
68-
});
69-
}
60+
spanBuilder.setAllAttributes(ObservabilityUtils.toOtelAttributes(attributes));
7061

7162
io.opentelemetry.api.trace.Span span = spanBuilder.startSpan();
7263

0 commit comments

Comments
 (0)