Skip to content

Commit 9e08c8f

Browse files
committed
feat(o11y): introduce server.port attribute
1 parent d9b39ed commit 9e08c8f

12 files changed

Lines changed: 77 additions & 15 deletions

File tree

gax-java/gax/src/main/java/com/google/api/gax/rpc/ClientContext.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,7 @@ public static ClientContext create(StubSettings settings) throws IOException {
273273
ApiTracerContext apiTracerContext =
274274
ApiTracerContext.newBuilder()
275275
.setServerAddress(endpointContext.resolvedServerAddress())
276+
.setServerPort(endpointContext.resolvedServerPort())
276277
.build();
277278
ApiTracerFactory apiTracerFactory = settings.getTracerFactory().withContext(apiTracerContext);
278279

gax-java/gax/src/main/java/com/google/api/gax/rpc/EndpointContext.java

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,9 @@ public static EndpointContext getDefaultInstance() {
136136

137137
public abstract String resolvedServerAddress();
138138

139+
@Nullable
140+
public abstract Integer resolvedServerPort();
141+
139142
public abstract Builder toBuilder();
140143

141144
public static Builder newBuilder() {
@@ -233,6 +236,8 @@ public abstract static class Builder {
233236

234237
public abstract Builder setResolvedServerAddress(String serverAddress);
235238

239+
public abstract Builder setResolvedServerPort(Integer serverPort);
240+
236241
public abstract Builder setResolvedUniverseDomain(String resolvedUniverseDomain);
237242

238243
abstract Builder setUseS2A(boolean useS2A);
@@ -404,6 +409,27 @@ private String parseServerAddress(String endpoint) {
404409
}
405410
}
406411

412+
private Integer parseServerPort(String endpoint) {
413+
if (Strings.isNullOrEmpty(endpoint)) {
414+
return null;
415+
}
416+
String hostPort = endpoint;
417+
if (hostPort.contains("://")) {
418+
// Strip the scheme if present. HostAndPort doesn't support schemes.
419+
hostPort = hostPort.substring(hostPort.indexOf("://") + 3);
420+
}
421+
try {
422+
HostAndPort parsedHostPort = HostAndPort.fromString(hostPort);
423+
if (parsedHostPort.hasPort()) {
424+
return parsedHostPort.getPort();
425+
}
426+
return null;
427+
} catch (IllegalArgumentException e) {
428+
// Fallback for cases HostAndPort can't handle.
429+
return null;
430+
}
431+
}
432+
407433
// Default to port 443 for HTTPS. Using HTTP requires explicitly setting the endpoint
408434
private String buildEndpointTemplate(String serviceName, String resolvedUniverseDomain) {
409435
return serviceName + "." + resolvedUniverseDomain + ":443";
@@ -441,6 +467,7 @@ public EndpointContext build() throws IOException {
441467
String endpoint = determineEndpoint();
442468
setResolvedEndpoint(endpoint);
443469
setResolvedServerAddress(parseServerAddress(endpoint));
470+
setResolvedServerPort(parseServerPort(endpoint));
444471
setUseS2A(shouldUseS2A());
445472
return autoBuild();
446473
}

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

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,17 +49,23 @@ public abstract class ApiTracerContext {
4949
/**
5050
* @return a map of attributes to be included in attempt-level spans
5151
*/
52-
public Map<String, String> getAttemptAttributes() {
53-
Map<String, String> attributes = new HashMap<>();
52+
public Map<String, Object> getAttemptAttributes() {
53+
Map<String, Object> attributes = new HashMap<>();
5454
if (getServerAddress() != null) {
5555
attributes.put(ObservabilityAttributes.SERVER_ADDRESS_ATTRIBUTE, getServerAddress());
5656
}
57+
if (getServerPort() != null) {
58+
attributes.put(ObservabilityAttributes.SERVER_PORT_ATTRIBUTE, getServerPort());
59+
}
5760
return attributes;
5861
}
5962

6063
@Nullable
6164
public abstract String getServerAddress();
6265

66+
@Nullable
67+
public abstract Integer getServerPort();
68+
6369
public static Builder newBuilder() {
6470
return new AutoValue_ApiTracerContext.Builder();
6571
}
@@ -68,6 +74,8 @@ public static Builder newBuilder() {
6874
public abstract static class Builder {
6975
public abstract Builder setServerAddress(String serverAddress);
7076

77+
public abstract Builder setServerPort(Integer serverPort);
78+
7179
public abstract ApiTracerContext build();
7280
}
7381
}

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,7 @@
4343
public class ObservabilityAttributes {
4444
/** The address of the server being called (e.g., "pubsub.googleapis.com"). */
4545
public static final String SERVER_ADDRESS_ATTRIBUTE = "server.address";
46+
47+
/** The port of the server being called (e.g., 443). */
48+
public static final String SERVER_PORT_ATTRIBUTE = "server.port";
4649
}

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

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,14 +51,21 @@ public OpenTelemetryTraceManager(OpenTelemetry openTelemetry) {
5151
}
5252

5353
@Override
54-
public Span createSpan(String name, Map<String, String> attributes) {
54+
public Span createSpan(String name, Map<String, Object> attributes) {
5555
SpanBuilder spanBuilder = tracer.spanBuilder(name);
5656

5757
// Attempt spans are of the CLIENT kind
5858
spanBuilder.setSpanKind(SpanKind.CLIENT);
5959

6060
if (attributes != null) {
61-
attributes.forEach((k, v) -> spanBuilder.setAttribute(k, v));
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+
});
6269
}
6370

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

gax-java/gax/src/main/java/com/google/api/gax/tracing/SpanTracer.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ public class SpanTracer implements ApiTracer {
4848
public static final String DEFAULT_LANGUAGE = "Java";
4949

5050
private final TraceManager traceManager;
51-
private final Map<String, String> attemptAttributes;
51+
private final Map<String, Object> attemptAttributes;
5252
private final String attemptSpanName;
5353
private final ApiTracerContext apiTracerContext;
5454
private TraceManager.Span attemptHandle;
@@ -75,7 +75,7 @@ private void buildAttributes() {
7575

7676
@Override
7777
public void attemptStarted(Object request, int attemptNumber) {
78-
Map<String, String> attemptAttributes = new HashMap<>(this.attemptAttributes);
78+
Map<String, Object> attemptAttributes = new HashMap<>(this.attemptAttributes);
7979
// Start the specific attempt span with the operation span as parent
8080
this.attemptHandle = traceManager.createSpan(attemptSpanName, attemptAttributes);
8181
}

gax-java/gax/src/main/java/com/google/api/gax/tracing/TraceManager.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
@InternalApi
4343
public interface TraceManager {
4444
/** Starts a span and returns a handle to manage its lifecycle. */
45-
Span createSpan(String name, Map<String, String> attributes);
45+
Span createSpan(String name, Map<String, Object> attributes);
4646

4747
interface Span {
4848
void end();

gax-java/gax/src/test/java/com/google/api/gax/rpc/EndpointContextTest.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -603,6 +603,7 @@ void endpointContextBuild_resolvesPortAndServerAddress() throws IOException {
603603
.setTransportChannelProviderEndpoint(null)
604604
.build();
605605
Truth.assertThat(endpointContext.resolvedServerAddress()).isEqualTo("localhost");
606+
Truth.assertThat(endpointContext.resolvedServerPort()).isEqualTo(7469);
606607

607608
endpoint = "localhost:7469";
608609
endpointContext =
@@ -611,6 +612,7 @@ void endpointContextBuild_resolvesPortAndServerAddress() throws IOException {
611612
.setTransportChannelProviderEndpoint(null)
612613
.build();
613614
Truth.assertThat(endpointContext.resolvedServerAddress()).isEqualTo("localhost");
615+
Truth.assertThat(endpointContext.resolvedServerPort()).isEqualTo(7469);
614616

615617
endpoint = "test.googleapis.com:443";
616618
endpointContext =
@@ -619,6 +621,7 @@ void endpointContextBuild_resolvesPortAndServerAddress() throws IOException {
619621
.setTransportChannelProviderEndpoint(null)
620622
.build();
621623
Truth.assertThat(endpointContext.resolvedServerAddress()).isEqualTo("test.googleapis.com");
624+
Truth.assertThat(endpointContext.resolvedServerPort()).isEqualTo(443);
622625

623626
// IPv6 literal with port
624627
endpoint = "[2001:db8::1]:443";
@@ -628,6 +631,7 @@ void endpointContextBuild_resolvesPortAndServerAddress() throws IOException {
628631
.setTransportChannelProviderEndpoint(null)
629632
.build();
630633
Truth.assertThat(endpointContext.resolvedServerAddress()).isEqualTo("2001:db8::1");
634+
Truth.assertThat(endpointContext.resolvedServerPort()).isEqualTo(443);
631635

632636
// Bare IPv6 literal (no port)
633637
endpoint = "2001:db8::1";
@@ -637,5 +641,6 @@ void endpointContextBuild_resolvesPortAndServerAddress() throws IOException {
637641
.setTransportChannelProviderEndpoint(null)
638642
.build();
639643
Truth.assertThat(endpointContext.resolvedServerAddress()).isEqualTo("2001:db8::1");
644+
Truth.assertThat(endpointContext.resolvedServerPort()).isNull();
640645
}
641646
}

gax-java/gax/src/test/java/com/google/api/gax/tracing/OpenTelemetryTraceManagerTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ void testCreateSpan_attempt_isClient() {
9090
@Test
9191
void testCreateSpan_recordsSpan() {
9292
String spanName = "test-span";
93-
Map<String, String> attributes = ImmutableMap.of("key1", "value1");
93+
Map<String, Object> attributes = ImmutableMap.of("key1", "value1");
9494

9595
when(tracer.spanBuilder(spanName)).thenReturn(spanBuilder);
9696
when(spanBuilder.setSpanKind(SpanKind.CLIENT)).thenReturn(spanBuilder);

gax-java/gax/src/test/java/com/google/api/gax/tracing/SpanTracerFactoryTest.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -72,10 +72,10 @@ void testNewTracer_addsAttributes() {
7272

7373
tracer.attemptStarted(null, 1);
7474

75-
ArgumentCaptor<Map<String, String>> attributesCaptor = ArgumentCaptor.forClass(Map.class);
75+
ArgumentCaptor<Map<String, Object>> attributesCaptor = ArgumentCaptor.forClass(Map.class);
7676
verify(recorder, atLeastOnce()).createSpan(anyString(), attributesCaptor.capture());
7777

78-
Map<String, String> attemptAttributes = attributesCaptor.getValue();
78+
Map<String, Object> attemptAttributes = attributesCaptor.getValue();
7979
assertThat(attemptAttributes).containsEntry("server.address", "test-address");
8080
}
8181

@@ -97,10 +97,10 @@ void testWithContext_addsInferredAttributes() {
9797

9898
tracer.attemptStarted(null, 1);
9999

100-
ArgumentCaptor<Map<String, String>> attributesCaptor = ArgumentCaptor.forClass(Map.class);
100+
ArgumentCaptor<Map<String, Object>> attributesCaptor = ArgumentCaptor.forClass(Map.class);
101101
verify(recorder, atLeastOnce()).createSpan(anyString(), attributesCaptor.capture());
102102

103-
Map<String, String> attemptAttributes = attributesCaptor.getValue();
103+
Map<String, Object> attemptAttributes = attributesCaptor.getValue();
104104
assertThat(attemptAttributes)
105105
.containsEntry(ObservabilityAttributes.SERVER_ADDRESS_ATTRIBUTE, "example.com");
106106
}
@@ -122,10 +122,10 @@ void testWithContext_noEndpointContext_doesNotAddAttributes() {
122122

123123
tracer.attemptStarted(null, 1);
124124

125-
ArgumentCaptor<Map<String, String>> attributesCaptor = ArgumentCaptor.forClass(Map.class);
125+
ArgumentCaptor<Map<String, Object>> attributesCaptor = ArgumentCaptor.forClass(Map.class);
126126
verify(recorder, atLeastOnce()).createSpan(anyString(), attributesCaptor.capture());
127127

128-
Map<String, String> attemptAttributes = attributesCaptor.getValue();
128+
Map<String, Object> attemptAttributes = attributesCaptor.getValue();
129129
assertThat(attemptAttributes)
130130
.doesNotContainKey(ObservabilityAttributes.SERVER_ADDRESS_ATTRIBUTE);
131131
}

0 commit comments

Comments
 (0)