Skip to content

Commit 737f700

Browse files
committed
feat(otelgrpc): support adding custom metric attributes to gRPCContext
1 parent c1cdce7 commit 737f700

File tree

4 files changed

+58
-17
lines changed

4 files changed

+58
-17
lines changed

instrumentation/google.golang.org/grpc/otelgrpc/internal/test/test_utils.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,14 @@ import (
3636
"google.golang.org/grpc"
3737
"google.golang.org/grpc/codes"
3838
"google.golang.org/grpc/grpclog"
39+
testpb "google.golang.org/grpc/interop/grpc_testing"
3940
"google.golang.org/grpc/metadata"
4041
"google.golang.org/grpc/status"
4142
"google.golang.org/protobuf/proto"
4243

43-
testpb "google.golang.org/grpc/interop/grpc_testing"
44+
"go.opentelemetry.io/otel/attribute"
45+
46+
"go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"
4447
)
4548

4649
var (
@@ -241,6 +244,7 @@ func NewTestServer() testpb.TestServiceServer {
241244
}
242245

243246
func (s *testServer) EmptyCall(ctx context.Context, in *testpb.Empty) (*testpb.Empty, error) {
247+
otelgrpc.AddMetricAttributes(ctx, attribute.String("custom_test_metric", "OK"))
244248
return new(testpb.Empty), nil
245249
}
246250

@@ -261,6 +265,7 @@ func serverNewPayload(t testpb.PayloadType, size int32) (*testpb.Payload, error)
261265
}
262266

