Skip to content

Commit d799eba

Browse files
committed
gopls: additional instrumentation during goimports
Add some visibility into goimports operations, by instrumenting spans in top-level imports and gocommand operations. This may be the first time we instrument non-gopls code in this way, but it should be safe as other build targets (e.g. the goimports or gopackages commands) do not set a global exporter, and therefore the cost of event instrumentation should be minimal. For golang/go#59216 Change-Id: Id2f8fe05d6b61e96cdd2d41cc43b3d4c3cf39e21 Reviewed-on: https://go-review.googlesource.com/c/tools/+/494095 Reviewed-by: Alan Donovan <[email protected]> Run-TryBot: Robert Findley <[email protected]> TryBot-Result: Gopher Robot <[email protected]> gopls-CI: kokoro <[email protected]>
1 parent a7e7dc4 commit d799eba

File tree

11 files changed

+64
-24
lines changed

11 files changed

+64
-24
lines changed

gopls/internal/lsp/cache/imports.go

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,10 @@ type importsState struct {
3131
cachedDirectoryFilters []string
3232
}
3333

34-
func (s *importsState) runProcessEnvFunc(ctx context.Context, snapshot *snapshot, fn func(*imports.Options) error) error {
34+
func (s *importsState) runProcessEnvFunc(ctx context.Context, snapshot *snapshot, fn func(context.Context, *imports.Options) error) error {
35+
ctx, done := event.Start(ctx, "cache.importsState.runProcessEnvFunc")
36+
defer done()
37+
3538
s.mu.Lock()
3639
defer s.mu.Unlock()
3740

@@ -93,7 +96,7 @@ func (s *importsState) runProcessEnvFunc(ctx context.Context, snapshot *snapshot
9396
LocalPrefix: localPrefix,
9497
}
9598

96-
if err := fn(opts); err != nil {
99+
if err := fn(ctx, opts); err != nil {
97100
return err
98101
}
99102

@@ -114,6 +117,9 @@ func (s *importsState) runProcessEnvFunc(ctx context.Context, snapshot *snapshot
114117
// the view's process environment. Assumes that the caller is holding the
115118
// importsState mutex.
116119
func populateProcessEnvFromSnapshot(ctx context.Context, pe *imports.ProcessEnv, snapshot *snapshot) error {
120+
ctx, done := event.Start(ctx, "cache.populateProcessEnvFromSnapshot")
121+
defer done()
122+
117123
if snapshot.view.Options().VerboseOutput {
118124
pe.Logf = func(format string, args ...interface{}) {
119125
event.Log(ctx, fmt.Sprintf(format, args...))
@@ -153,6 +159,9 @@ func populateProcessEnvFromSnapshot(ctx context.Context, pe *imports.ProcessEnv,
153159
}
154160

155161
func (s *importsState) refreshProcessEnv() {
162+
ctx, done := event.Start(s.ctx, "cache.importsState.refreshProcessEnv")
163+
defer done()
164+
156165
start := time.Now()
157166

158167
s.mu.Lock()
@@ -164,9 +173,9 @@ func (s *importsState) refreshProcessEnv() {
164173

165174
event.Log(s.ctx, "background imports cache refresh starting")
166175
if err := imports.PrimeCache(context.Background(), env); err == nil {
167-
event.Log(s.ctx, fmt.Sprintf("background refresh finished after %v", time.Since(start)))
176+
event.Log(ctx, fmt.Sprintf("background refresh finished after %v", time.Since(start)))
168177
} else {
169-
event.Log(s.ctx, fmt.Sprintf("background refresh finished after %v", time.Since(start)), keys.Err.Of(err))
178+
event.Log(ctx, fmt.Sprintf("background refresh finished after %v", time.Since(start)), keys.Err.Of(err))
170179
}
171180
s.mu.Lock()
172181
s.cacheRefreshDuration = time.Since(start)

gopls/internal/lsp/cache/view.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -436,7 +436,7 @@ func viewEnv(v *View) string {
436436
return buf.String()
437437
}
438438

439-
func (s *snapshot) RunProcessEnvFunc(ctx context.Context, fn func(*imports.Options) error) error {
439+
func (s *snapshot) RunProcessEnvFunc(ctx context.Context, fn func(context.Context, *imports.Options) error) error {
440440
return s.view.importsState.runProcessEnvFunc(ctx, s, fn)
441441
}
442442

gopls/internal/lsp/debug/trace.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ var TraceTmpl = template.Must(template.Must(BaseTemplate.Clone()).Parse(`
3535
3636
<H2>Recent spans (oldest first)</H2>
3737
<p>
38-
A finite number of recent span start/end times are shown below.
38+
A finite number of recent span start/end times are shown below.
3939
The nesting represents the children of a parent span (and the log events within a span).
4040
A span may appear twice: chronologically at toplevel, and nested within its parent.
4141
</p>

gopls/internal/lsp/source/completion/completion.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ type completer struct {
200200
// completionCallbacks is a list of callbacks to collect completions that
201201
// require expensive operations. This includes operations where we search
202202
// through the entire module cache.
203-
completionCallbacks []func(opts *imports.Options) error
203+
completionCallbacks []func(context.Context, *imports.Options) error
204204

205205
// surrounding describes the identifier surrounding the position.
206206
surrounding *Selection
@@ -887,7 +887,7 @@ func (c *completer) populateImportCompletions(ctx context.Context, searchImport
887887
})
888888
}
889889

890-
c.completionCallbacks = append(c.completionCallbacks, func(opts *imports.Options) error {
890+
c.completionCallbacks = append(c.completionCallbacks, func(ctx context.Context, opts *imports.Options) error {
891891
return imports.GetImportPaths(ctx, searchImports, prefix, c.filename, c.pkg.GetTypes().Name(), opts.Env)
892892
})
893893
return nil
@@ -1195,7 +1195,7 @@ func (c *completer) selector(ctx context.Context, sel *ast.SelectorExpr) error {
11951195
// Rank import paths as goimports would.
11961196
var relevances map[string]float64
11971197
if len(paths) > 0 {
1198-
if err := c.snapshot.RunProcessEnvFunc(ctx, func(opts *imports.Options) error {
1198+
if err := c.snapshot.RunProcessEnvFunc(ctx, func(ctx context.Context, opts *imports.Options) error {
11991199
var err error
12001200
relevances, err = imports.ScoreImportPaths(ctx, opts.Env, paths)
12011201
return err
@@ -1342,7 +1342,7 @@ func (c *completer) selector(ctx context.Context, sel *ast.SelectorExpr) error {
13421342
}
13431343
}
13441344

1345-
c.completionCallbacks = append(c.completionCallbacks, func(opts *imports.Options) error {
1345+
c.completionCallbacks = append(c.completionCallbacks, func(ctx context.Context, opts *imports.Options) error {
13461346
defer cancel()
13471347
return imports.GetPackageExports(ctx, add, id.Name, c.filename, c.pkg.GetTypes().Name(), opts.Env)
13481348
})
@@ -1635,7 +1635,7 @@ func (c *completer) unimportedPackages(ctx context.Context, seen map[string]stru
16351635
// Rank candidates using goimports' algorithm.
16361636
var relevances map[string]float64
16371637
if len(paths) != 0 {
1638-
if err := c.snapshot.RunProcessEnvFunc(ctx, func(opts *imports.Options) error {
1638+
if err := c.snapshot.RunProcessEnvFunc(ctx, func(ctx context.Context, opts *imports.Options) error {
16391639
var err error
16401640
relevances, err = imports.ScoreImportPaths(ctx, opts.Env, paths)
16411641
return err
@@ -1708,7 +1708,7 @@ func (c *completer) unimportedPackages(ctx context.Context, seen map[string]stru
17081708
})
17091709
count++
17101710
}
1711-
c.completionCallbacks = append(c.completionCallbacks, func(opts *imports.Options) error {
1711+
c.completionCallbacks = append(c.completionCallbacks, func(ctx context.Context, opts *imports.Options) error {
17121712
defer cancel()
17131713
return imports.GetAllCandidates(ctx, add, prefix, c.filename, c.pkg.GetTypes().Name(), opts.Env)
17141714
})

gopls/internal/lsp/source/format.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -116,8 +116,8 @@ func AllImportsFixes(ctx context.Context, snapshot Snapshot, fh FileHandle) (all
116116
if err != nil {
117117
return nil, nil, err
118118
}
119-
if err := snapshot.RunProcessEnvFunc(ctx, func(opts *imports.Options) error {
120-
allFixEdits, editsPerFix, err = computeImportEdits(snapshot, pgf, opts)
119+
if err := snapshot.RunProcessEnvFunc(ctx, func(ctx context.Context, opts *imports.Options) error {
120+
allFixEdits, editsPerFix, err = computeImportEdits(ctx, snapshot, pgf, opts)
121121
return err
122122
}); err != nil {
123123
return nil, nil, fmt.Errorf("AllImportsFixes: %v", err)
@@ -127,11 +127,11 @@ func AllImportsFixes(ctx context.Context, snapshot Snapshot, fh FileHandle) (all
127127

128128
// computeImportEdits computes a set of edits that perform one or all of the
129129
// necessary import fixes.
130-
func computeImportEdits(snapshot Snapshot, pgf *ParsedGoFile, options *imports.Options) (allFixEdits []protocol.TextEdit, editsPerFix []*ImportFix, err error) {
130+
func computeImportEdits(ctx context.Context, snapshot Snapshot, pgf *ParsedGoFile, options *imports.Options) (allFixEdits []protocol.TextEdit, editsPerFix []*ImportFix, err error) {
131131
filename := pgf.URI.Filename()
132132

133133
// Build up basic information about the original file.
134-
allFixes, err := imports.FixImports(filename, pgf.Src, options)
134+
allFixes, err := imports.FixImports(ctx, filename, pgf.Src, options)
135135
if err != nil {
136136
return nil, nil, err
137137
}

gopls/internal/lsp/source/known_packages.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ func KnownPackagePaths(ctx context.Context, snapshot Snapshot, fh FileHandle) ([
8585
}
8686

8787
// Augment the set by invoking the goimports algorithm.
88-
if err := snapshot.RunProcessEnvFunc(ctx, func(o *imports.Options) error {
88+
if err := snapshot.RunProcessEnvFunc(ctx, func(ctx context.Context, o *imports.Options) error {
8989
ctx, cancel := context.WithTimeout(ctx, time.Millisecond*80)
9090
defer cancel()
9191
var seenMu sync.Mutex

gopls/internal/lsp/source/view.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ type Snapshot interface {
117117

118118
// RunProcessEnvFunc runs fn with the process env for this snapshot's view.
119119
// Note: the process env contains cached module and filesystem state.
120-
RunProcessEnvFunc(ctx context.Context, fn func(*imports.Options) error) error
120+
RunProcessEnvFunc(ctx context.Context, fn func(context.Context, *imports.Options) error) error
121121

122122
// ModFiles are the go.mod files enclosed in the snapshot's view and known
123123
// to the snapshot.

internal/gocommand/invoke.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ import (
2424
exec "golang.org/x/sys/execabs"
2525

2626
"golang.org/x/tools/internal/event"
27+
"golang.org/x/tools/internal/event/keys"
28+
"golang.org/x/tools/internal/event/label"
29+
"golang.org/x/tools/internal/event/tag"
2730
)
2831

2932
// An Runner will run go command invocations and serialize
@@ -53,23 +56,38 @@ func (runner *Runner) initialize() {
5356
// 1.14: go: updating go.mod: existing contents have changed since last read
5457
var modConcurrencyError = regexp.MustCompile(`go:.*go.mod.*contents have changed`)
5558

59+
// verb is an event label for the go command verb.
60+
var verb = keys.NewString("verb", "go command verb")
61+
62+
func invLabels(inv Invocation) []label.Label {
63+
return []label.Label{verb.Of(inv.Verb), tag.Directory.Of(inv.WorkingDir)}
64+
}
65+
5666
// Run is a convenience wrapper around RunRaw.
5767
// It returns only stdout and a "friendly" error.
5868
func (runner *Runner) Run(ctx context.Context, inv Invocation) (*bytes.Buffer, error) {
69+
ctx, done := event.Start(ctx, "gocommand.Runner.Run", invLabels(inv)...)
70+
defer done()
71+
5972
stdout, _, friendly, _ := runner.RunRaw(ctx, inv)
6073
return stdout, friendly
6174
}
6275

6376
// RunPiped runs the invocation serially, always waiting for any concurrent
6477
// invocations to complete first.
6578
func (runner *Runner) RunPiped(ctx context.Context, inv Invocation, stdout, stderr io.Writer) error {
79+
ctx, done := event.Start(ctx, "gocommand.Runner.RunPiped", invLabels(inv)...)
80+
defer done()
81+
6682
_, err := runner.runPiped(ctx, inv, stdout, stderr)
6783
return err
6884
}
6985

7086
// RunRaw runs the invocation, serializing requests only if they fight over
7187
// go.mod changes.
7288
func (runner *Runner) RunRaw(ctx context.Context, inv Invocation) (*bytes.Buffer, *bytes.Buffer, error, error) {
89+
ctx, done := event.Start(ctx, "gocommand.Runner.RunRaw", invLabels(inv)...)
90+
defer done()
7391
// Make sure the runner is always initialized.
7492
runner.initialize()
7593

internal/imports/fix.go

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import (
2626
"unicode/utf8"
2727

2828
"golang.org/x/tools/go/ast/astutil"
29+
"golang.org/x/tools/internal/event"
2930
"golang.org/x/tools/internal/gocommand"
3031
"golang.org/x/tools/internal/gopathwalk"
3132
)
@@ -543,7 +544,7 @@ func (p *pass) addCandidate(imp *ImportInfo, pkg *packageInfo) {
543544
var fixImports = fixImportsDefault
544545

545546
func fixImportsDefault(fset *token.FileSet, f *ast.File, filename string, env *ProcessEnv) error {
546-
fixes, err := getFixes(fset, f, filename, env)
547+
fixes, err := getFixes(context.Background(), fset, f, filename, env)
547548
if err != nil {
548549
return err
549550
}
@@ -553,7 +554,7 @@ func fixImportsDefault(fset *token.FileSet, f *ast.File, filename string, env *P
553554

554555
// getFixes gets the import fixes that need to be made to f in order to fix the imports.
555556
// It does not modify the ast.
556-
func getFixes(fset *token.FileSet, f *ast.File, filename string, env *ProcessEnv) ([]*ImportFix, error) {
557+
func getFixes(ctx context.Context, fset *token.FileSet, f *ast.File, filename string, env *ProcessEnv) ([]*ImportFix, error) {
557558
abs, err := filepath.Abs(filename)
558559
if err != nil {
559560
return nil, err
@@ -607,7 +608,7 @@ func getFixes(fset *token.FileSet, f *ast.File, filename string, env *ProcessEnv
607608

608609
// Go look for candidates in $GOPATH, etc. We don't necessarily load
609610
// the real exports of sibling imports, so keep assuming their contents.
610-
if err := addExternalCandidates(p, p.missingRefs, filename); err != nil {
611+
if err := addExternalCandidates(ctx, p, p.missingRefs, filename); err != nil {
611612
return nil, err
612613
}
613614

@@ -1055,7 +1056,10 @@ type scanCallback struct {
10551056
exportsLoaded func(pkg *pkg, exports []string)
10561057
}
10571058

1058-
func addExternalCandidates(pass *pass, refs references, filename string) error {
1059+
func addExternalCandidates(ctx context.Context, pass *pass, refs references, filename string) error {
1060+
ctx, done := event.Start(ctx, "imports.addExternalCandidates")
1061+
defer done()
1062+
10591063
var mu sync.Mutex
10601064
found := make(map[string][]pkgDistance)
10611065
callback := &scanCallback{

internal/imports/imports.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ package imports
1111
import (
1212
"bufio"
1313
"bytes"
14+
"context"
1415
"fmt"
1516
"go/ast"
1617
"go/format"
@@ -23,6 +24,7 @@ import (
2324
"strings"
2425

2526
"golang.org/x/tools/go/ast/astutil"
27+
"golang.org/x/tools/internal/event"
2628
)
2729

2830
// Options is golang.org/x/tools/imports.Options with extra internal-only options.
@@ -66,14 +68,17 @@ func Process(filename string, src []byte, opt *Options) (formatted []byte, err e
6668
//
6769
// Note that filename's directory influences which imports can be chosen,
6870
// so it is important that filename be accurate.
69-
func FixImports(filename string, src []byte, opt *Options) (fixes []*ImportFix, err error) {
71+
func FixImports(ctx context.Context, filename string, src []byte, opt *Options) (fixes []*ImportFix, err error) {
72+
ctx, done := event.Start(ctx, "imports.FixImports")
73+
defer done()
74+
7075
fileSet := token.NewFileSet()
7176
file, _, err := parse(fileSet, filename, src, opt)
7277
if err != nil {
7378
return nil, err
7479
}
7580

76-
return getFixes(fileSet, file, filename, opt.Env)
81+
return getFixes(ctx, fileSet, file, filename, opt.Env)
7782
}
7883

7984
// ApplyFixes applies all of the fixes to the file and formats it. extraMode

internal/imports/mod.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919
"strings"
2020

2121
"golang.org/x/mod/module"
22+
"golang.org/x/tools/internal/event"
2223
"golang.org/x/tools/internal/gocommand"
2324
"golang.org/x/tools/internal/gopathwalk"
2425
)
@@ -424,6 +425,9 @@ func (r *ModuleResolver) loadPackageNames(importPaths []string, srcDir string) (
424425
}
425426

426427
func (r *ModuleResolver) scan(ctx context.Context, callback *scanCallback) error {
428+
ctx, done := event.Start(ctx, "imports.ModuleResolver.scan")
429+
defer done()
430+
427431
if err := r.init(); err != nil {
428432
return err
429433
}

0 commit comments

Comments
 (0)