Skip to content

Commit d61796f

Browse files
authored
otelgrpc: add server.address and server.port (#8723)
Signed-off-by: David Ashpole <dashpole@google.com>
1 parent 4aa9e0f commit d61796f

4 files changed

Lines changed: 42 additions & 22 deletions

File tree

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
1414
- Added support for `service` resource detector in `go.opentelemetry.io/contrib/otelconf`. (#8674)
1515
- Added support for `attribute_count_limit` and `attribute_value_length_limit` in tracer provider configuration in `go.opentelemetry.io/contrib/otelconf`. (#8687)
1616
- Added support for `attribute_count_limit` and `attribute_value_length_limit` in logger provider configuration in `go.opentelemetry.io/contrib/otelconf`. (#8686)
17+
- Added support for `server.address` and `server.port` attributes in `go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc`. (#8723)
1718

1819
### Changed
1920

@@ -22,6 +23,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
2223
### Fixed
2324

2425
- Limit the request body size at 1MB in `go.opentelemetry.io/contrib/zpages`. (#8656)
26+
- Fix server spans using the client's address and port for `server.address` and `server.port` attributes in `go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc`. (#8723)
2527

2628
### Removed
2729

instrumentation/google.golang.org/grpc/otelgrpc/grpc_stats_handler_test.go

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -106,11 +106,11 @@ func TestStatsHandler(t *testing.T) {
106106
})
107107

108108
t.Run("ClientMetrics", func(t *testing.T) {
109-
checkClientMetrics(t, clientMetricReader)
109+
checkClientMetrics(t, clientMetricReader, listener.Addr().String())
110110
})
111111

112112
t.Run("ServerSpans", func(t *testing.T) {
113-
checkServerSpans(t, serverSR)
113+
checkServerSpans(t, serverSR, listener.Addr().String())
114114
})
115115

116116
t.Run("ServerMetrics", func(t *testing.T) {
@@ -217,7 +217,12 @@ func checkClientSpans(t *testing.T, spans []trace.ReadOnlySpan, addr string) {
217217
}, pingPong.Attributes())
218218
}
219219

220-
func checkServerSpans(t *testing.T, sr *tracetest.SpanRecorder) {
220+
func checkServerSpans(t *testing.T, sr *tracetest.SpanRecorder, addr string) {
221+
host, p, err := net.SplitHostPort(addr)
222+
require.NoError(t, err)
223+
port, err := strconv.Atoi(p)
224+
require.NoError(t, err)
225+
221226
var spans []trace.ReadOnlySpan
222227
require.Eventually(t, func() bool {
223228
spans = sr.Ended()
@@ -245,25 +250,28 @@ func checkServerSpans(t *testing.T, sr *tracetest.SpanRecorder) {
245250
assert.False(t, s.EndTime().IsZero())
246251
assert.Equal(t, tc.name, s.Name())
247252
assert.Empty(t, s.Events())
248-
port, ok := findAttribute(s.Attributes(), semconv.ServerPortKey)
249-
assert.True(t, ok)
250253
assert.ElementsMatch(t, []attribute.KeyValue{
251254
semconv.RPCMethodKey.String(tc.name),
252255
semconv.RPCSystemNameGRPC,
253256
semconv.RPCResponseStatusCode(codes.OK.String()),
254-
semconv.ServerAddress("127.0.0.1"),
255-
port,
257+
semconv.ServerAddress(host),
258+
semconv.ServerPort(port),
256259
testSpanAttr,
257260
}, s.Attributes())
258261
}
259262
}
260263

261-
func checkClientMetrics(t *testing.T, reader metric.Reader) {
264+
func checkClientMetrics(t *testing.T, reader metric.Reader, addr string) {
262265
rm := metricdata.ResourceMetrics{}
263266
err := reader.Collect(t.Context(), &rm)
264267
assert.NoError(t, err)
265268
require.Len(t, rm.ScopeMetrics, 1)
266269
require.Len(t, rm.ScopeMetrics[0].Metrics, 1)
270+
271+
host, p, err := net.SplitHostPort(addr)
272+
require.NoError(t, err)
273+
port, err := strconv.Atoi(p)
274+
require.NoError(t, err)
267275
expectedScopeMetric := metricdata.ScopeMetrics{
268276
Scope: instrumentation.Scope{
269277
Name: "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc",
@@ -283,34 +291,44 @@ func checkClientMetrics(t *testing.T, reader metric.Reader) {
283291
semconv.RPCResponseStatusCode(codes.OK.String()),
284292
semconv.RPCMethod("grpc.testing.TestService/EmptyCall"),
285293
semconv.RPCSystemNameGRPC,
294+
semconv.ServerAddress(host),
295+
semconv.ServerPort(port),
286296
testMetricAttr),
287297
},
288298
{
289299
Attributes: attribute.NewSet(
290300
semconv.RPCResponseStatusCode(codes.OK.String()),
291301
semconv.RPCMethod("grpc.testing.TestService/UnaryCall"),
292302
semconv.RPCSystemNameGRPC,
303+
semconv.ServerAddress(host),
304+
semconv.ServerPort(port),
293305
testMetricAttr),
294306
},
295307
{
296308
Attributes: attribute.NewSet(
297309
semconv.RPCResponseStatusCode(codes.OK.String()),
298310
semconv.RPCMethod("grpc.testing.TestService/StreamingInputCall"),
299311
semconv.RPCSystemNameGRPC,
312+
semconv.ServerAddress(host),
313+
semconv.ServerPort(port),
300314
testMetricAttr),
301315
},
302316
{
303317
Attributes: attribute.NewSet(
304318
semconv.RPCResponseStatusCode(codes.OK.String()),
305319
semconv.RPCMethod("grpc.testing.TestService/StreamingOutputCall"),
306320
semconv.RPCSystemNameGRPC,
321+
semconv.ServerAddress(host),
322+
semconv.ServerPort(port),
307323
testMetricAttr),
308324
},
309325
{
310326
Attributes: attribute.NewSet(
311327
semconv.RPCResponseStatusCode(codes.OK.String()),
312328
semconv.RPCMethod("grpc.testing.TestService/FullDuplexCall"),
313329
semconv.RPCSystemNameGRPC,
330+
semconv.ServerAddress(host),
331+
semconv.ServerPort(port),
314332
testMetricAttr),
315333
},
316334
},

instrumentation/google.golang.org/grpc/otelgrpc/grpc_test.go

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import (
1010

1111
"github.com/stretchr/testify/assert"
1212
"github.com/stretchr/testify/require"
13-
"go.opentelemetry.io/otel/attribute"
1413
"go.opentelemetry.io/otel/sdk/instrumentation"
1514
semconv "go.opentelemetry.io/otel/semconv/v1.40.0"
1615
"google.golang.org/grpc"
@@ -69,12 +68,3 @@ func doCalls(ctx context.Context, client pb.TestServiceClient) {
6968
test.DoServerStreaming(ctx, client)
7069
test.DoPingPong(ctx, client)
7170
}
72-
73-
func findAttribute(kvs []attribute.KeyValue, key attribute.Key) (attribute.KeyValue, bool) {
74-
for _, kv := range kvs {
75-
if kv.Key == key {
76-
return kv, true
77-
}
78-
}
79-
return attribute.KeyValue{}, false
80-
}

instrumentation/google.golang.org/grpc/otelgrpc/stats_handler.go

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ import (
1616
"go.opentelemetry.io/otel/semconv/v1.40.0/rpcconv"
1717
"go.opentelemetry.io/otel/trace"
1818
grpc_codes "google.golang.org/grpc/codes"
19-
"google.golang.org/grpc/peer"
2019
"google.golang.org/grpc/stats"
2120
"google.golang.org/grpc/status"
2221

@@ -255,12 +254,23 @@ func (*config) handleRPC(
255254
switch rs := rs.(type) {
256255
case *stats.Begin:
257256
case *stats.InPayload:
257+
case *stats.InHeader:
258+
if !rs.Client && rs.LocalAddr != nil {
259+
if span.IsRecording() {
260+
span.SetAttributes(serverAddrAttrs(rs.LocalAddr.String())...)
261+
}
262+
// TODO: add server.address and server.port to metrics once the API supports opt-in attributes.
263+
}
258264
case *stats.OutPayload:
259265
case *stats.OutTrailer:
260266
case *stats.OutHeader:
261-
if span.IsRecording() {
262-
if p, ok := peer.FromContext(ctx); ok {
263-
span.SetAttributes(serverAddrAttrs(p.Addr.String())...)
267+
if rs.Client && rs.RemoteAddr != nil && (span.IsRecording() || gctx != nil) {
268+
attrs := serverAddrAttrs(rs.RemoteAddr.String())
269+
if span.IsRecording() {
270+
span.SetAttributes(attrs...)
271+
}
272+
if gctx != nil {
273+
gctx.metricAttrs = append(gctx.metricAttrs, attrs...)
264274
}
265275
}
266276
case *stats.End:

0 commit comments

Comments
 (0)