263267
func (s *testServer) UnaryCall(ctx context.Context, in *testpb.SimpleRequest) (*testpb.SimpleResponse, error) {
268+
otelgrpc.AddMetricAttributes(ctx, attribute.String("custom_test_metric", "OK"))
264269
st := in.GetResponseStatus()
265270
if md, ok := metadata.FromIncomingContext(ctx); ok {
266271
if initialMetadata, ok := md[initialMetadataKey]; ok {

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,17 @@ type gRPCContext struct {
3131
record bool
3232
}
3333

34+
// AddMetricAttributes adds extra metric attributes which be added to recorded metrics.
35+
// This can be called from within your gRPC handlers.
36+
func AddMetricAttributes(ctx context.Context, attributes ...attribute.KeyValue) {
37+
gctx, ok := ctx.Value(gRPCContextKey{}).(*gRPCContext)
38+
if !ok {
39+
return
40+
}
41+
42+
gctx.metricAttrs = append(gctx.metricAttrs, attributes...)
43+
}
44+
3445
type serverHandler struct {
3546
*config
3647
}

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

Lines changed: 34 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ import (
1919
testpb "google.golang.org/grpc/interop/grpc_testing"
2020
"google.golang.org/grpc/status"
2121

22+
"go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"
23+
"go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc/filters"
24+
"go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc/internal/test"
2225
"go.opentelemetry.io/otel/attribute"
2326
"go.opentelemetry.io/otel/sdk/instrumentation"
2427
"go.opentelemetry.io/otel/sdk/metric"
@@ -27,15 +30,12 @@ import (
2730
"go.opentelemetry.io/otel/sdk/trace"
2831
"go.opentelemetry.io/otel/sdk/trace/tracetest"
2932
semconv "go.opentelemetry.io/otel/semconv/v1.17.0"
30-
31-
"go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"
32-
"go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc/filters"
33-
"go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc/internal/test"
3433
)
3534

3635
var (
37-
testSpanAttr = attribute.String("test_span", "OK")
38-
testMetricAttr = attribute.String("test_metric", "OK")
36+
testSpanAttr = attribute.String("test_span", "OK")
37+
testMetricAttr = attribute.String("test_metric", "OK")
38+
customTestMetricAttr = attribute.String("custom_test_metric", "OK")
3939
)
4040

4141
func TestStatsHandler(t *testing.T) {
@@ -1115,15 +1115,19 @@ func checkServerMetrics(t *testing.T, reader metric.Reader) {
11151115
semconv.RPCMethod("EmptyCall"),
11161116
semconv.RPCService("grpc.testing.TestService"),
11171117
semconv.RPCSystemGRPC,
1118-
testMetricAttr),
1118+
testMetricAttr,
1119+
customTestMetricAttr,
1120+
),
11191121
},
11201122
{
11211123
Attributes: attribute.NewSet(
11221124
semconv.RPCGRPCStatusCodeOk,
11231125
semconv.RPCMethod("UnaryCall"),
11241126
semconv.RPCService("grpc.testing.TestService"),
11251127
semconv.RPCSystemGRPC,
1126-
testMetricAttr),
1128+
testMetricAttr,
1129+
customTestMetricAttr,
1130+
),
11271131
},
11281132
{
11291133
Attributes: attribute.NewSet(
@@ -1164,7 +1168,8 @@ func checkServerMetrics(t *testing.T, reader metric.Reader) {
11641168
semconv.RPCMethod("EmptyCall"),
11651169
semconv.RPCService("grpc.testing.TestService"),
11661170
semconv.RPCSystemGRPC,
1167-
testMetricAttr),
1171+
testMetricAttr,
1172+
),
11681173
Bounds: []float64{0, 5, 10, 25, 50, 75, 100, 250, 500, 750, 1000, 2500, 5000, 7500, 10000},
11691174
BucketCounts: []uint64{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
11701175
Max: metricdata.NewExtrema(int64(0)),
@@ -1177,7 +1182,8 @@ func checkServerMetrics(t *testing.T, reader metric.Reader) {
11771182
semconv.RPCMethod("UnaryCall"),
11781183
semconv.RPCService("grpc.testing.TestService"),
11791184
semconv.RPCSystemGRPC,
1180-
testMetricAttr),
1185+
testMetricAttr,
1186+
),
11811187
Bounds: []float64{0, 5, 10, 25, 50, 75, 100, 250, 500, 750, 1000, 2500, 5000, 7500, 10000},
11821188
BucketCounts: []uint64{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
11831189
Max: metricdata.NewExtrema(int64(271840)),
@@ -1239,7 +1245,9 @@ func checkServerMetrics(t *testing.T, reader metric.Reader) {
12391245
semconv.RPCMethod("EmptyCall"),
12401246
semconv.RPCService("grpc.testing.TestService"),
12411247
semconv.RPCSystemGRPC,
1242-
testMetricAttr),
1248+
testMetricAttr,
1249+
customTestMetricAttr,
1250+
),
12431251
Bounds: []float64{0, 5, 10, 25, 50, 75, 100, 250, 500, 750, 1000, 2500, 5000, 7500, 10000},
12441252
BucketCounts: []uint64{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
12451253
Max: metricdata.NewExtrema(int64(0)),
@@ -1252,7 +1260,9 @@ func checkServerMetrics(t *testing.T, reader metric.Reader) {
12521260
semconv.RPCMethod("UnaryCall"),
12531261
semconv.RPCService("grpc.testing.TestService"),
12541262
semconv.RPCSystemGRPC,
1255-
testMetricAttr),
1263+
testMetricAttr,
1264+
customTestMetricAttr,
1265+
),
12561266
Bounds: []float64{0, 5, 10, 25, 50, 75, 100, 250, 500, 750, 1000, 2500, 5000, 7500, 10000},
12571267
BucketCounts: []uint64{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
12581268
Max: metricdata.NewExtrema(int64(314167)),
@@ -1315,7 +1325,9 @@ func checkServerMetrics(t *testing.T, reader metric.Reader) {
13151325
semconv.RPCMethod("EmptyCall"),
13161326
semconv.RPCService("grpc.testing.TestService"),
13171327
semconv.RPCSystemGRPC,
1318-
testMetricAttr),
1328+
testMetricAttr,
1329+
customTestMetricAttr,
1330+
),
13191331
Bounds: []float64{0, 5, 10, 25, 50, 75, 100, 250, 500, 750, 1000, 2500, 5000, 7500, 10000},
13201332
BucketCounts: []uint64{0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
13211333
Max: metricdata.NewExtrema(int64(1)),
@@ -1329,7 +1341,9 @@ func checkServerMetrics(t *testing.T, reader metric.Reader) {
13291341
semconv.RPCMethod("UnaryCall"),
13301342
semconv.RPCService("grpc.testing.TestService"),
13311343
semconv.RPCSystemGRPC,
1332-
testMetricAttr),
1344+
testMetricAttr,
1345+
customTestMetricAttr,
1346+
),
13331347
Bounds: []float64{0, 5, 10, 25, 50, 75, 100, 250, 500, 750, 1000, 2500, 5000, 7500, 10000},
13341348
BucketCounts: []uint64{0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
13351349
Max: metricdata.NewExtrema(int64(1)),
@@ -1395,7 +1409,9 @@ func checkServerMetrics(t *testing.T, reader metric.Reader) {
13951409
semconv.RPCMethod("EmptyCall"),
13961410
semconv.RPCService("grpc.testing.TestService"),
13971411
semconv.RPCSystemGRPC,
1398-
testMetricAttr),
1412+
testMetricAttr,
1413+
customTestMetricAttr,
1414+
),
13991415
Bounds: []float64{0, 5, 10, 25, 50, 75, 100, 250, 500, 750, 1000, 2500, 5000, 7500, 10000},
14001416
BucketCounts: []uint64{0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
14011417
Max: metricdata.NewExtrema(int64(1)),
@@ -1409,7 +1425,9 @@ func checkServerMetrics(t *testing.T, reader metric.Reader) {
14091425
semconv.RPCMethod("UnaryCall"),
14101426
semconv.RPCService("grpc.testing.TestService"),
14111427
semconv.RPCSystemGRPC,
1412-
testMetricAttr),
1428+
testMetricAttr,
1429+
customTestMetricAttr,
1430+
),
14131431
Bounds: []float64{0, 5, 10, 25, 50, 75, 100, 250, 500, 750, 1000, 2500, 5000, 7500, 10000},
14141432
BucketCounts: []uint64{0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
14151433
Max: metricdata.NewExtrema(int64(1)),

instrumentation/google.golang.org/grpc/otelgrpc/test/stats_handler_test.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,15 @@ func TestStatsHandlerHandleRPCServerErrors(t *testing.T) {
4343
serviceName := "TestGrpcService"
4444
methodName := serviceName + "/" + name
4545
fullMethodName := "/" + methodName
46+
4647
// call the server handler
4748
ctx := serverHandler.TagRPC(context.Background(), &stats.RPCTagInfo{
4849
FullMethodName: fullMethodName,
4950
})
5051

52+
// add custom metric attribute
53+
otelgrpc.AddMetricAttributes(ctx, customTestMetricAttr)
54+
5155
grpcErr := status.Error(check.grpcCode, check.grpcCode.String())
5256
serverHandler.HandleRPC(ctx, &stats.End{
5357
Error: grpcErr,
@@ -82,6 +86,7 @@ func assertStatsHandlerServerMetrics(t *testing.T, reader metric.Reader, service
8286
otelgrpc.RPCSystemGRPC,
8387
otelgrpc.GRPCStatusCodeKey.Int64(int64(code)),
8488
testMetricAttr,
89+
customTestMetricAttr,
8590
),
8691
},
8792
},
@@ -101,6 +106,7 @@ func assertStatsHandlerServerMetrics(t *testing.T, reader metric.Reader, service
101106
otelgrpc.RPCSystemGRPC,
102107
otelgrpc.GRPCStatusCodeKey.Int64(int64(code)),
103108
testMetricAttr,
109+
customTestMetricAttr,
104110
),
105111
},
106112
},
@@ -120,6 +126,7 @@ func assertStatsHandlerServerMetrics(t *testing.T, reader metric.Reader, service
120126
otelgrpc.RPCSystemGRPC,
121127
otelgrpc.GRPCStatusCodeKey.Int64(int64(code)),
122128
testMetricAttr,
129+
customTestMetricAttr,
123130
),
124131
},
125132
},

0 commit comments

Comments
 (0)