github.com/songzhibin97/gkit@v1.2.13/trace/trace.go (about)

     1  package trace
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  
     7  	"github.com/songzhibin97/gkit/errors"
     8  	"github.com/songzhibin97/gkit/options"
     9  	"go.opentelemetry.io/otel"
    10  	"go.opentelemetry.io/otel/attribute"
    11  	"go.opentelemetry.io/otel/codes"
    12  	"go.opentelemetry.io/otel/propagation"
    13  	"go.opentelemetry.io/otel/trace"
    14  	"google.golang.org/protobuf/proto"
    15  )
    16  
    17  type Tracer struct {
    18  	tracer trace.Tracer
    19  	kind   trace.SpanKind
    20  	opt    *config
    21  }
    22  
    23  // NewTracer 创建追踪器
    24  func NewTracer(kind trace.SpanKind, opts ...options.Option) *Tracer {
    25  	cfg := config{
    26  		propagator: propagation.NewCompositeTextMapPropagator(Metadata{}, propagation.Baggage{}, propagation.TraceContext{}),
    27  	}
    28  	for _, o := range opts {
    29  		o(&cfg)
    30  	}
    31  	if cfg.tracerProvider != nil {
    32  		otel.SetTracerProvider(cfg.tracerProvider)
    33  	}
    34  
    35  	switch kind {
    36  	case trace.SpanKindClient:
    37  		return &Tracer{tracer: otel.Tracer("gkit"), kind: kind, opt: &cfg}
    38  	case trace.SpanKindServer:
    39  		return &Tracer{tracer: otel.Tracer("gkit"), kind: kind, opt: &cfg}
    40  	default:
    41  		panic(fmt.Sprintf("unsupported span kind: %v", kind))
    42  	}
    43  }
    44  
    45  // Start 开始追踪
    46  func (t *Tracer) Start(ctx context.Context, operation string, carrier propagation.TextMapCarrier) (context.Context, trace.Span) {
    47  	if t.kind == trace.SpanKindServer {
    48  		ctx = t.opt.propagator.Extract(ctx, carrier)
    49  	}
    50  	ctx, span := t.tracer.Start(ctx,
    51  		operation,
    52  		trace.WithSpanKind(t.kind),
    53  	)
    54  	if t.kind == trace.SpanKindClient {
    55  		t.opt.propagator.Inject(ctx, carrier)
    56  	}
    57  	return ctx, span
    58  }
    59  
    60  // End 完成追踪
    61  func (t *Tracer) End(ctx context.Context, span trace.Span, m interface{}, err error) {
    62  	if err != nil {
    63  		span.RecordError(err)
    64  		if e := errors.FromError(err); e != nil {
    65  			span.SetAttributes(attribute.Key("rpc.status_code").Int64(int64(e.Code)))
    66  		}
    67  		span.SetStatus(codes.Error, err.Error())
    68  	} else {
    69  		span.SetStatus(codes.Ok, "OK")
    70  	}
    71  
    72  	if p, ok := m.(proto.Message); ok {
    73  		if t.kind == trace.SpanKindServer {
    74  			span.SetAttributes(attribute.Key("send_msg.size").Int(proto.Size(p)))
    75  		} else {
    76  			span.SetAttributes(attribute.Key("recv_msg.size").Int(proto.Size(p)))
    77  		}
    78  	}
    79  	span.End()
    80  }