github.com/grahambrereton-form3/tilt@v0.10.18/internal/tracer/tracer.go (about)

     1  package tracer
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"log"
     7  	"os"
     8  	"strings"
     9  
    10  	"github.com/pkg/errors"
    11  
    12  	"github.com/lightstep/lightstep-tracer-go"
    13  	"github.com/opentracing/opentracing-go"
    14  	zipkin "github.com/openzipkin/zipkin-go-opentracing"
    15  	jaeger "github.com/uber/jaeger-client-go"
    16  	jaegercfg "github.com/uber/jaeger-client-go/config"
    17  
    18  	"github.com/windmilleng/tilt/pkg/logger"
    19  )
    20  
    21  const windmillTracerHostPort = "opentracing.windmill.build:9411"
    22  
    23  type TracerBackend int
    24  
    25  const (
    26  	Windmill TracerBackend = iota
    27  	Lightstep
    28  	Jaeger
    29  )
    30  
    31  type zipkinLogger struct {
    32  	ctx context.Context
    33  }
    34  
    35  func (zl zipkinLogger) Log(keyvals ...interface{}) error {
    36  	logger.Get(zl.ctx).Debugf("%v", keyvals)
    37  	return nil
    38  }
    39  
    40  var _ zipkin.Logger = zipkinLogger{}
    41  
    42  func Init(ctx context.Context, tracer TracerBackend) (func() error, error) {
    43  	switch tracer {
    44  	case Windmill:
    45  		return initWindmillZipkin(ctx)
    46  	case Lightstep:
    47  		return initLightStep(ctx)
    48  	case Jaeger:
    49  		return initJaeger(ctx)
    50  	default:
    51  		return nil, fmt.Errorf("Init: Invalid Tracer backend: %d", tracer)
    52  	}
    53  }
    54  
    55  func TraceID(ctx context.Context) (string, error) {
    56  	spanContext := opentracing.SpanFromContext(ctx)
    57  	if spanContext == nil {
    58  		return "", errors.New("cannot get traceid - there is no span context")
    59  	}
    60  	switch t := spanContext.Context().(type) {
    61  	case zipkin.SpanContext:
    62  		return t.TraceID.ToHex(), nil
    63  	case lightstep.SpanContext:
    64  		return string(t.TraceID), nil
    65  	case jaeger.SpanContext:
    66  		return t.TraceID().String(), nil
    67  	default:
    68  		return "", errors.New("cannot get traceid - unknown span type")
    69  	}
    70  }
    71  
    72  // TagStrToMap converts a user-passed string of tags of the form `key1=val1,key2=val2` to a map.
    73  func TagStrToMap(tagStr string) map[string]string {
    74  	if tagStr == "" {
    75  		return nil
    76  	}
    77  
    78  	res := make(map[string]string)
    79  	pairs := strings.Split(tagStr, ",")
    80  	for _, p := range pairs {
    81  		elems := strings.Split(strings.TrimSpace(p), "=")
    82  		if len(elems) != 2 {
    83  			log.Printf("got malformed trace tag: %s", p)
    84  			continue
    85  		}
    86  		res[elems[0]] = elems[1]
    87  	}
    88  	return res
    89  }
    90  
    91  func StringToTracerBackend(s string) (TracerBackend, error) {
    92  	switch s {
    93  	case "windmill":
    94  		return Windmill, nil
    95  	case "lightstep":
    96  		return Lightstep, nil
    97  	case "jaeger":
    98  		return Jaeger, nil
    99  	default:
   100  		return Windmill, fmt.Errorf("Invalid Tracer backend: %s", s)
   101  	}
   102  }
   103  
   104  func initWindmillZipkin(ctx context.Context) (func() error, error) {
   105  	collector, err := zipkin.NewHTTPCollector(fmt.Sprintf("http://%s/api/v1/spans", windmillTracerHostPort), zipkin.HTTPLogger(zipkinLogger{ctx}))
   106  
   107  	if err != nil {
   108  		return nil, errors.Wrap(err, "unable to create zipkin collector")
   109  	}
   110  
   111  	recorder := zipkin.NewRecorder(collector, true, "0.0.0.0:0", "tilt")
   112  	tracer, err := zipkin.NewTracer(recorder)
   113  
   114  	if err != nil {
   115  		return nil, errors.Wrap(err, "unable to create tracer")
   116  	}
   117  
   118  	opentracing.SetGlobalTracer(tracer)
   119  
   120  	return collector.Close, nil
   121  }
   122  
   123  func initLightStep(ctx context.Context) (func() error, error) {
   124  	token, ok := os.LookupEnv("LIGHTSTEP_ACCESS_TOKEN")
   125  	if !ok {
   126  		return nil, fmt.Errorf("No token found in the LIGHTSTEP_ACCESS_TOKEN environment variable")
   127  	}
   128  	lightstepTracer := lightstep.NewTracer(lightstep.Options{
   129  		AccessToken: token,
   130  	})
   131  
   132  	opentracing.SetGlobalTracer(lightstepTracer)
   133  
   134  	close := func() error {
   135  		lightstepTracer.Close(context.Background())
   136  		return nil
   137  	}
   138  	return close, nil
   139  }
   140  
   141  func initJaeger(ctx context.Context) (func() error, error) {
   142  	cfg := jaegercfg.Configuration{
   143  		Sampler: &jaegercfg.SamplerConfig{
   144  			Type:  "const",
   145  			Param: 1,
   146  		},
   147  	}
   148  	closer, err := cfg.InitGlobalTracer("tilt")
   149  	return closer.Close, err
   150  }