From 502543d2eda973a752458304a1cb8931c554aaea Mon Sep 17 00:00:00 2001 From: Ian Cottrell Date: Fri, 12 Jul 2019 16:33:10 -0400 Subject: [PATCH] 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 Reviewed-by: Rebecca Stambler --- internal/jsonrpc2/jsonrpc2.go | 93 ----------------------------------- internal/lsp/cmd/serve.go | 90 +++++++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+), 93 deletions(-) diff --git a/internal/jsonrpc2/jsonrpc2.go b/internal/jsonrpc2/jsonrpc2.go index 61aa4e212d..76919a87e5 100644 --- a/internal/jsonrpc2/jsonrpc2.go +++ b/internal/jsonrpc2/jsonrpc2.go @@ -11,14 +11,8 @@ import ( "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 @@ type Request struct { 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 @@ func marshalToRaw(obj interface{}) (*json.RawMessage, error) { 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 9b45f9f3e2..275b002031 100644 --- a/internal/lsp/cmd/serve.go +++ b/internal/lsp/cmd/serve.go @@ -20,6 +20,9 @@ import ( "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 @@ func (h *handler) log(direction jsonrpc2.Direction, id *jsonrpc2.ID, elapsed tim 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) +}