stats: deprecate trace and tags methods and remove all usages from internal code (#7837)

This commit is contained in:
Purnesh Dixit 2024-11-19 09:37:12 +05:30 committed by GitHub
parent ee3fb2982c
commit 36d5ca0fae
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 82 additions and 100 deletions

View File

@ -599,12 +599,6 @@ func (t *http2Client) createHeaderFields(ctx context.Context, callHdr *CallHdr)
for k, v := range callAuthData {
headerFields = append(headerFields, hpack.HeaderField{Name: k, Value: encodeMetadataHeader(k, v)})
}
if b := stats.OutgoingTags(ctx); b != nil {
headerFields = append(headerFields, hpack.HeaderField{Name: "grpc-tags-bin", Value: encodeBinHeader(b)})
}
if b := stats.OutgoingTrace(ctx); b != nil {
headerFields = append(headerFields, hpack.HeaderField{Name: "grpc-trace-bin", Value: encodeBinHeader(b)})
}
if md, added, ok := metadataFromOutgoingContextRaw(ctx); ok {
var k string

View File

@ -539,12 +539,6 @@ func (t *http2Server) operateHeaders(ctx context.Context, frame *http2.MetaHeade
// Attach the received metadata to the context.
if len(mdata) > 0 {
s.ctx = metadata.NewIncomingContext(s.ctx, mdata)
if statsTags := mdata["grpc-tags-bin"]; len(statsTags) > 0 {
s.ctx = stats.SetIncomingTags(s.ctx, []byte(statsTags[len(statsTags)-1]))
}
if statsTrace := mdata["grpc-trace-bin"]; len(statsTrace) > 0 {
s.ctx = stats.SetIncomingTrace(s.ctx, []byte(statsTrace[len(statsTrace)-1]))
}
}
t.mu.Lock()
if t.state != reachable {

View File

@ -29,6 +29,7 @@ import (
"google.golang.org/grpc/codes"
"google.golang.org/grpc/grpclog"
"google.golang.org/grpc/internal"
"google.golang.org/grpc/metadata"
"google.golang.org/grpc/stats"
"google.golang.org/grpc/status"
)
@ -86,7 +87,7 @@ func (csh *clientStatsHandler) statsTagRPC(ctx context.Context, info *stats.RPCT
// Populate gRPC Metadata with OpenCensus tag map if set by application.
if tm := tag.FromContext(ctx); tm != nil {
ctx = stats.SetTags(ctx, tag.Encode(tm))
ctx = metadata.AppendToOutgoingContext(ctx, "grpc-tags-bin", string(tag.Encode(tm)))
}
return ctx, mi
}
@ -94,18 +95,21 @@ func (csh *clientStatsHandler) statsTagRPC(ctx context.Context, info *stats.RPCT
// statsTagRPC creates a recording object to derive measurements from in the
// context, scoping the recordings to per RPC server side (scope of the
// context). It also deserializes the opencensus tags set in the context's gRPC
// Metadata, and adds a server method tag to the opencensus tags.
// Metadata, and adds a server method tag to the opencensus tags. If multiple
// tags exist, it adds the last one.
func (ssh *serverStatsHandler) statsTagRPC(ctx context.Context, info *stats.RPCTagInfo) (context.Context, *metricsInfo) {
mi := &metricsInfo{
startTime: time.Now(),
method: info.FullMethodName,
}
if tagsBin := stats.Tags(ctx); tagsBin != nil {
if tgValues := metadata.ValueFromIncomingContext(ctx, "grpc-tags-bin"); len(tgValues) > 0 {
tagsBin := []byte(tgValues[len(tgValues)-1])
if tags, err := tag.Decode(tagsBin); err == nil {
ctx = tag.NewContext(ctx, tags)
}
}
// We can ignore the error here because in the error case, the context
// passed in is returned. If the call errors, the server side application
// layer won't get this key server method information in the tag map, but

View File

@ -24,6 +24,7 @@ import (
"go.opencensus.io/trace"
"go.opencensus.io/trace/propagation"
"google.golang.org/grpc/metadata"
"google.golang.org/grpc/stats"
"google.golang.org/grpc/status"
)
@ -46,7 +47,7 @@ func (csh *clientStatsHandler) traceTagRPC(ctx context.Context, rti *stats.RPCTa
_, span := trace.StartSpan(ctx, mn, trace.WithSampler(csh.to.TS))
tcBin := propagation.Binary(span.SpanContext())
return stats.SetTrace(ctx, tcBin), &traceInfo{
return metadata.AppendToOutgoingContext(ctx, "grpc-trace-bin", string(tcBin)), &traceInfo{
span: span,
countSentMsg: 0, // msg events scoped to scope of context, per attempt client side
countRecvMsg: 0,
@ -55,12 +56,17 @@ func (csh *clientStatsHandler) traceTagRPC(ctx context.Context, rti *stats.RPCTa
// traceTagRPC populates context with new span data, with a parent based on the
// spanContext deserialized from context passed in (wire data in gRPC metadata)
// if present.
// if present. If multiple spanContexts exist, it takes the last one.
func (ssh *serverStatsHandler) traceTagRPC(ctx context.Context, rti *stats.RPCTagInfo) (context.Context, *traceInfo) {
mn := strings.ReplaceAll(removeLeadingSlash(rti.FullMethodName), "/", ".")
var tcBin []byte
if tcValues := metadata.ValueFromIncomingContext(ctx, "grpc-trace-bin"); len(tcValues) > 0 {
tcBin = []byte(tcValues[len(tcValues)-1])
}
var span *trace.Span
if sc, ok := propagation.FromBinary(stats.Trace(ctx)); ok {
if sc, ok := propagation.FromBinary(tcBin); ok {
// Returned context is ignored because will populate context with data
// that wraps the span instead.
_, span = trace.StartSpanWithRemoteParent(ctx, mn, sc, trace.WithSpanKind(trace.SpanKindServer), trace.WithSampler(ssh.to.TS))

View File

@ -260,84 +260,42 @@ func (s *ConnEnd) IsClient() bool { return s.Client }
func (s *ConnEnd) isConnStats() {}
type incomingTagsKey struct{}
type outgoingTagsKey struct{}
// SetTags attaches stats tagging data to the context, which will be sent in
// the outgoing RPC with the header grpc-tags-bin. Subsequent calls to
// SetTags will overwrite the values from earlier calls.
//
// NOTE: this is provided only for backward compatibility with existing clients
// and will likely be removed in an upcoming release. New uses should transmit
// this type of data using metadata with a different, non-reserved (i.e. does
// not begin with "grpc-") header name.
// Deprecated: set the `grpc-tags-bin` header in the metadata instead.
func SetTags(ctx context.Context, b []byte) context.Context {
return context.WithValue(ctx, outgoingTagsKey{}, b)
return metadata.AppendToOutgoingContext(ctx, "grpc-tags-bin", string(b))
}
// Tags returns the tags from the context for the inbound RPC.
//
// NOTE: this is provided only for backward compatibility with existing clients
// and will likely be removed in an upcoming release. New uses should transmit
// this type of data using metadata with a different, non-reserved (i.e. does
// not begin with "grpc-") header name.
// Deprecated: obtain the `grpc-tags-bin` header from metadata instead.
func Tags(ctx context.Context) []byte {
b, _ := ctx.Value(incomingTagsKey{}).([]byte)
return b
traceValues := metadata.ValueFromIncomingContext(ctx, "grpc-tags-bin")
if len(traceValues) == 0 {
return nil
}
return []byte(traceValues[len(traceValues)-1])
}
// SetIncomingTags attaches stats tagging data to the context, to be read by
// the application (not sent in outgoing RPCs).
//
// This is intended for gRPC-internal use ONLY.
func SetIncomingTags(ctx context.Context, b []byte) context.Context {
return context.WithValue(ctx, incomingTagsKey{}, b)
}
// OutgoingTags returns the tags from the context for the outbound RPC.
//
// This is intended for gRPC-internal use ONLY.
func OutgoingTags(ctx context.Context) []byte {
b, _ := ctx.Value(outgoingTagsKey{}).([]byte)
return b
}
type incomingTraceKey struct{}
type outgoingTraceKey struct{}
// SetTrace attaches stats tagging data to the context, which will be sent in
// the outgoing RPC with the header grpc-trace-bin. Subsequent calls to
// SetTrace will overwrite the values from earlier calls.
//
// NOTE: this is provided only for backward compatibility with existing clients
// and will likely be removed in an upcoming release. New uses should transmit
// this type of data using metadata with a different, non-reserved (i.e. does
// not begin with "grpc-") header name.
// Deprecated: set the `grpc-trace-bin` header in the metadata instead.
func SetTrace(ctx context.Context, b []byte) context.Context {
return context.WithValue(ctx, outgoingTraceKey{}, b)
return metadata.AppendToOutgoingContext(ctx, "grpc-trace-bin", string(b))
}
// Trace returns the trace from the context for the inbound RPC.
//
// NOTE: this is provided only for backward compatibility with existing clients
// and will likely be removed in an upcoming release. New uses should transmit
// this type of data using metadata with a different, non-reserved (i.e. does
// not begin with "grpc-") header name.
// Deprecated: obtain the `grpc-trace-bin` header from metadata instead.
func Trace(ctx context.Context) []byte {
b, _ := ctx.Value(incomingTraceKey{}).([]byte)
return b
}
// SetIncomingTrace attaches stats tagging data to the context, to be read by
// the application (not sent in outgoing RPCs). It is intended for
// gRPC-internal use.
func SetIncomingTrace(ctx context.Context, b []byte) context.Context {
return context.WithValue(ctx, incomingTraceKey{}, b)
}
// OutgoingTrace returns the trace from the context for the outbound RPC. It is
// intended for gRPC-internal use.
func OutgoingTrace(ctx context.Context) []byte {
b, _ := ctx.Value(outgoingTraceKey{}).([]byte)
return b
traceValues := metadata.ValueFromIncomingContext(ctx, "grpc-trace-bin")
if len(traceValues) == 0 {
return nil
}
return []byte(traceValues[len(traceValues)-1])
}

View File

@ -94,6 +94,27 @@ func payloadToID(p *testpb.Payload) int32 {
return int32(p.Body[0]) + int32(p.Body[1])<<8 + int32(p.Body[2])<<16 + int32(p.Body[3])<<24
}
func setIncomingStats(ctx context.Context, mdKey string, b []byte) context.Context {
md, ok := metadata.FromIncomingContext(ctx)
if !ok {
md = metadata.MD{}
}
md.Set(mdKey, string(b))
return metadata.NewIncomingContext(ctx, md)
}
func getOutgoingStats(ctx context.Context, mdKey string) []byte {
md, ok := metadata.FromOutgoingContext(ctx)
if !ok {
return nil
}
tagValues := md.Get(mdKey)
if len(tagValues) == 0 {
return nil
}
return []byte(tagValues[len(tagValues)-1])
}
type testServer struct {
testgrpc.UnimplementedTestServiceServer
}
@ -1312,19 +1333,19 @@ func (s) TestTags(t *testing.T) {
tCtx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
defer cancel()
ctx := stats.SetTags(tCtx, b)
if tg := stats.OutgoingTags(ctx); !reflect.DeepEqual(tg, b) {
t.Errorf("OutgoingTags(%v) = %v; want %v", ctx, tg, b)
if tg := getOutgoingStats(ctx, "grpc-tags-bin"); !reflect.DeepEqual(tg, b) {
t.Errorf("getOutgoingStats(%v, grpc-tags-bin) = %v; want %v", ctx, tg, b)
}
if tg := stats.Tags(ctx); tg != nil {
t.Errorf("Tags(%v) = %v; want nil", ctx, tg)
}
ctx = stats.SetIncomingTags(tCtx, b)
ctx = setIncomingStats(tCtx, "grpc-tags-bin", b)
if tg := stats.Tags(ctx); !reflect.DeepEqual(tg, b) {
t.Errorf("Tags(%v) = %v; want %v", ctx, tg, b)
}
if tg := stats.OutgoingTags(ctx); tg != nil {
t.Errorf("OutgoingTags(%v) = %v; want nil", ctx, tg)
if tg := getOutgoingStats(ctx, "grpc-tags-bin"); tg != nil {
t.Errorf("getOutgoingStats(%v, grpc-tags-bin) = %v; want nil", ctx, tg)
}
}
@ -1333,19 +1354,19 @@ func (s) TestTrace(t *testing.T) {
tCtx, cancel := context.WithTimeout(context.Background(), defaultTestTimeout)
defer cancel()
ctx := stats.SetTrace(tCtx, b)
if tr := stats.OutgoingTrace(ctx); !reflect.DeepEqual(tr, b) {
t.Errorf("OutgoingTrace(%v) = %v; want %v", ctx, tr, b)
if tr := getOutgoingStats(ctx, "grpc-trace-bin"); !reflect.DeepEqual(tr, b) {
t.Errorf("getOutgoingStats(%v, grpc-trace-bin) = %v; want %v", ctx, tr, b)
}
if tr := stats.Trace(ctx); tr != nil {
t.Errorf("Trace(%v) = %v; want nil", ctx, tr)
}
ctx = stats.SetIncomingTrace(tCtx, b)
ctx = setIncomingStats(tCtx, "grpc-trace-bin", b)
if tr := stats.Trace(ctx); !reflect.DeepEqual(tr, b) {
t.Errorf("Trace(%v) = %v; want %v", ctx, tr, b)
}
if tr := stats.OutgoingTrace(ctx); tr != nil {
t.Errorf("OutgoingTrace(%v) = %v; want nil", ctx, tr)
if tr := getOutgoingStats(ctx, "grpc-trace-bin"); tr != nil {
t.Errorf("getOutgoingStats(%v, grpc-trace-bin) = %v; want nil", ctx, tr)
}
}

View File

@ -41,6 +41,7 @@ import (
"testing"
"time"
"github.com/google/go-cmp/cmp"
"golang.org/x/net/http2"
"golang.org/x/net/http2/hpack"
"google.golang.org/grpc"
@ -4618,6 +4619,16 @@ func (s) TestStreamingProxyDoesNotForwardMetadata(t *testing.T) {
}
func (s) TestStatsTagsAndTrace(t *testing.T) {
const mdTraceKey = "grpc-trace-bin"
const mdTagsKey = "grpc-tags-bin"
setTrace := func(ctx context.Context, b []byte) context.Context {
return metadata.AppendToOutgoingContext(ctx, mdTraceKey, string(b))
}
setTags := func(ctx context.Context, b []byte) context.Context {
return metadata.AppendToOutgoingContext(ctx, mdTagsKey, string(b))
}
// Data added to context by client (typically in a stats handler).
tags := []byte{1, 5, 2, 4, 3}
trace := []byte{5, 2, 1, 3, 4}
@ -4627,17 +4638,11 @@ func (s) TestStatsTagsAndTrace(t *testing.T) {
endpoint := &stubserver.StubServer{
EmptyCallF: func(ctx context.Context, _ *testpb.Empty) (*testpb.Empty, error) {
md, _ := metadata.FromIncomingContext(ctx)
if tg := stats.Tags(ctx); !reflect.DeepEqual(tg, tags) {
return nil, status.Errorf(codes.Internal, "stats.Tags(%v)=%v; want %v", ctx, tg, tags)
if md[mdTagsKey] == nil || !cmp.Equal(md[mdTagsKey][len(md[mdTagsKey])-1], string(tags)) {
return nil, status.Errorf(codes.Internal, "md['grpc-tags-bin']=%v; want %v", md[mdTagsKey], tags)
}
if !reflect.DeepEqual(md["grpc-tags-bin"], []string{string(tags)}) {
return nil, status.Errorf(codes.Internal, "md['grpc-tags-bin']=%v; want %v", md["grpc-tags-bin"], tags)
}
if tr := stats.Trace(ctx); !reflect.DeepEqual(tr, trace) {
return nil, status.Errorf(codes.Internal, "stats.Trace(%v)=%v; want %v", ctx, tr, trace)
}
if !reflect.DeepEqual(md["grpc-trace-bin"], []string{string(trace)}) {
return nil, status.Errorf(codes.Internal, "md['grpc-trace-bin']=%v; want %v", md["grpc-trace-bin"], trace)
if md[mdTraceKey] == nil || !cmp.Equal(md[mdTraceKey][len(md[mdTraceKey])-1], string(trace)) {
return nil, status.Errorf(codes.Internal, "md['grpc-trace-bin']=%v; want %v", md[mdTraceKey], trace)
}
return &testpb.Empty{}, nil
},
@ -4655,10 +4660,10 @@ func (s) TestStatsTagsAndTrace(t *testing.T) {
want codes.Code
}{
{ctx: ctx, want: codes.Internal},
{ctx: stats.SetTags(ctx, tags), want: codes.Internal},
{ctx: stats.SetTrace(ctx, trace), want: codes.Internal},
{ctx: stats.SetTags(stats.SetTrace(ctx, tags), tags), want: codes.Internal},
{ctx: stats.SetTags(stats.SetTrace(ctx, trace), tags), want: codes.OK},
{ctx: setTags(ctx, tags), want: codes.Internal},
{ctx: setTrace(ctx, trace), want: codes.Internal},
{ctx: setTags(setTrace(ctx, tags), tags), want: codes.Internal},
{ctx: setTags(setTrace(ctx, trace), tags), want: codes.OK},
}
for _, tc := range testCases {