github.com/blend/go-sdk@v1.20240719.1/tracing/r2trace/tracer.go (about)

     1  /*
     2  
     3  Copyright (c) 2024 - Present. Blend Labs, Inc. All rights reserved
     4  Use of this source code is governed by a MIT license that can be found in the LICENSE file.
     5  
     6  */
     7  
     8  package r2trace
     9  
    10  import (
    11  	"net/http"
    12  	"strconv"
    13  	"strings"
    14  	"time"
    15  
    16  	opentracing "github.com/opentracing/opentracing-go"
    17  	opentracingExt "github.com/opentracing/opentracing-go/ext"
    18  
    19  	"github.com/blend/go-sdk/r2"
    20  	"github.com/blend/go-sdk/tracing"
    21  )
    22  
    23  var (
    24  	_ r2.Tracer        = (*r2Tracer)(nil)
    25  	_ r2.TraceFinisher = (*r2TraceFinisher)(nil)
    26  )
    27  
    28  // Tracer returns a request tracer that also injects span context into outgoing headers.
    29  func Tracer(tracer opentracing.Tracer) r2.Tracer {
    30  	return &r2Tracer{tracer: tracer}
    31  }
    32  
    33  type r2Tracer struct {
    34  	tracer opentracing.Tracer
    35  }
    36  
    37  func (rt r2Tracer) Start(req *http.Request) r2.TraceFinisher {
    38  	startOptions := []opentracing.StartSpanOption{
    39  		opentracingExt.SpanKindRPCClient,
    40  		opentracing.Tag{Key: tracing.TagKeySpanType, Value: tracing.SpanTypeHTTP},
    41  		opentracing.Tag{Key: tracing.TagKeyResourceName, Value: r2.GetRawURLParameterized(req)},
    42  		opentracing.Tag{Key: tracing.TagKeyHTTPMethod, Value: strings.ToUpper(req.Method)},
    43  		opentracing.Tag{Key: tracing.TagKeyHTTPURL, Value: req.URL.String()},
    44  		tracing.TagMeasured(),
    45  		opentracing.StartTime(time.Now().UTC()),
    46  	}
    47  	span, ctx := tracing.StartSpanFromContext(req.Context(), rt.tracer, tracing.OperationHTTPRequestOutgoing, startOptions...)
    48  	*req = *req.WithContext(ctx)
    49  
    50  	if req.Header == nil {
    51  		req.Header = make(http.Header)
    52  	}
    53  	_ = rt.tracer.Inject(span.Context(), opentracing.HTTPHeaders, opentracing.HTTPHeadersCarrier(req.Header))
    54  	return r2TraceFinisher{span: span}
    55  }
    56  
    57  type r2TraceFinisher struct {
    58  	span opentracing.Span
    59  }
    60  
    61  func (rtf r2TraceFinisher) Finish(req *http.Request, res *http.Response, ts time.Time, err error) {
    62  	if rtf.span == nil {
    63  		return
    64  	}
    65  	tracing.SpanError(rtf.span, err)
    66  	if res != nil {
    67  		rtf.span.SetTag(tracing.TagKeyHTTPCode, strconv.Itoa(res.StatusCode))
    68  	} else {
    69  		rtf.span.SetTag(tracing.TagKeyHTTPCode, http.StatusInternalServerError)
    70  	}
    71  	rtf.span.Finish()
    72  }