internal/trace: add a wrapper for tracing

This package adds a StartSpan function that does nothing unless an
implementation for the StartSpan function is injected in. That allows
us to have the frontend and worker mains inject the implementation
while internal/fetch and internal/source can use the StartSpan
function without depending on opencensus's tracing library.

For golang/go#61399

Change-Id: I2c650bdbb56c8fcc47ffabab8353cef74e0d1c4e
Reviewed-on: https://go-review.googlesource.com/c/pkgsite/+/523739
Reviewed-by: Robert Findley <rfindley@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Run-TryBot: Michael Matloob <matloob@golang.org>
kokoro-CI: kokoro <noreply+kokoro@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
diff --git a/cmd/frontend/main.go b/cmd/frontend/main.go
index a140a17..11bcaa7 100644
--- a/cmd/frontend/main.go
+++ b/cmd/frontend/main.go
@@ -16,6 +16,7 @@
 	"github.com/go-redis/redis/v8"
 	"github.com/google/safehtml/template"
 	"go.opencensus.io/plugin/ochttp"
+	octrace "go.opencensus.io/trace"
 	"golang.org/x/pkgsite/cmd/internal/cmdconfig"
 	"golang.org/x/pkgsite/internal"
 	"golang.org/x/pkgsite/internal/config"
@@ -34,6 +35,7 @@
 	"golang.org/x/pkgsite/internal/queue/gcpqueue"
 	"golang.org/x/pkgsite/internal/source"
 	"golang.org/x/pkgsite/internal/static"
+	"golang.org/x/pkgsite/internal/trace"
 	"golang.org/x/pkgsite/internal/vuln"
 )
 
@@ -118,6 +120,9 @@
 		}
 	}
 
+	trace.SetTraceFunction(func(ctx context.Context, name string) (context.Context, trace.Span) {
+		return octrace.StartSpan(ctx, name)
+	})
 	reporter := cmdconfig.Reporter(ctx, cfg)
 	vc, err := vuln.NewClient(cfg.VulnDB)
 	if err != nil {
diff --git a/cmd/worker/main.go b/cmd/worker/main.go
index 3238587..2383130 100644
--- a/cmd/worker/main.go
+++ b/cmd/worker/main.go
@@ -18,6 +18,7 @@
 	"github.com/google/safehtml/template"
 	_ "github.com/jackc/pgx/v4/stdlib" // for pgx driver
 	"go.opencensus.io/plugin/ochttp"
+	octrace "go.opencensus.io/trace"
 	"golang.org/x/pkgsite/cmd/internal/cmdconfig"
 	"golang.org/x/pkgsite/internal/config"
 	"golang.org/x/pkgsite/internal/config/serverconfig"
@@ -29,6 +30,7 @@
 	"golang.org/x/pkgsite/internal/proxy"
 	"golang.org/x/pkgsite/internal/queue/gcpqueue"
 	"golang.org/x/pkgsite/internal/source"
+	"golang.org/x/pkgsite/internal/trace"
 	"golang.org/x/pkgsite/internal/worker"
 )
 
@@ -96,6 +98,9 @@
 	}
 
 	reporter := cmdconfig.Reporter(ctx, cfg)
+	trace.SetTraceFunction(func(ctx context.Context, name string) (context.Context, trace.Span) {
+		return octrace.StartSpan(ctx, name)
+	})
 	redisCacheClient := getCacheRedis(ctx, cfg)
 	redisBetaCacheClient := getBetaCacheRedis(ctx, cfg)
 	experimenter := cmdconfig.Experimenter(ctx, cfg, expg, reporter)
diff --git a/internal/fetch/fetch.go b/internal/fetch/fetch.go
index 6aab1f8..f91e059 100644
--- a/internal/fetch/fetch.go
+++ b/internal/fetch/fetch.go
@@ -14,7 +14,6 @@
 	"strings"
 	"time"
 
-	"go.opencensus.io/trace"
 	"golang.org/x/mod/modfile"
 	"golang.org/x/pkgsite/internal"
 	"golang.org/x/pkgsite/internal/derrors"
@@ -22,6 +21,7 @@
 	"golang.org/x/pkgsite/internal/log"
 	"golang.org/x/pkgsite/internal/proxy"
 	"golang.org/x/pkgsite/internal/stdlib"
+	"golang.org/x/pkgsite/internal/trace"
 )
 
 var ErrModuleContainsNoPackages = errors.New("module contains 0 packages")
diff --git a/internal/fetch/load.go b/internal/fetch/load.go
index ea3323e..97105a3 100644
--- a/internal/fetch/load.go
+++ b/internal/fetch/load.go
@@ -22,12 +22,12 @@
 	"sort"
 	"strings"
 
-	"go.opencensus.io/trace"
 	"golang.org/x/pkgsite/internal"
 	"golang.org/x/pkgsite/internal/derrors"
 	"golang.org/x/pkgsite/internal/godoc"
 	"golang.org/x/pkgsite/internal/source"
 	"golang.org/x/pkgsite/internal/stdlib"
+	"golang.org/x/pkgsite/internal/trace"
 )
 
 // BadPackageError represents an error loading a package
diff --git a/internal/fetch/package.go b/internal/fetch/package.go
index b409ae4..73c072e 100644
--- a/internal/fetch/package.go
+++ b/internal/fetch/package.go
@@ -14,7 +14,6 @@
 	"runtime/debug"
 	"strings"
 
-	"go.opencensus.io/trace"
 	"golang.org/x/mod/module"
 	"golang.org/x/pkgsite/internal"
 	"golang.org/x/pkgsite/internal/derrors"
@@ -22,6 +21,7 @@
 	"golang.org/x/pkgsite/internal/licenses"
 	"golang.org/x/pkgsite/internal/log"
 	"golang.org/x/pkgsite/internal/source"
+	"golang.org/x/pkgsite/internal/trace"
 )
 
 // A goPackage is a group of one or more Go source files with the same
diff --git a/internal/source/source.go b/internal/source/source.go
index 3435d58..111b7fd 100644
--- a/internal/source/source.go
+++ b/internal/source/source.go
@@ -31,11 +31,11 @@
 	"strconv"
 	"strings"
 
-	"go.opencensus.io/trace"
 	"golang.org/x/net/context/ctxhttp"
 	"golang.org/x/pkgsite/internal/derrors"
 	"golang.org/x/pkgsite/internal/log"
 	"golang.org/x/pkgsite/internal/stdlib"
+	"golang.org/x/pkgsite/internal/trace"
 	"golang.org/x/pkgsite/internal/version"
 )
 
diff --git a/internal/trace/trace.go b/internal/trace/trace.go
new file mode 100644
index 0000000..44567ae
--- /dev/null
+++ b/internal/trace/trace.go
@@ -0,0 +1,35 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// package trace provides a wrapper around third party tracing
+// libraries
+package trace
+
+import "context"
+
+// Span is an interface for a type that ends a span.
+type Span interface {
+	End()
+}
+
+type trivialEnder struct{}
+
+func (trivialEnder) End() {}
+
+var startSpan func(context.Context, string) (context.Context, Span)
+
+// SetTraceFunction sets StartSpan to call the given function to start
+// a trace span.
+func SetTraceFunction(f func(context.Context, string) (context.Context, Span)) {
+	startSpan = f
+}
+
+// If SetTraceFunction has been called, StartSpan uses its given
+// function to start a span. Otherwise it does nothing.
+func StartSpan(ctx context.Context, name string) (context.Context, Span) {
+	if startSpan != nil {
+		return startSpan(ctx, name)
+	}
+	return ctx, trivialEnder{}
+}