diff options
Diffstat (limited to 'internal/lsp/debug/rpc.go')
-rw-r--r-- | internal/lsp/debug/rpc.go | 239 |
1 files changed, 0 insertions, 239 deletions
diff --git a/internal/lsp/debug/rpc.go b/internal/lsp/debug/rpc.go deleted file mode 100644 index 033ee3797..000000000 --- a/internal/lsp/debug/rpc.go +++ /dev/null @@ -1,239 +0,0 @@ -// Copyright 2019 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 debug - -import ( - "context" - "fmt" - "html/template" - "net/http" - "sort" - "sync" - "time" - - "golang.org/x/tools/internal/event" - "golang.org/x/tools/internal/event/core" - "golang.org/x/tools/internal/event/export" - "golang.org/x/tools/internal/event/label" - "golang.org/x/tools/internal/lsp/debug/tag" -) - -var RPCTmpl = template.Must(template.Must(BaseTemplate.Clone()).Parse(` -{{define "title"}}RPC Information{{end}} -{{define "body"}} - <H2>Inbound</H2> - {{template "rpcSection" .Inbound}} - <H2>Outbound</H2> - {{template "rpcSection" .Outbound}} -{{end}} -{{define "rpcSection"}} - {{range .}}<P> - <b>{{.Method}}</b> {{.Started}} <a href="/trace/{{.Method}}">traces</a> ({{.InProgress}} in progress) - <br> - <i>Latency</i> {{with .Latency}}{{.Mean}} ({{.Min}}<{{.Max}}){{end}} - <i>By bucket</i> 0s {{range .Latency.Values}}{{if gt .Count 0}}<b>{{.Count}}</b> {{.Limit}} {{end}}{{end}} - <br> - <i>Received</i> {{.Received}} (avg. {{.ReceivedMean}}) - <i>Sent</i> {{.Sent}} (avg. {{.SentMean}}) - <br> - <i>Result codes</i> {{range .Codes}}{{.Key}}={{.Count}} {{end}} - </P> - {{end}} -{{end}} -`)) - -type Rpcs struct { // exported for testing - mu sync.Mutex - Inbound []*rpcStats // stats for incoming lsp rpcs sorted by method name - Outbound []*rpcStats // stats for outgoing lsp rpcs sorted by method name -} - -type rpcStats struct { - Method string - Started int64 - Completed int64 - - Latency rpcTimeHistogram - Received byteUnits - Sent byteUnits - Codes []*rpcCodeBucket -} - -type rpcTimeHistogram struct { - Sum timeUnits - Count int64 - Min timeUnits - Max timeUnits - Values []rpcTimeBucket -} - -type rpcTimeBucket struct { - Limit timeUnits - Count int64 -} - -type rpcCodeBucket struct { - Key string - Count int64 -} - -func (r *Rpcs) ProcessEvent(ctx context.Context, ev core.Event, lm label.Map) context.Context { - r.mu.Lock() - defer r.mu.Unlock() - switch { - case event.IsStart(ev): - if _, stats := r.getRPCSpan(ctx, ev); stats != nil { - stats.Started++ - } - case event.IsEnd(ev): - span, stats := r.getRPCSpan(ctx, ev) - if stats != nil { - endRPC(ctx, ev, span, stats) - } - case event.IsMetric(ev): - sent := byteUnits(tag.SentBytes.Get(lm)) - rec := byteUnits(tag.ReceivedBytes.Get(lm)) - if sent != 0 || rec != 0 { - if _, stats := r.getRPCSpan(ctx, ev); stats != nil { - stats.Sent += sent - stats.Received += rec - } - } - } - return ctx -} - -func endRPC(ctx context.Context, ev core.Event, span *export.Span, stats *rpcStats) { - // update the basic counts - stats.Completed++ - - // get and record the status code - if status := getStatusCode(span); status != "" { - var b *rpcCodeBucket - for c, entry := range stats.Codes { - if entry.Key == status { - b = stats.Codes[c] - break - } - } - if b == nil { - b = &rpcCodeBucket{Key: status} - stats.Codes = append(stats.Codes, b) - sort.Slice(stats.Codes, func(i int, j int) bool { - return stats.Codes[i].Key < stats.Codes[j].Key - }) - } - b.Count++ - } - - // calculate latency if this was an rpc span - elapsedTime := span.Finish().At().Sub(span.Start().At()) - latencyMillis := timeUnits(elapsedTime) / timeUnits(time.Millisecond) - if stats.Latency.Count == 0 { - stats.Latency.Min = latencyMillis - stats.Latency.Max = latencyMillis - } else { - if stats.Latency.Min > latencyMillis { - stats.Latency.Min = latencyMillis - } - if stats.Latency.Max < latencyMillis { - stats.Latency.Max = latencyMillis - } - } - stats.Latency.Count++ - stats.Latency.Sum += latencyMillis - for i := range stats.Latency.Values { - if stats.Latency.Values[i].Limit > latencyMillis { - stats.Latency.Values[i].Count++ - break - } - } -} - -func (r *Rpcs) getRPCSpan(ctx context.Context, ev core.Event) (*export.Span, *rpcStats) { - // get the span - span := export.GetSpan(ctx) - if span == nil { - return nil, nil - } - // use the span start event look up the correct stats block - // we do this because it prevents us matching a sub span - return span, r.getRPCStats(span.Start()) -} - -func (r *Rpcs) getRPCStats(lm label.Map) *rpcStats { - method := tag.Method.Get(lm) - if method == "" { - return nil - } - set := &r.Inbound - if tag.RPCDirection.Get(lm) != tag.Inbound { - set = &r.Outbound - } - // get the record for this method - index := sort.Search(len(*set), func(i int) bool { - return (*set)[i].Method >= method - }) - - if index < len(*set) && (*set)[index].Method == method { - return (*set)[index] - } - - old := *set - *set = make([]*rpcStats, len(old)+1) - copy(*set, old[:index]) - copy((*set)[index+1:], old[index:]) - stats := &rpcStats{Method: method} - stats.Latency.Values = make([]rpcTimeBucket, len(millisecondsDistribution)) - for i, m := range millisecondsDistribution { - stats.Latency.Values[i].Limit = timeUnits(m) - } - (*set)[index] = stats - return stats -} - -func (s *rpcStats) InProgress() int64 { return s.Started - s.Completed } -func (s *rpcStats) SentMean() byteUnits { return s.Sent / byteUnits(s.Started) } -func (s *rpcStats) ReceivedMean() byteUnits { return s.Received / byteUnits(s.Started) } - -func (h *rpcTimeHistogram) Mean() timeUnits { return h.Sum / timeUnits(h.Count) } - -func getStatusCode(span *export.Span) string { - for _, ev := range span.Events() { - if status := tag.StatusCode.Get(ev); status != "" { - return status - } - } - return "" -} - -func (r *Rpcs) getData(req *http.Request) interface{} { - return r -} - -func units(v float64, suffixes []string) string { - s := "" - for _, s = range suffixes { - n := v / 1000 - if n < 1 { - break - } - v = n - } - return fmt.Sprintf("%.2f%s", v, s) -} - -type timeUnits float64 - -func (v timeUnits) String() string { - v = v * 1000 * 1000 - return units(float64(v), []string{"ns", "μs", "ms", "s"}) -} - -type byteUnits float64 - -func (v byteUnits) String() string { - return units(float64(v), []string{"B", "KB", "MB", "GB", "TB"}) -} |