Skip to content

Commit

Permalink
feat(otelgrpc): support adding custom metric attributes to gRPCContext
Browse files Browse the repository at this point in the history
  • Loading branch information
krak3n committed Oct 29, 2024
1 parent c1cdce7 commit 737f700
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,14 @@ import (
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/grpclog"
testpb "google.golang.org/grpc/interop/grpc_testing"
"google.golang.org/grpc/metadata"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/proto"

testpb "google.golang.org/grpc/interop/grpc_testing"
"go.opentelemetry.io/otel/attribute"

"go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"
)

var (
Expand Down Expand Up @@ -241,6 +244,7 @@ func NewTestServer() testpb.TestServiceServer {
}

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

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

func (s *testServer) UnaryCall(ctx context.Context, in *testpb.SimpleRequest) (*testpb.SimpleResponse, error) {
otelgrpc.AddMetricAttributes(ctx, attribute.String("custom_test_metric", "OK"))
st := in.GetResponseStatus()
if md, ok := metadata.FromIncomingContext(ctx); ok {
if initialMetadata, ok := md[initialMetadataKey]; ok {
Expand Down
11 changes: 11 additions & 0 deletions instrumentation/google.golang.org/grpc/otelgrpc/stats_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,17 @@ type gRPCContext struct {
record bool
}

// AddMetricAttributes adds extra metric attributes which be added to recorded metrics.
// This can be called from within your gRPC handlers.
func AddMetricAttributes(ctx context.Context, attributes ...attribute.KeyValue) {
gctx, ok := ctx.Value(gRPCContextKey{}).(*gRPCContext)
if !ok {
return
}

gctx.metricAttrs = append(gctx.metricAttrs, attributes...)
}

type serverHandler struct {
*config
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ import (
testpb "google.golang.org/grpc/interop/grpc_testing"
"google.golang.org/grpc/status"

"go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"
"go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc/filters"
"go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc/internal/test"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/sdk/instrumentation"
"go.opentelemetry.io/otel/sdk/metric"
Expand All @@ -27,15 +30,12 @@ import (
"go.opentelemetry.io/otel/sdk/trace"
"go.opentelemetry.io/otel/sdk/trace/tracetest"
semconv "go.opentelemetry.io/otel/semconv/v1.17.0"

"go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"
"go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc/filters"
"go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc/internal/test"
)

var (
testSpanAttr = attribute.String("test_span", "OK")
testMetricAttr = attribute.String("test_metric", "OK")
testSpanAttr = attribute.String("test_span", "OK")
testMetricAttr = attribute.String("test_metric", "OK")
customTestMetricAttr = attribute.String("custom_test_metric", "OK")
)

func TestStatsHandler(t *testing.T) {
Expand Down Expand Up @@ -1115,15 +1115,19 @@ func checkServerMetrics(t *testing.T, reader metric.Reader) {
semconv.RPCMethod("EmptyCall"),
semconv.RPCService("grpc.testing.TestService"),
semconv.RPCSystemGRPC,
testMetricAttr),
testMetricAttr,
customTestMetricAttr,
),
},
{
Attributes: attribute.NewSet(
semconv.RPCGRPCStatusCodeOk,
semconv.RPCMethod("UnaryCall"),
semconv.RPCService("grpc.testing.TestService"),
semconv.RPCSystemGRPC,
testMetricAttr),
testMetricAttr,
customTestMetricAttr,
),
},
{
Attributes: attribute.NewSet(
Expand Down Expand Up @@ -1164,7 +1168,8 @@ func checkServerMetrics(t *testing.T, reader metric.Reader) {
semconv.RPCMethod("EmptyCall"),
semconv.RPCService("grpc.testing.TestService"),
semconv.RPCSystemGRPC,
testMetricAttr),
testMetricAttr,
),
Bounds: []float64{0, 5, 10, 25, 50, 75, 100, 250, 500, 750, 1000, 2500, 5000, 7500, 10000},
BucketCounts: []uint64{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
Max: metricdata.NewExtrema(int64(0)),
Expand All @@ -1177,7 +1182,8 @@ func checkServerMetrics(t *testing.T, reader metric.Reader) {
semconv.RPCMethod("UnaryCall"),
semconv.RPCService("grpc.testing.TestService"),
semconv.RPCSystemGRPC,
testMetricAttr),
testMetricAttr,
),
Bounds: []float64{0, 5, 10, 25, 50, 75, 100, 250, 500, 750, 1000, 2500, 5000, 7500, 10000},
BucketCounts: []uint64{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
Max: metricdata.NewExtrema(int64(271840)),
Expand Down Expand Up @@ -1239,7 +1245,9 @@ func checkServerMetrics(t *testing.T, reader metric.Reader) {
semconv.RPCMethod("EmptyCall"),
semconv.RPCService("grpc.testing.TestService"),
semconv.RPCSystemGRPC,
testMetricAttr),
testMetricAttr,
customTestMetricAttr,
),
Bounds: []float64{0, 5, 10, 25, 50, 75, 100, 250, 500, 750, 1000, 2500, 5000, 7500, 10000},
BucketCounts: []uint64{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
Max: metricdata.NewExtrema(int64(0)),
Expand All @@ -1252,7 +1260,9 @@ func checkServerMetrics(t *testing.T, reader metric.Reader) {
semconv.RPCMethod("UnaryCall"),
semconv.RPCService("grpc.testing.TestService"),
semconv.RPCSystemGRPC,
testMetricAttr),
testMetricAttr,
customTestMetricAttr,
),
Bounds: []float64{0, 5, 10, 25, 50, 75, 100, 250, 500, 750, 1000, 2500, 5000, 7500, 10000},
BucketCounts: []uint64{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
Max: metricdata.NewExtrema(int64(314167)),
Expand Down Expand Up @@ -1315,7 +1325,9 @@ func checkServerMetrics(t *testing.T, reader metric.Reader) {
semconv.RPCMethod("EmptyCall"),
semconv.RPCService("grpc.testing.TestService"),
semconv.RPCSystemGRPC,
testMetricAttr),
testMetricAttr,
customTestMetricAttr,
),
Bounds: []float64{0, 5, 10, 25, 50, 75, 100, 250, 500, 750, 1000, 2500, 5000, 7500, 10000},
BucketCounts: []uint64{0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
Max: metricdata.NewExtrema(int64(1)),
Expand All @@ -1329,7 +1341,9 @@ func checkServerMetrics(t *testing.T, reader metric.Reader) {
semconv.RPCMethod("UnaryCall"),
semconv.RPCService("grpc.testing.TestService"),
semconv.RPCSystemGRPC,
testMetricAttr),
testMetricAttr,
customTestMetricAttr,
),
Bounds: []float64{0, 5, 10, 25, 50, 75, 100, 250, 500, 750, 1000, 2500, 5000, 7500, 10000},
BucketCounts: []uint64{0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
Max: metricdata.NewExtrema(int64(1)),
Expand Down Expand Up @@ -1395,7 +1409,9 @@ func checkServerMetrics(t *testing.T, reader metric.Reader) {
semconv.RPCMethod("EmptyCall"),
semconv.RPCService("grpc.testing.TestService"),
semconv.RPCSystemGRPC,
testMetricAttr),
testMetricAttr,
customTestMetricAttr,
),
Bounds: []float64{0, 5, 10, 25, 50, 75, 100, 250, 500, 750, 1000, 2500, 5000, 7500, 10000},
BucketCounts: []uint64{0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
Max: metricdata.NewExtrema(int64(1)),
Expand All @@ -1409,7 +1425,9 @@ func checkServerMetrics(t *testing.T, reader metric.Reader) {
semconv.RPCMethod("UnaryCall"),
semconv.RPCService("grpc.testing.TestService"),
semconv.RPCSystemGRPC,
testMetricAttr),
testMetricAttr,
customTestMetricAttr,
),
Bounds: []float64{0, 5, 10, 25, 50, 75, 100, 250, 500, 750, 1000, 2500, 5000, 7500, 10000},
BucketCounts: []uint64{0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
Max: metricdata.NewExtrema(int64(1)),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,15 @@ func TestStatsHandlerHandleRPCServerErrors(t *testing.T) {
serviceName := "TestGrpcService"
methodName := serviceName + "/" + name
fullMethodName := "/" + methodName

// call the server handler
ctx := serverHandler.TagRPC(context.Background(), &stats.RPCTagInfo{
FullMethodName: fullMethodName,
})

// add custom metric attribute
otelgrpc.AddMetricAttributes(ctx, customTestMetricAttr)

grpcErr := status.Error(check.grpcCode, check.grpcCode.String())
serverHandler.HandleRPC(ctx, &stats.End{
Error: grpcErr,
Expand Down Expand Up @@ -82,6 +86,7 @@ func assertStatsHandlerServerMetrics(t *testing.T, reader metric.Reader, service
otelgrpc.RPCSystemGRPC,
otelgrpc.GRPCStatusCodeKey.Int64(int64(code)),
testMetricAttr,
customTestMetricAttr,
),
},
},
Expand All @@ -101,6 +106,7 @@ func assertStatsHandlerServerMetrics(t *testing.T, reader metric.Reader, service
otelgrpc.RPCSystemGRPC,
otelgrpc.GRPCStatusCodeKey.Int64(int64(code)),
testMetricAttr,
customTestMetricAttr,
),
},
},
Expand All @@ -120,6 +126,7 @@ func assertStatsHandlerServerMetrics(t *testing.T, reader metric.Reader, service
otelgrpc.RPCSystemGRPC,
otelgrpc.GRPCStatusCodeKey.Int64(int64(code)),
testMetricAttr,
customTestMetricAttr,
),
},
},
Expand Down

0 comments on commit 737f700

Please sign in to comment.