snapshot of https://github.com/grpc/grpc-go.git (master, 2026-09-15; blobs > 131072B omitted)
Some checks failed
codecov / upload (push) Failing after 13m59s
CodeQL / Analyze (push) Failing after 1s
Testing / vet-proto (push) Failing after 1s
Testing / tests (arm, latest) (push) Waiting to run
Testing / extras (latest) (push) Failing after 1s
Testing / static checks (latest-1) (push) Failing after 1s
Testing / tests (-race, latest) (push) Failing after 1s
Testing / tests (i386, latest) (push) Failing after 1s
Testing / tests (latest) (push) Failing after 1s
Testing / tests (latest-1) (push) Failing after 1s
Lock Threads / lock (push) Failing after 1s
govulncheck / govulncheck (.) (push) Failing after 1s
govulncheck / govulncheck (./cmd/protoc-gen-go-grpc) (push) Failing after 1s
govulncheck / govulncheck (./gcp/observability) (push) Failing after 1s
govulncheck / govulncheck (./security/advancedtls) (push) Failing after 1s
govulncheck / govulncheck (./stats/opencensus) (push) Failing after 1s
Stale bot / stale (push) Failing after 1s
Some checks failed
codecov / upload (push) Failing after 13m59s
CodeQL / Analyze (push) Failing after 1s
Testing / vet-proto (push) Failing after 1s
Testing / tests (arm, latest) (push) Waiting to run
Testing / extras (latest) (push) Failing after 1s
Testing / static checks (latest-1) (push) Failing after 1s
Testing / tests (-race, latest) (push) Failing after 1s
Testing / tests (i386, latest) (push) Failing after 1s
Testing / tests (latest) (push) Failing after 1s
Testing / tests (latest-1) (push) Failing after 1s
Lock Threads / lock (push) Failing after 1s
govulncheck / govulncheck (.) (push) Failing after 1s
govulncheck / govulncheck (./cmd/protoc-gen-go-grpc) (push) Failing after 1s
govulncheck / govulncheck (./gcp/observability) (push) Failing after 1s
govulncheck / govulncheck (./security/advancedtls) (push) Failing after 1s
govulncheck / govulncheck (./stats/opencensus) (push) Failing after 1s
Stale bot / stale (push) Failing after 1s
This commit is contained in:
130
stats/opencensus/trace.go
Normal file
130
stats/opencensus/trace.go
Normal file
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* Copyright 2022 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package opencensus
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
|
||||
"go.opencensus.io/trace"
|
||||
"go.opencensus.io/trace/propagation"
|
||||
|
||||
"google.golang.org/grpc/metadata"
|
||||
"google.golang.org/grpc/stats"
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
// traceInfo is data used for recording traces.
|
||||
type traceInfo struct {
|
||||
span *trace.Span
|
||||
countSentMsg uint32
|
||||
countRecvMsg uint32
|
||||
}
|
||||
|
||||
// traceTagRPC populates context with a new span, and serializes information
|
||||
// about this span into gRPC Metadata.
|
||||
func (csh *clientStatsHandler) traceTagRPC(ctx context.Context, rti *stats.RPCTagInfo) (context.Context, *traceInfo) {
|
||||
// TODO: get consensus on whether this method name of "s.m" is correct.
|
||||
mn := "Attempt." + strings.ReplaceAll(removeLeadingSlash(rti.FullMethodName), "/", ".")
|
||||
// Returned context is ignored because will populate context with data that
|
||||
// wraps the span instead. Don't set span kind client on this attempt span
|
||||
// to prevent backend from prepending span name with "Sent.".
|
||||
_, span := trace.StartSpan(ctx, mn, trace.WithSampler(csh.to.TS))
|
||||
|
||||
tcBin := propagation.Binary(span.SpanContext())
|
||||
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,
|
||||
}
|
||||
}
|
||||
|
||||
// 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 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(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))
|
||||
span.AddLink(trace.Link{TraceID: sc.TraceID, SpanID: sc.SpanID, Type: trace.LinkTypeChild})
|
||||
} else {
|
||||
// Returned context is ignored because will populate context with data
|
||||
// that wraps the span instead.
|
||||
_, span = trace.StartSpan(ctx, mn, trace.WithSpanKind(trace.SpanKindServer), trace.WithSampler(ssh.to.TS))
|
||||
}
|
||||
|
||||
return ctx, &traceInfo{
|
||||
span: span,
|
||||
countSentMsg: 0,
|
||||
countRecvMsg: 0,
|
||||
}
|
||||
}
|
||||
|
||||
// populateSpan populates span information based on stats passed in (invariants
|
||||
// of the RPC lifecycle), and also ends span which triggers the span to be
|
||||
// exported.
|
||||
func populateSpan(_ context.Context, rs stats.RPCStats, ti *traceInfo) {
|
||||
if ti == nil || ti.span == nil {
|
||||
// Shouldn't happen, tagRPC call comes before this function gets called
|
||||
// which populates this information.
|
||||
logger.Error("ctx passed into stats handler tracing event handling has no span present")
|
||||
return
|
||||
}
|
||||
span := ti.span
|
||||
|
||||
switch rs := rs.(type) {
|
||||
case *stats.Begin:
|
||||
// Note: Go always added these attributes even though they are not
|
||||
// defined by the OpenCensus gRPC spec. Thus, they are unimportant for
|
||||
// correctness.
|
||||
span.AddAttributes(
|
||||
trace.BoolAttribute("Client", rs.Client),
|
||||
trace.BoolAttribute("FailFast", rs.FailFast),
|
||||
)
|
||||
case *stats.PickerUpdated:
|
||||
span.Annotate(nil, "Delayed LB pick complete")
|
||||
case *stats.InPayload:
|
||||
// message id - "must be calculated as two different counters starting
|
||||
// from one for sent messages and one for received messages."
|
||||
mi := atomic.AddUint32(&ti.countRecvMsg, 1)
|
||||
span.AddMessageReceiveEvent(int64(mi), int64(rs.Length), int64(rs.CompressedLength))
|
||||
case *stats.OutPayload:
|
||||
mi := atomic.AddUint32(&ti.countSentMsg, 1)
|
||||
span.AddMessageSendEvent(int64(mi), int64(rs.Length), int64(rs.CompressedLength))
|
||||
case *stats.End:
|
||||
if rs.Error != nil {
|
||||
// "The mapping between gRPC canonical codes and OpenCensus codes
|
||||
// can be found here", which implies 1:1 mapping to gRPC statuses
|
||||
// (OpenCensus statuses are based off gRPC statuses and a subset).
|
||||
s := status.Convert(rs.Error)
|
||||
span.SetStatus(trace.Status{Code: int32(s.Code()), Message: s.Message()})
|
||||
} else {
|
||||
span.SetStatus(trace.Status{Code: trace.StatusCodeOK}) // could get rid of this else conditional and just leave as 0 value, but this makes it explicit
|
||||
}
|
||||
span.End()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user