mirror of
https://gitea.com/Lydanne/buildx.git
synced 2025-07-09 21:17:09 +08:00
vendor: update buildkit to opentelemetry support
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
This commit is contained in:
133
vendor/github.com/moby/buildkit/util/tracing/tracing.go
generated
vendored
Normal file
133
vendor/github.com/moby/buildkit/util/tracing/tracing.go
generated
vendored
Normal file
@ -0,0 +1,133 @@
|
||||
package tracing
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/codes"
|
||||
"go.opentelemetry.io/otel/propagation"
|
||||
semconv "go.opentelemetry.io/otel/semconv/v1.4.0"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
)
|
||||
|
||||
// StartSpan starts a new span as a child of the span in context.
|
||||
// If there is no span in context then this is a no-op.
|
||||
func StartSpan(ctx context.Context, operationName string, opts ...trace.SpanStartOption) (trace.Span, context.Context) {
|
||||
parent := trace.SpanFromContext(ctx)
|
||||
tracer := trace.NewNoopTracerProvider().Tracer("")
|
||||
if parent != nil && parent.SpanContext().IsValid() {
|
||||
tracer = parent.TracerProvider().Tracer("")
|
||||
}
|
||||
ctx, span := tracer.Start(ctx, operationName, opts...)
|
||||
return span, ctx
|
||||
}
|
||||
|
||||
// FinishWithError finalizes the span and sets the error if one is passed
|
||||
func FinishWithError(span trace.Span, err error) {
|
||||
if err != nil {
|
||||
span.RecordError(err)
|
||||
if _, ok := err.(interface {
|
||||
Cause() error
|
||||
}); ok {
|
||||
span.SetAttributes(attribute.String(string(semconv.ExceptionStacktraceKey), fmt.Sprintf("%+v", err)))
|
||||
}
|
||||
span.SetStatus(codes.Error, err.Error())
|
||||
}
|
||||
span.End()
|
||||
}
|
||||
|
||||
// ContextWithSpanFromContext sets the tracing span of a context from other
|
||||
// context if one is not already set. Alternative would be
|
||||
// context.WithoutCancel() that would copy the context but reset ctx.Done
|
||||
func ContextWithSpanFromContext(ctx, ctx2 context.Context) context.Context {
|
||||
// if already is a span then noop
|
||||
if span := trace.SpanFromContext(ctx); span.SpanContext().IsValid() {
|
||||
return ctx
|
||||
}
|
||||
if span := trace.SpanFromContext(ctx2); span != nil && span.SpanContext().IsValid() {
|
||||
return trace.ContextWithSpan(ctx, span)
|
||||
}
|
||||
return ctx
|
||||
}
|
||||
|
||||
var DefaultTransport http.RoundTripper = &Transport{
|
||||
RoundTripper: NewTransport(http.DefaultTransport),
|
||||
}
|
||||
|
||||
var DefaultClient = &http.Client{
|
||||
Transport: DefaultTransport,
|
||||
}
|
||||
|
||||
var propagators = propagation.NewCompositeTextMapPropagator(propagation.TraceContext{}, propagation.Baggage{})
|
||||
|
||||
type Transport struct {
|
||||
http.RoundTripper
|
||||
}
|
||||
|
||||
func NewTransport(rt http.RoundTripper) http.RoundTripper {
|
||||
// TODO: switch to otelhttp. needs upstream updates to avoid transport-global tracer
|
||||
return &Transport{
|
||||
RoundTripper: rt,
|
||||
}
|
||||
}
|
||||
|
||||
func (t *Transport) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||
span := trace.SpanFromContext(req.Context())
|
||||
if !span.SpanContext().IsValid() { // no tracer connected with either request or transport
|
||||
return t.RoundTripper.RoundTrip(req)
|
||||
}
|
||||
|
||||
ctx, span := span.TracerProvider().Tracer("").Start(req.Context(), req.Method)
|
||||
|
||||
req = req.WithContext(ctx)
|
||||
span.SetAttributes(semconv.HTTPClientAttributesFromHTTPRequest(req)...)
|
||||
propagators.Inject(ctx, propagation.HeaderCarrier(req.Header))
|
||||
|
||||
resp, err := t.RoundTripper.RoundTrip(req)
|
||||
if err != nil {
|
||||
span.RecordError(err)
|
||||
span.End()
|
||||
return resp, err
|
||||
}
|
||||
|
||||
span.SetAttributes(semconv.HTTPAttributesFromHTTPStatusCode(resp.StatusCode)...)
|
||||
span.SetStatus(semconv.SpanStatusFromHTTPStatusCode(resp.StatusCode))
|
||||
|
||||
if req.Method == "HEAD" {
|
||||
span.End()
|
||||
} else {
|
||||
resp.Body = &wrappedBody{ctx: ctx, span: span, body: resp.Body}
|
||||
}
|
||||
|
||||
return resp, err
|
||||
}
|
||||
|
||||
type wrappedBody struct {
|
||||
ctx context.Context
|
||||
span trace.Span
|
||||
body io.ReadCloser
|
||||
}
|
||||
|
||||
var _ io.ReadCloser = &wrappedBody{}
|
||||
|
||||
func (wb *wrappedBody) Read(b []byte) (int, error) {
|
||||
n, err := wb.body.Read(b)
|
||||
|
||||
switch err {
|
||||
case nil:
|
||||
// nothing to do here but fall through to the return
|
||||
case io.EOF:
|
||||
wb.span.End()
|
||||
default:
|
||||
wb.span.RecordError(err)
|
||||
}
|
||||
return n, err
|
||||
}
|
||||
|
||||
func (wb *wrappedBody) Close() error {
|
||||
wb.span.End()
|
||||
return wb.body.Close()
|
||||
}
|
Reference in New Issue
Block a user