fork of https://github.com/sourcegraph/zoekt
0

Configure Feed

Select the types of activity you want to include in your feed.

add Jaeger tracing (#55)

author
Beyang Liu
committer
GitHub
date (Aug 13, 2020, 11:06 AM -0700) commit 1373c398 parent 18a8fad5
+362 -15
+7
api.go
··· 316 316 // Trim the number of results after collating and sorting the 317 317 // results 318 318 MaxDocDisplayCount int 319 + 320 + // Trace turns on opentracing for this request if true and if the Jaeger address was provided as 321 + // a command-line flag 322 + Trace bool 323 + 324 + // SpanContext is the opentracing span context, if it exists, from the zoekt client 325 + SpanContext map[string]string 319 326 } 320 327 321 328 func (s *SearchOptions) String() string {
+46
cmd/zoekt-webserver/main.go
··· 28 28 "net/http" 29 29 "os" 30 30 "path/filepath" 31 + "reflect" 32 + "strconv" 31 33 "strings" 32 34 "syscall" 33 35 "time" ··· 38 40 "github.com/google/zoekt/query" 39 41 "github.com/google/zoekt/shards" 40 42 "github.com/google/zoekt/web" 43 + "github.com/opentracing/opentracing-go" 41 44 "github.com/prometheus/client_golang/prometheus" 42 45 "go.uber.org/automaxprocs/maxprocs" 46 + 47 + "github.com/uber/jaeger-client-go" 48 + jaegercfg "github.com/uber/jaeger-client-go/config" 49 + jaegerlog "github.com/uber/jaeger-client-go/log" 50 + jaegermetrics "github.com/uber/jaeger-lib/metrics" 43 51 ) 44 52 45 53 const logFormat = "2006-01-02T15-04-05.999999999Z07" ··· 125 133 dumpTemplates := flag.Bool("dump_templates", false, "dump templates into --template_dir and exit.") 126 134 version := flag.Bool("version", false, "Print version number") 127 135 flag.Parse() 136 + 137 + initializeJaeger() 128 138 129 139 if *version { 130 140 fmt.Printf("zoekt-webserver version %q\n", zoekt.Version) ··· 314 324 } 315 325 return sr, err 316 326 } 327 + 328 + func initializeJaeger() { 329 + jaegerDisabled := os.Getenv("JAEGER_DISABLED") 330 + if jaegerDisabled == "" { 331 + return 332 + } 333 + isJaegerDisabled, err := strconv.ParseBool(jaegerDisabled) 334 + if err != nil { 335 + log.Printf("EROR: failed to parse JAEGER_DISABLED: %s", err) 336 + return 337 + } 338 + if isJaegerDisabled { 339 + return 340 + } 341 + cfg, err := jaegercfg.FromEnv() 342 + cfg.ServiceName = "zoekt" 343 + if err != nil { 344 + log.Printf("EROR: could not initialize jaeger tracer from env, error: %v", err.Error()) 345 + return 346 + } 347 + if reflect.DeepEqual(cfg.Sampler, &jaegercfg.SamplerConfig{}) { 348 + // Default sampler configuration for when it is not specified via 349 + // JAEGER_SAMPLER_* env vars. In most cases, this is sufficient 350 + // enough to connect to Jaeger without any env vars. 351 + cfg.Sampler.Type = jaeger.SamplerTypeConst 352 + cfg.Sampler.Param = 1 353 + } 354 + tracer, _, err := cfg.NewTracer( 355 + jaegercfg.Logger(jaegerlog.StdLogger), 356 + jaegercfg.Metrics(jaegermetrics.NullFactory), 357 + ) 358 + if err != nil { 359 + log.Printf("could not initialize jaeger tracer, error: %v", err.Error()) 360 + } 361 + opentracing.SetGlobalTracer(tracer) 362 + }
+1 -2
eval.go
··· 21 21 "sort" 22 22 "strings" 23 23 24 + "github.com/google/zoekt/query" 24 25 "golang.org/x/net/trace" 25 - 26 - "github.com/google/zoekt/query" 27 26 ) 28 27 29 28 const maxUInt16 = 0xffff
+6
go.mod
··· 2 2 3 3 require ( 4 4 github.com/andygrunwald/go-gerrit v0.0.0-20191101112536-3f5e365ccf57 5 + github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd // indirect 5 6 github.com/fsnotify/fsnotify v1.4.9 6 7 github.com/gfleury/go-bitbucket-v1 v0.0.0-20200312180434-e5170e3280fb 7 8 github.com/go-git/go-git/v5 v5.0.0 ··· 15 16 github.com/keegancsmith/tmpfriend v0.0.0-20180423180255-86e88902a513 16 17 github.com/kylelemons/godebug v1.1.0 17 18 github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f 19 + github.com/opentracing-contrib/go-stdlib v1.0.0 20 + github.com/opentracing/opentracing-go v1.2.0 18 21 github.com/prometheus/client_golang v1.5.1 19 22 github.com/prometheus/procfs v0.0.10 // indirect 23 + github.com/uber/jaeger-client-go v2.25.0+incompatible 24 + github.com/uber/jaeger-lib v2.2.0+incompatible 20 25 github.com/xanzy/go-gitlab v0.28.0 26 + go.uber.org/atomic v1.4.0 21 27 go.uber.org/automaxprocs v1.3.0 22 28 golang.org/x/crypto v0.0.0-20200311171314-f7b00557c8c4 // indirect 23 29 golang.org/x/net v0.0.0-20200301022130-244492dfa37a
+14
go.sum
··· 28 28 github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= 29 29 github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= 30 30 github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= 31 + github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd h1:qMd81Ts1T2OTKmB4acZcyKaMtRnY5Y44NuXGX2GFJ1w= 32 + github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= 31 33 github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= 32 34 github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= 33 35 github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= ··· 77 79 github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= 78 80 github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= 79 81 github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= 82 + github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= 80 83 github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= 81 84 github.com/go-toolsmith/astcast v1.0.0/go.mod h1:mt2OdQTeAQcY4DQgPSArJjHCcOwlX+Wl/kwN+LbLGQ4= 82 85 github.com/go-toolsmith/astcopy v1.0.0/go.mod h1:vrgyG+5Bxrnz4MZWPF+pI4R8h3qKRjjyvV/DSez4WVQ= ··· 242 245 github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= 243 246 github.com/onsi/gomega v1.8.1/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= 244 247 github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= 248 + github.com/opentracing-contrib/go-stdlib v1.0.0 h1:TBS7YuVotp8myLon4Pv7BtCBzOTo1DeZCld0Z63mW2w= 249 + github.com/opentracing-contrib/go-stdlib v1.0.0/go.mod h1:qtI1ogk+2JhVPIXVc6q+NHziSmy2W5GbdQZFUHADCBU= 250 + github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= 251 + github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= 252 + github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= 245 253 github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= 246 254 github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= 247 255 github.com/pelletier/go-toml v1.6.0/go.mod h1:5N711Q9dKgbdkxHL+MEfF31hpT7l0S0s/t2kKREewys= ··· 313 321 github.com/spf13/viper v1.6.2/go.mod h1:t3iDnF5Jlj76alVNuyFBk5oUMCvsrkbvZK0WQdfDi5k= 314 322 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 315 323 github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 324 + github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48= 316 325 github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= 317 326 github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= 318 327 github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= ··· 327 336 github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= 328 337 github.com/tommy-muehle/go-mnd v1.1.1/go.mod h1:dSUh0FtTP8VhvkL1S+gUR1OKd9ZnSaozuI6r3m6wOig= 329 338 github.com/tommy-muehle/go-mnd v1.3.0/go.mod h1:dSUh0FtTP8VhvkL1S+gUR1OKd9ZnSaozuI6r3m6wOig= 339 + github.com/uber/jaeger-client-go v2.25.0+incompatible h1:IxcNZ7WRY1Y3G4poYlx24szfsn/3LvK9QHCq9oQw8+U= 340 + github.com/uber/jaeger-client-go v2.25.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= 341 + github.com/uber/jaeger-lib v2.2.0+incompatible h1:MxZXOiR2JuoANZ3J6DE/U0kSFv/eJ/GfSYVCjK7dyaw= 342 + github.com/uber/jaeger-lib v2.2.0+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U= 330 343 github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= 331 344 github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= 332 345 github.com/ultraware/funlen v0.0.2/go.mod h1:Dp4UiAus7Wdb9KUZsYWZEWiRzGuM2kXM1lPbfaF6xhA= ··· 343 356 github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= 344 357 github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= 345 358 go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= 359 + go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU= 346 360 go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= 347 361 go.uber.org/automaxprocs v1.3.0 h1:II28aZoGdaglS5vVNnspf28lnZpXScxtIozx1lAjdb0= 348 362 go.uber.org/automaxprocs v1.3.0/go.mod h1:9CWT6lKIep8U41DDaPiH6eFscnTyjfTANNQNx6LrIcA=
+6 -7
shards/eval.go
··· 3 3 import ( 4 4 "context" 5 5 6 - "golang.org/x/net/trace" 7 - 8 6 "github.com/google/zoekt" 9 7 "github.com/google/zoekt/query" 8 + "github.com/google/zoekt/trace" 10 9 ) 11 10 12 - // repoSearcher evaluates all type:repo sub-queries before sending the query 11 + // typeRepoSearcher evaluates all type:repo sub-queries before sending the query 13 12 // to the underlying searcher. We need to evaluate type:repo queries first 14 13 // since they need to do cross shard operations. 15 14 type typeRepoSearcher struct { ··· 17 16 } 18 17 19 18 func (s *typeRepoSearcher) Search(ctx context.Context, q query.Q, opts *zoekt.SearchOptions) (sr *zoekt.SearchResult, err error) { 20 - tr := trace.New("typeRepoSearcher.Search", "") 19 + tr, ctx := trace.New(ctx, "typeRepoSearcher.Search", "") 21 20 tr.LazyLog(q, true) 22 21 tr.LazyPrintf("opts: %+v", opts) 23 22 defer func() { ··· 27 26 } 28 27 if err != nil { 29 28 tr.LazyPrintf("error: %v", err) 30 - tr.SetError() 29 + tr.SetError(err) 31 30 } 32 31 tr.Finish() 33 32 }() ··· 41 40 } 42 41 43 42 func (s *typeRepoSearcher) List(ctx context.Context, r query.Q) (rl *zoekt.RepoList, err error) { 44 - tr := trace.New("typeRepoSearcher.List", "") 43 + tr, ctx := trace.New(ctx, "typeRepoSearcher.List", "") 45 44 tr.LazyLog(r, true) 46 45 defer func() { 47 46 if rl != nil { ··· 50 49 } 51 50 if err != nil { 52 51 tr.LazyPrintf("error: %v", err) 53 - tr.SetError() 52 + tr.SetError(err) 54 53 } 55 54 tr.Finish() 56 55 }()
+5 -5
shards/shards.go
··· 24 24 "sort" 25 25 "time" 26 26 27 - "golang.org/x/net/trace" 28 27 "golang.org/x/sync/semaphore" 29 28 30 29 "github.com/google/zoekt" 31 30 "github.com/google/zoekt/query" 31 + "github.com/google/zoekt/trace" 32 32 "github.com/prometheus/client_golang/prometheus" 33 33 "github.com/prometheus/client_golang/prometheus/promauto" 34 34 ) ··· 290 290 } 291 291 292 292 func (ss *shardedSearcher) Search(ctx context.Context, q query.Q, opts *zoekt.SearchOptions) (sr *zoekt.SearchResult, err error) { 293 - tr := trace.New("shardedSearcher.Search", "") 293 + tr, ctx := trace.New(ctx, "shardedSearcher.Search", "") 294 294 tr.LazyLog(q, true) 295 295 tr.LazyPrintf("opts: %+v", opts) 296 296 overallStart := time.Now() ··· 318 318 metricSearchFailedTotal.Inc() 319 319 320 320 tr.LazyPrintf("error: %v", err) 321 - tr.SetError() 321 + tr.SetError(err) 322 322 } 323 323 tr.Finish() 324 324 }() ··· 464 464 } 465 465 466 466 func (ss *shardedSearcher) List(ctx context.Context, r query.Q) (rl *zoekt.RepoList, err error) { 467 - tr := trace.New("shardedSearcher.List", "") 467 + tr, ctx := trace.New(ctx, "shardedSearcher.List", "") 468 468 tr.LazyLog(r, true) 469 469 metricListRunning.Inc() 470 470 defer func() { ··· 475 475 } 476 476 if err != nil { 477 477 tr.LazyPrintf("error: %v", err) 478 - tr.SetError() 478 + tr.SetError(err) 479 479 } 480 480 tr.Finish() 481 481 }()
+49
trace/opentracing.go
··· 1 + package trace 2 + 3 + import ( 4 + "context" 5 + 6 + "github.com/opentracing/opentracing-go" 7 + ) 8 + 9 + type key int 10 + 11 + const ( 12 + enableOpenTracingKey key = iota 13 + ) 14 + 15 + // isOpenTracingEnabled returns true if the enableOpenTracingKey context value is true. 16 + func isOpenTracingEnabled(ctx context.Context) bool { 17 + v, ok := ctx.Value(enableOpenTracingKey).(bool) 18 + if !ok { 19 + return false 20 + } 21 + return v 22 + } 23 + 24 + func WithOpenTracingEnabled(ctx context.Context, enableOpenTracing bool) context.Context { 25 + return context.WithValue(ctx, enableOpenTracingKey, enableOpenTracing) 26 + } 27 + 28 + // GetOpenTracer returns the tracer to actually use depending on whether isOpenTracingEnabled(ctx) 29 + // returns true or false. If false, this returns the NoopTracer. 30 + func GetOpenTracer(ctx context.Context, tracer opentracing.Tracer) opentracing.Tracer { 31 + if !isOpenTracingEnabled(ctx) { 32 + return opentracing.NoopTracer{} 33 + } 34 + if tracer == nil { 35 + return opentracing.GlobalTracer() 36 + } 37 + return tracer 38 + } 39 + 40 + // StartSpanFromContext starts a span using the tracer returned by invoking GetOpenTracer with the 41 + // passed-in tracer. 42 + func StartSpanFromContextWithTracer(ctx context.Context, tracer opentracing.Tracer, operationName string, opts ...opentracing.StartSpanOption) (opentracing.Span, context.Context) { 43 + return opentracing.StartSpanFromContextWithTracer(ctx, GetOpenTracer(ctx, tracer), operationName, opts...) 44 + } 45 + 46 + // StartSpanFromContext starts a span using the tracer returned by GetOpenTracer. 47 + func StartSpanFromContext(ctx context.Context, operationName string, opts ...opentracing.StartSpanOption) (opentracing.Span, context.Context) { 48 + return StartSpanFromContextWithTracer(ctx, GetOpenTracer(ctx, nil), operationName, opts...) 49 + }
+187
trace/trace.go
··· 1 + // Package trace provides a tracing API that in turn invokes both the `golang.org/x/net/trace` API 2 + // and creates an opentracing span if appropriate. 3 + // 4 + // This is similar to the github.com/sourcegraph/sourcegraph/internal/trace package in the main repo, 5 + // and it may make sense to factor both out into a common package at some point. 6 + package trace 7 + 8 + import ( 9 + "context" 10 + "fmt" 11 + "strconv" 12 + "strings" 13 + 14 + "github.com/opentracing/opentracing-go" 15 + "github.com/opentracing/opentracing-go/ext" 16 + "github.com/opentracing/opentracing-go/log" 17 + nettrace "golang.org/x/net/trace" 18 + ) 19 + 20 + // A Tracer for trace creation, parameterised over an 21 + // opentracing.Tracer. Use this if you don't want to use 22 + // the global tracer. 23 + type Tracer struct { 24 + Tracer opentracing.Tracer 25 + } 26 + 27 + func New(ctx context.Context, family, title string) (*Trace, context.Context) { 28 + tr := Tracer{Tracer: GetOpenTracer(ctx, nil)} 29 + return tr.New(ctx, family, title) 30 + } 31 + 32 + // New returns a new Trace with the specified family and title. 33 + func (t Tracer) New(ctx context.Context, family, title string) (*Trace, context.Context) { 34 + span, ctx := StartSpanFromContextWithTracer( 35 + ctx, 36 + t.Tracer, 37 + family, 38 + opentracing.Tag{Key: "title", Value: title}, 39 + ) 40 + tr := nettrace.New(family, title) 41 + trace := &Trace{span: span, trace: tr, family: family} 42 + if parent := TraceFromContext(ctx); parent != nil { 43 + tr.LazyPrintf("parent: %s", parent.family) 44 + trace.family = parent.family + " > " + family 45 + } 46 + return trace, ContextWithTrace(ctx, trace) 47 + } 48 + 49 + // Trace is a combined version of golang.org/x/net/trace.Trace and 50 + // opentracing.Span. Use New to construct one. 51 + type Trace struct { 52 + trace nettrace.Trace 53 + span opentracing.Span 54 + family string 55 + } 56 + 57 + // LazyPrintf evaluates its arguments with fmt.Sprintf each time the 58 + // /debug/requests page is rendered. Any memory referenced by a will be 59 + // pinned until the trace is finished and later discarded. 60 + func (t *Trace) LazyPrintf(format string, a ...interface{}) { 61 + t.span.LogFields(Printf("log", format, a...)) 62 + t.trace.LazyPrintf(format, a...) 63 + } 64 + 65 + func (t *Trace) LazyLog(x fmt.Stringer, sensitive bool) { 66 + t.trace.LazyLog(x, sensitive) 67 + } 68 + 69 + // LogFields logs fields to the opentracing.Span 70 + // as well as the nettrace.Trace. 71 + func (t *Trace) LogFields(fields ...log.Field) { 72 + t.span.LogFields(fields...) 73 + t.trace.LazyLog(fieldsStringer(fields), false) 74 + } 75 + 76 + // SetError declares that this trace and span resulted in an error. 77 + func (t *Trace) SetError(err error) { 78 + if err == nil { 79 + return 80 + } 81 + t.trace.LazyPrintf("error: %v", err) 82 + t.trace.SetError() 83 + t.span.LogFields(log.Error(err)) 84 + ext.Error.Set(t.span, true) 85 + } 86 + 87 + // Finish declares that this trace and span is complete. 88 + // The trace should not be used after calling this method. 89 + func (t *Trace) Finish() { 90 + t.trace.Finish() 91 + t.span.Finish() 92 + } 93 + 94 + // Printf is an opentracing log.Field which is a LazyLogger. So the format 95 + // string will only be evaluated if the trace is collected. In the case of 96 + // net/trace, it will only be evaluated on page load. 97 + func Printf(key, f string, args ...interface{}) log.Field { 98 + return log.Lazy(func(fv log.Encoder) { 99 + fv.EmitString(key, fmt.Sprintf(f, args...)) 100 + }) 101 + } 102 + 103 + type traceContextKey string 104 + 105 + const traceKey = traceContextKey("trace") 106 + 107 + // ContextWithTrace returns a new context.Context that holds a reference to 108 + // trace's SpanContext. 109 + func ContextWithTrace(ctx context.Context, tr *Trace) context.Context { 110 + ctx = opentracing.ContextWithSpan(ctx, tr.span) 111 + ctx = context.WithValue(ctx, traceKey, tr) 112 + return ctx 113 + } 114 + 115 + // TraceFromContext returns the Trace previously associated with ctx, or 116 + // nil if no such Trace could be found. 117 + func TraceFromContext(ctx context.Context) *Trace { 118 + tr, _ := ctx.Value(traceKey).(*Trace) 119 + return tr 120 + } 121 + 122 + // fieldsStringer lazily marshals a slice of log.Field into a string for 123 + // printing in net/trace. 124 + type fieldsStringer []log.Field 125 + 126 + func (fs fieldsStringer) String() string { 127 + var e encoder 128 + for _, f := range fs { 129 + f.Marshal(&e) 130 + } 131 + return e.Builder.String() 132 + } 133 + 134 + // encoder is a log.Encoder used by fieldsStringer. 135 + type encoder struct { 136 + strings.Builder 137 + prefixNewline bool 138 + } 139 + 140 + func (e *encoder) EmitString(key, value string) { 141 + if e.prefixNewline { 142 + // most times encoder is used is for one field 143 + e.Builder.WriteString("\n") 144 + } 145 + if !e.prefixNewline { 146 + e.prefixNewline = true 147 + } 148 + 149 + e.Builder.Grow(len(key) + 1 + len(value)) 150 + e.Builder.WriteString(key) 151 + e.Builder.WriteString(":") 152 + e.Builder.WriteString(value) 153 + } 154 + 155 + func (e *encoder) EmitBool(key string, value bool) { 156 + e.EmitString(key, strconv.FormatBool(value)) 157 + } 158 + 159 + func (e *encoder) EmitInt(key string, value int) { 160 + e.EmitString(key, strconv.Itoa(value)) 161 + } 162 + 163 + func (e *encoder) EmitInt32(key string, value int32) { 164 + e.EmitString(key, strconv.FormatInt(int64(value), 10)) 165 + } 166 + func (e *encoder) EmitInt64(key string, value int64) { 167 + e.EmitString(key, strconv.FormatInt(value, 10)) 168 + } 169 + func (e *encoder) EmitUint32(key string, value uint32) { 170 + e.EmitString(key, strconv.FormatUint(uint64(value), 10)) 171 + } 172 + func (e *encoder) EmitUint64(key string, value uint64) { 173 + e.EmitString(key, strconv.FormatUint(value, 10)) 174 + } 175 + func (e *encoder) EmitFloat32(key string, value float32) { 176 + e.EmitString(key, strconv.FormatFloat(float64(value), 'E', -1, 64)) 177 + } 178 + func (e *encoder) EmitFloat64(key string, value float64) { 179 + e.EmitString(key, strconv.FormatFloat(value, 'E', -1, 64)) 180 + } 181 + func (e *encoder) EmitObject(key string, value interface{}) { 182 + e.EmitString(key, fmt.Sprintf("%+v", value)) 183 + } 184 + 185 + func (e *encoder) EmitLazyLogger(value log.LazyLogger) { 186 + value(e) 187 + }
+1 -1
web/server.go
··· 170 170 mux.HandleFunc("/print", s.servePrint) 171 171 } 172 172 if s.RPC { 173 - mux.Handle(rpc.DefaultRPCPath, rpc.Server(s.Searcher)) // /rpc 173 + mux.Handle(rpc.DefaultRPCPath, rpc.Server(traceAwareSearcher{s.Searcher})) // /rpc 174 174 } 175 175 176 176 return mux, nil
+40
web/trace.go
··· 1 + package web 2 + 3 + import ( 4 + "log" 5 + 6 + "github.com/google/zoekt" 7 + "github.com/google/zoekt/query" 8 + "github.com/google/zoekt/trace" 9 + "github.com/opentracing/opentracing-go" 10 + "golang.org/x/net/context" 11 + ) 12 + 13 + // traceAwareSearcher wraps a zoekt.Searcher instance so that the tracing context item is set in the 14 + // context. This context item toggles on trace collection via the 15 + // github.com/sourcegraph/zoekt/trace/ot package. 16 + type traceAwareSearcher struct { 17 + Searcher zoekt.Searcher 18 + } 19 + 20 + func (s traceAwareSearcher) Search(ctx context.Context, q query.Q, opts *zoekt.SearchOptions) (*zoekt.SearchResult, error) { 21 + ctx = trace.WithOpenTracingEnabled(ctx, opts.Trace) 22 + if opts.Trace && opts.SpanContext != nil { 23 + spanContext, err := trace.GetOpenTracer(ctx, nil).Extract(opentracing.TextMap, opentracing.TextMapCarrier(opts.SpanContext)) 24 + if err != nil { 25 + log.Printf("Error extracting span from opts: %s", err) 26 + } 27 + if spanContext != nil { 28 + span, newCtx := opentracing.StartSpanFromContext(ctx, "zoekt.traceAwareSearcher.Search", opentracing.ChildOf(spanContext)) 29 + defer span.Finish() 30 + ctx = newCtx 31 + } 32 + } 33 + return s.Searcher.Search(ctx, q, opts) 34 + } 35 + 36 + func (s traceAwareSearcher) List(ctx context.Context, q query.Q) (*zoekt.RepoList, error) { 37 + return s.Searcher.List(ctx, q) 38 + } 39 + func (s traceAwareSearcher) Close() { s.Searcher.Close() } 40 + func (s traceAwareSearcher) String() string { return s.Searcher.String() }