github.com/blend/go-sdk@v1.20220411.3/tracing/webtrace/tracer.go (about)

     1  /*
     2  
     3  Copyright (c) 2022 - 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 webtrace
     9  
    10  import (
    11  	"strconv"
    12  	"time"
    13  
    14  	opentracing "github.com/opentracing/opentracing-go"
    15  
    16  	"github.com/blend/go-sdk/tracing"
    17  	"github.com/blend/go-sdk/tracing/httptrace"
    18  	"github.com/blend/go-sdk/web"
    19  )
    20  
    21  var (
    22  	_ web.Tracer            = (*webTracer)(nil)
    23  	_ web.TraceFinisher     = (*webTraceFinisher)(nil)
    24  	_ web.ViewTracer        = (*webTracer)(nil)
    25  	_ web.ViewTraceFinisher = (*webViewTraceFinisher)(nil)
    26  )
    27  
    28  // Tracer returns a web tracer.
    29  func Tracer(tracer opentracing.Tracer) web.Tracer {
    30  	return &webTracer{tracer: tracer}
    31  }
    32  
    33  type webTracer struct {
    34  	tracer opentracing.Tracer
    35  }
    36  
    37  func (wt webTracer) Start(ctx *web.Ctx) web.TraceFinisher {
    38  	var resource string
    39  	var extra []opentracing.StartSpanOption
    40  	if ctx.Route != nil {
    41  		resource = ctx.Route.String()
    42  		extra = append(extra, opentracing.Tag{Key: "http.route", Value: ctx.Route.String()})
    43  	} else {
    44  		resource = ctx.Request.URL.Path
    45  	}
    46  	span, newReq := httptrace.StartHTTPSpan(
    47  		ctx.Context(),
    48  		wt.tracer,
    49  		ctx.Request,
    50  		resource,
    51  		ctx.RequestStarted,
    52  		extra...,
    53  	)
    54  	ctx.Request = newReq
    55  	ctx.WithContext(newReq.Context())
    56  	return &webTraceFinisher{span: span}
    57  }
    58  
    59  type webTraceFinisher struct {
    60  	span opentracing.Span
    61  }
    62  
    63  func (wtf webTraceFinisher) Finish(ctx *web.Ctx, err error) {
    64  	if wtf.span == nil {
    65  		return
    66  	}
    67  	tracing.SpanError(wtf.span, err)
    68  	wtf.span.SetTag(tracing.TagKeyHTTPCode, strconv.Itoa(ctx.Response.StatusCode()))
    69  	wtf.span.Finish()
    70  }
    71  
    72  func (wt webTracer) StartView(ctx *web.Ctx, vr *web.ViewResult) web.ViewTraceFinisher {
    73  	// set up basic start options (these are mostly tags).
    74  	startOptions := []opentracing.StartSpanOption{
    75  		tracing.TagMeasured(),
    76  		opentracing.Tag{Key: tracing.TagKeyResourceName, Value: vr.ViewName},
    77  		opentracing.Tag{Key: tracing.TagKeySpanType, Value: tracing.SpanTypeWeb},
    78  		opentracing.StartTime(time.Now().UTC()),
    79  	}
    80  	// start the span.
    81  	span, _ := tracing.StartSpanFromContext(ctx.Context(), wt.tracer, tracing.OperationHTTPRender, startOptions...)
    82  	return &webViewTraceFinisher{span: span}
    83  }
    84  
    85  type webViewTraceFinisher struct {
    86  	span opentracing.Span
    87  }
    88  
    89  func (wvtf webViewTraceFinisher) FinishView(ctx *web.Ctx, vr *web.ViewResult, err error) {
    90  	if wvtf.span == nil {
    91  		return
    92  	}
    93  	tracing.SpanError(wvtf.span, err)
    94  	wvtf.span.Finish()
    95  }