internal/jsonrpc2: move stats and logging across to gopls

Change-Id: I718ad6075028e922a1a046b22fd01a1315421be1
Reviewed-on: https://go-review.googlesource.com/c/tools/+/186297
Run-TryBot: Ian Cottrell <iancottrell@google.com>
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
diff --git a/internal/jsonrpc2/jsonrpc2.go b/internal/jsonrpc2/jsonrpc2.go
index 61aa4e2..76919a8 100644
--- a/internal/jsonrpc2/jsonrpc2.go
+++ b/internal/jsonrpc2/jsonrpc2.go
@@ -11,14 +11,8 @@
 	"context"
 	"encoding/json"
 	"fmt"
-	"log"
 	"sync"
 	"sync/atomic"
-	"time"
-
-	"golang.org/x/tools/internal/lsp/telemetry"
-	"golang.org/x/tools/internal/lsp/telemetry/tag"
-	"golang.org/x/tools/internal/lsp/telemetry/trace"
 )
 
 // Conn is a JSON RPC 2 client server connection.
@@ -55,47 +49,6 @@
 	WireRequest
 }
 
-type rpcStats struct {
-	server bool
-	method string
-	close  func()
-	start  time.Time
-}
-
-func start(ctx context.Context, server bool, method string, id *ID) (context.Context, *rpcStats) {
-	if method == "" {
-		panic("no method in rpc stats")
-	}
-	s := &rpcStats{
-		server: server,
-		method: method,
-		start:  time.Now(),
-	}
-	mode := telemetry.Outbound
-	if server {
-		mode = telemetry.Inbound
-	}
-	ctx, s.close = trace.StartSpan(ctx, method,
-		tag.Tag{Key: telemetry.Method, Value: method},
-		tag.Tag{Key: telemetry.RPCDirection, Value: mode},
-		tag.Tag{Key: telemetry.RPCID, Value: id},
-	)
-	telemetry.Started.Record(ctx, 1)
-	return ctx, s
-}
-
-func (s *rpcStats) end(ctx context.Context, err *error) {
-	if err != nil && *err != nil {
-		ctx = telemetry.StatusCode.With(ctx, "ERROR")
-	} else {
-		ctx = telemetry.StatusCode.With(ctx, "OK")
-	}
-	elapsedTime := time.Since(s.start)
-	latencyMillis := float64(elapsedTime) / float64(time.Millisecond)
-	telemetry.Latency.Record(ctx, latencyMillis)
-	s.close()
-}
-
 // NewErrorf builds a Error struct for the suppied message and code.
 // If args is not empty, message and args will be passed to Sprintf.
 func NewErrorf(code int64, format string, args ...interface{}) *Error {
@@ -451,49 +404,3 @@
 	raw := json.RawMessage(data)
 	return &raw, nil
 }
-
-type statsKeyType int
-
-const statsKey = statsKeyType(0)
-
-type tracer struct {
-}
-
-func (h *tracer) Deliver(ctx context.Context, r *Request, delivered bool) bool {
-	return false
-}
-
-func (h *tracer) Cancel(ctx context.Context, conn *Conn, id ID, cancelled bool) bool {
-	return false
-}
-
-func (h *tracer) Request(ctx context.Context, direction Direction, r *WireRequest) context.Context {
-	ctx, stats := start(ctx, direction == Receive, r.Method, r.ID)
-	ctx = context.WithValue(ctx, statsKey, stats)
-	return ctx
-}
-
-func (h *tracer) Response(ctx context.Context, direction Direction, r *WireResponse) context.Context {
-	return ctx
-}
-
-func (h *tracer) Done(ctx context.Context, err error) {
-	stats, ok := ctx.Value(statsKey).(*rpcStats)
-	if ok && stats != nil {
-		stats.end(ctx, &err)
-	}
-}
-
-func (h *tracer) Read(ctx context.Context, bytes int64) context.Context {
-	telemetry.SentBytes.Record(ctx, bytes)
-	return ctx
-}
-
-func (h *tracer) Wrote(ctx context.Context, bytes int64) context.Context {
-	telemetry.ReceivedBytes.Record(ctx, bytes)
-	return ctx
-}
-
-func (h *tracer) Error(ctx context.Context, err error) {
-	log.Printf("%v", err)
-}
diff --git a/internal/lsp/cmd/serve.go b/internal/lsp/cmd/serve.go
index 9b45f9f..275b002 100644
--- a/internal/lsp/cmd/serve.go
+++ b/internal/lsp/cmd/serve.go
@@ -20,6 +20,9 @@
 	"golang.org/x/tools/internal/jsonrpc2"
 	"golang.org/x/tools/internal/lsp"
 	"golang.org/x/tools/internal/lsp/debug"
