зеркало из https://github.com/golang/tools.git
internal/lsp/debug: add a facility to track known bugs
Sometimes users report issues related to edge cases in Gopls that aren't reproducible. In some of these cases, we end up guarding against conditions that shouldn't be possible, which is an unfortunately fragile solution. Add a new debug.Bug function to both annotate such branches as known bugs, and help find them when they reoccur. For now this just records them in the debug server, but in the future we could send the user a message to the effect of "hey, a known bug has occurred" for debug builds of gopls. Also included are some minor cosmetic fixes. Change-Id: I95df0caf2c81f430661cabd573ce8e338fa69934 Reviewed-on: https://go-review.googlesource.com/c/tools/+/318369 Trust: Robert Findley <rfindley@google.com> Run-TryBot: Robert Findley <rfindley@google.com> gopls-CI: kokoro <noreply+kokoro@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Rebecca Stambler <rstambler@golang.org>
This commit is contained in:
Родитель
5a667787ee
Коммит
fa05545715
|
@ -1,6 +1,7 @@
|
|||
// Copyright 2021 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 misc
|
||||
|
||||
import (
|
||||
|
|
|
@ -27,13 +27,13 @@ type Exporter struct {
|
|||
metrics []metric.Data
|
||||
}
|
||||
|
||||
func (e *Exporter) ProcessEvent(ctx context.Context, ev core.Event, ln label.Map) context.Context {
|
||||
func (e *Exporter) ProcessEvent(ctx context.Context, ev core.Event, lm label.Map) context.Context {
|
||||
if !event.IsMetric(ev) {
|
||||
return ctx
|
||||
}
|
||||
e.mu.Lock()
|
||||
defer e.mu.Unlock()
|
||||
metrics := metric.Entries.Get(ln).([]metric.Data)
|
||||
metrics := metric.Entries.Get(lm).([]metric.Data)
|
||||
for _, data := range metrics {
|
||||
name := data.Handle()
|
||||
// We keep the metrics in name sorted order so the page is stable and easy
|
||||
|
|
|
@ -20,6 +20,7 @@ import (
|
|||
"path/filepath"
|
||||
"runtime"
|
||||
rpprof "runtime/pprof"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
|
@ -76,6 +77,46 @@ type State struct {
|
|||
mu sync.Mutex
|
||||
clients []*Client
|
||||
servers []*Server
|
||||
|
||||
// bugs maps bug description -> formatted event
|
||||
bugs map[string]string
|
||||
}
|
||||
|
||||
func Bug(ctx context.Context, desc string) {
|
||||
labels := [3]label.Label{
|
||||
tag.Bug.Of(desc),
|
||||
}
|
||||
_, file, line, ok := runtime.Caller(1)
|
||||
if ok {
|
||||
labels[1] = tag.Callsite.Of(fmt.Sprintf("%s:%d", file, line))
|
||||
}
|
||||
core.Export(ctx, core.MakeEvent(labels, nil))
|
||||
}
|
||||
|
||||
type bug struct {
|
||||
Description, Event string
|
||||
}
|
||||
|
||||
func (st *State) Bugs() []bug {
|
||||
st.mu.Lock()
|
||||
defer st.mu.Unlock()
|
||||
var bugs []bug
|
||||
for k, v := range st.bugs {
|
||||
bugs = append(bugs, bug{k, v})
|
||||
}
|
||||
sort.Slice(bugs, func(i, j int) bool {
|
||||
return bugs[i].Description < bugs[j].Description
|
||||
})
|
||||
return bugs
|
||||
}
|
||||
|
||||
func (st *State) recordBug(description, event string) {
|
||||
st.mu.Lock()
|
||||
defer st.mu.Unlock()
|
||||
if st.bugs == nil {
|
||||
st.bugs = make(map[string]string)
|
||||
}
|
||||
st.bugs[description] = event
|
||||
}
|
||||
|
||||
// Caches returns the set of Cache objects currently being served.
|
||||
|
@ -338,7 +379,7 @@ func (i *Instance) AddService(s protocol.Server, session *cache.Session) {
|
|||
stdlog.Printf("unable to find a Client to add the protocol.Server to")
|
||||
}
|
||||
|
||||
func getMemory(r *http.Request) interface{} {
|
||||
func getMemory(_ *http.Request) interface{} {
|
||||
var m runtime.MemStats
|
||||
runtime.ReadMemStats(&m)
|
||||
return m
|
||||
|
@ -636,6 +677,9 @@ func makeInstanceExporter(i *Instance) event.Exporter {
|
|||
}
|
||||
}
|
||||
}
|
||||
if b := tag.Bug.Get(ev); b != "" {
|
||||
i.State.recordBug(b, fmt.Sprintf("%v", ev))
|
||||
}
|
||||
return ctx
|
||||
}
|
||||
// StdTrace must be above export.Spans below (by convention, export
|
||||
|
@ -766,6 +810,8 @@ var MainTmpl = template.Must(template.Must(BaseTemplate.Clone()).Parse(`
|
|||
<ul>{{range .State.Clients}}<li>{{template "clientlink" .Session.ID}}</li>{{end}}</ul>
|
||||
<h2>Servers</h2>
|
||||
<ul>{{range .State.Servers}}<li>{{template "serverlink" .ID}}</li>{{end}}</ul>
|
||||
<h2>Known bugs encountered</h2>
|
||||
<dl>{{range .State.Bugs}}<dt>{{.Description}}</dt><dd>{{.Event}}</dd>{{end}}</dl>
|
||||
{{end}}
|
||||
`))
|
||||
|
||||
|
|
|
@ -43,6 +43,10 @@ var (
|
|||
ClientID = keys.NewString("client_id", "")
|
||||
|
||||
Level = keys.NewInt("level", "The logging level")
|
||||
|
||||
// Bug tracks occurrences of known bugs in the server.
|
||||
Bug = keys.NewString("bug", "A bug has occurred")
|
||||
Callsite = keys.NewString("callsite", "gopls function call site")
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
Загрузка…
Ссылка в новой задаче