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 }