+	"golang.org/x/tools/internal/lsp/telemetry"
+	"golang.org/x/tools/internal/lsp/telemetry/tag"
+	"golang.org/x/tools/internal/lsp/telemetry/trace"
 	"golang.org/x/tools/internal/tool"
 )
 
@@ -246,3 +249,90 @@
 	fmt.Fprintf(outx, ".\r\nParams: %s%s", params, eol)
 	fmt.Fprintf(h.out, "%s", outx.String())
 }
+
+type rpcStats struct {
+	server bool
+	method string
+	close  func()
+	start  time.Time
+}
+
+func start(ctx context.Context, server bool, method string, id *ID) (context.Context, *rpcStats) {
+	if method == "" {
+		panic("no method in rpc stats")
+	}
+	s := &rpcStats{
+		server: server,
+		method: method,
+		start:  time.Now(),
+	}
+	mode := telemetry.Outbound
+	if server {
+		mode = telemetry.Inbound
+	}
+	ctx, s.close = trace.StartSpan(ctx, method,
+		tag.Tag{Key: telemetry.Method, Value: method},
+		tag.Tag{Key: telemetry.RPCDirection, Value: mode},
+		tag.Tag{Key: telemetry.RPCID, Value: id},
+	)
+	telemetry.Started.Record(ctx, 1)
+	return ctx, s
+}
+
+func (s *rpcStats) end(ctx context.Context, err *error) {
+	if err != nil && *err != nil {
+		ctx = telemetry.StatusCode.With(ctx, "ERROR")
+	} else {
+		ctx = telemetry.StatusCode.With(ctx, "OK")
+	}
+	elapsedTime := time.Since(s.start)
+	latencyMillis := float64(elapsedTime) / float64(time.Millisecond)
+	telemetry.Latency.Record(ctx, latencyMillis)
+	s.close()
+}
+
+type statsKeyType int
+
+const statsKey = statsKeyType(0)
+
+type tracer struct {
+}
+
+func (h *tracer) Deliver(ctx context.Context, r *Request, delivered bool) bool {
+	return false
+}
+
+func (h *tracer) Cancel(ctx context.Context, conn *Conn, id ID, cancelled bool) bool {
+	return false
+}
+
+func (h *tracer) Request(ctx context.Context, direction Direction, r *WireRequest) context.Context {
+	ctx, stats := start(ctx, direction == Receive, r.Method, r.ID)
+	ctx = context.WithValue(ctx, statsKey, stats)
+	return ctx
+}
+
+func (h *tracer) Response(ctx context.Context, direction Direction, r *WireResponse) context.Context {
+	return ctx
+}
+
+func (h *tracer) Done(ctx context.Context, err error) {
+	stats, ok := ctx.Value(statsKey).(*rpcStats)
+	if ok && stats != nil {
+		stats.end(ctx, &err)
+	}
+}
+
+func (h *tracer) Read(ctx context.Context, bytes int64) context.Context {
+	telemetry.SentBytes.Record(ctx, bytes)
+	return ctx
+}
+
+func (h *tracer) Wrote(ctx context.Context, bytes int64) context.Context {
+	telemetry.ReceivedBytes.Record(ctx, bytes)
+	return ctx
+}
+
+func (h *tracer) Error(ctx context.Context, err error) {
+	log.Printf("%v", err)
+}