Skip to content

Commit 8a7caf0

Browse files
authored
feat(v2): add TransportTelemetryData for dynamic transport attributes (#481)
1 parent 76f0284 commit 8a7caf0

2 files changed

Lines changed: 71 additions & 0 deletions

File tree

v2/telemetry.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,56 @@
3030
package gax
3131

3232
import (
33+
"context"
34+
3335
"go.opentelemetry.io/otel"
3436
"go.opentelemetry.io/otel/attribute"
3537
"go.opentelemetry.io/otel/metric"
3638
)
3739

40+
// TransportTelemetryData contains mutable telemetry information that the transport
41+
// layer (e.g. gRPC or HTTP) populates during an RPC. This allows gax.Invoke to
42+
// correctly emit metric data without directly importing those transport layers.
43+
// This is an EXPERIMENTAL struct and should not be used by external consumers.
44+
type TransportTelemetryData struct {
45+
serverAddress string
46+
serverPort int
47+
responseStatusCode int
48+
}
49+
50+
// SetServerAddress sets the server address.
51+
func (d *TransportTelemetryData) SetServerAddress(addr string) { d.serverAddress = addr }
52+
53+
// ServerAddress returns the server address.
54+
func (d *TransportTelemetryData) ServerAddress() string { return d.serverAddress }
55+
56+
// SetServerPort sets the server port.
57+
func (d *TransportTelemetryData) SetServerPort(port int) { d.serverPort = port }
58+
59+
// ServerPort returns the server port.
60+
func (d *TransportTelemetryData) ServerPort() int { return d.serverPort }
61+
62+
// SetResponseStatusCode sets the response status code.
63+
func (d *TransportTelemetryData) SetResponseStatusCode(code int) { d.responseStatusCode = code }
64+
65+
// ResponseStatusCode returns the response status code.
66+
func (d *TransportTelemetryData) ResponseStatusCode() int { return d.responseStatusCode }
67+
68+
// transportTelemetryKey is the private context key used to inject TransportTelemetryData
69+
type transportTelemetryKey struct{}
70+
71+
// InjectTransportTelemetry injects a mutable TransportTelemetryData pointer into the context.
72+
// Experimental: This function is subject to breaking changes.
73+
func InjectTransportTelemetry(ctx context.Context, data *TransportTelemetryData) context.Context {
74+
return context.WithValue(ctx, transportTelemetryKey{}, data)
75+
}
76+
77+
// ExtractTransportTelemetry retrieves a mutable TransportTelemetryData pointer from the context.
78+
func ExtractTransportTelemetry(ctx context.Context) *TransportTelemetryData {
79+
data, _ := ctx.Value(transportTelemetryKey{}).(*TransportTelemetryData)
80+
return data
81+
}
82+
3883
const (
3984
metricName = "gcp.client.request.duration"
4085
metricDescription = "Duration of the request to the Google Cloud API"

v2/telemetry_test.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,3 +234,29 @@ func TestNoSDKImport(t *testing.T) {
234234
t.Errorf("Production code imports the OpenTelemetry SDK (go.opentelemetry.io/otel/sdk). This is forbidden.")
235235
}
236236
}
237+
238+
func TestTransportTelemetry(t *testing.T) {
239+
ctx := context.Background()
240+
data := &TransportTelemetryData{}
241+
data.SetServerAddress("localhost")
242+
data.SetServerPort(8080)
243+
data.SetResponseStatusCode(200)
244+
245+
ctx = InjectTransportTelemetry(ctx, data)
246+
got := ExtractTransportTelemetry(ctx)
247+
if got == nil {
248+
t.Errorf("ExtractTransportTelemetry() = nil, want %v", data)
249+
}
250+
if got != data {
251+
t.Errorf("ExtractTransportTelemetry() = %v, want %v", got, data)
252+
}
253+
if got.ServerAddress() != "localhost" {
254+
t.Errorf("got.ServerAddress() = %q, want %q", got.ServerAddress(), "localhost")
255+
}
256+
if got.ServerPort() != 8080 {
257+
t.Errorf("got.ServerPort() = %d, want %d", got.ServerPort(), 8080)
258+
}
259+
if got.ResponseStatusCode() != 200 {
260+
t.Errorf("got.ResponseStatusCode() = %d, want %d", got.ResponseStatusCode(), 200)
261+
}
262+
}

0 commit comments

Comments
 (0)