зеркало из https://github.com/golang/tools.git
gopls/lsp/command: add gopls.add_telemetry_counters
Gopls clients can ask gopls to increment the specified counters using this custom command. Other than communication errors or obvious violation of protocol (e.g. unmatched names/values length, type errors), this will never return an error even when some counters cannot be updated. golang.org/x/telemetry/counter APIs does not report errors. Change-Id: I21dbbba461f04819df8a7b2190fbe77547375d99 Reviewed-on: https://go-review.googlesource.com/c/tools/+/527821 Run-TryBot: Hyang-Ah Hana Kim <hyangah@gmail.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Robert Findley <rfindley@google.com>
This commit is contained in:
Родитель
940ffda009
Коммит
8421a35b9e
|
@ -41,6 +41,22 @@ Args:
|
|||
}
|
||||
```
|
||||
|
||||
### **update the given telemetry counters.**
|
||||
Identifier: `gopls.add_telemetry_counters`
|
||||
|
||||
Gopls will prepend "fwd/" to all the counters updated using this command
|
||||
to avoid conflicts with other counters gopls collects.
|
||||
|
||||
Args:
|
||||
|
||||
```
|
||||
{
|
||||
// Names and Values must have the same length.
|
||||
"Names": []string,
|
||||
"Values": []int64,
|
||||
}
|
||||
```
|
||||
|
||||
### **Apply a fix**
|
||||
Identifier: `gopls.apply_fix`
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@ import (
|
|||
"golang.org/x/tools/gopls/internal/lsp/protocol"
|
||||
"golang.org/x/tools/gopls/internal/lsp/source"
|
||||
"golang.org/x/tools/gopls/internal/span"
|
||||
"golang.org/x/tools/gopls/internal/telemetry"
|
||||
"golang.org/x/tools/gopls/internal/vulncheck"
|
||||
"golang.org/x/tools/gopls/internal/vulncheck/scan"
|
||||
"golang.org/x/tools/internal/event"
|
||||
|
@ -63,6 +64,16 @@ type commandHandler struct {
|
|||
params *protocol.ExecuteCommandParams
|
||||
}
|
||||
|
||||
// AddTelemetryCounters implements command.Interface.
|
||||
func (*commandHandler) AddTelemetryCounters(_ context.Context, args command.AddTelemetryCountersArgs) error {
|
||||
if len(args.Names) != len(args.Values) {
|
||||
return fmt.Errorf("Names and Values must have the same length")
|
||||
}
|
||||
// invalid counter update requests will be silently dropped. (no audience)
|
||||
telemetry.AddForwardedCounters(args.Names, args.Values)
|
||||
return nil
|
||||
}
|
||||
|
||||
// commandConfig configures common command set-up and execution.
|
||||
type commandConfig struct {
|
||||
async bool // whether to run the command asynchronously. Async commands can only return errors.
|
||||
|
|
|
@ -21,6 +21,7 @@ import (
|
|||
const (
|
||||
AddDependency Command = "add_dependency"
|
||||
AddImport Command = "add_import"
|
||||
AddTelemetryCounters Command = "add_telemetry_counters"
|
||||
ApplyFix Command = "apply_fix"
|
||||
CheckUpgrades Command = "check_upgrades"
|
||||
EditGoDirective Command = "edit_go_directive"
|
||||
|
@ -52,6 +53,7 @@ const (
|
|||
var Commands = []Command{
|
||||
AddDependency,
|
||||
AddImport,
|
||||
AddTelemetryCounters,
|
||||
ApplyFix,
|
||||
CheckUpgrades,
|
||||
EditGoDirective,
|
||||
|
@ -94,6 +96,12 @@ func Dispatch(ctx context.Context, params *protocol.ExecuteCommandParams, s Inte
|
|||
return nil, err
|
||||
}
|
||||
return nil, s.AddImport(ctx, a0)
|
||||
case "gopls.add_telemetry_counters":
|
||||
var a0 AddTelemetryCountersArgs
|
||||
if err := UnmarshalArgs(params.Arguments, &a0); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return nil, s.AddTelemetryCounters(ctx, a0)
|
||||
case "gopls.apply_fix":
|
||||
var a0 ApplyFixArgs
|
||||
if err := UnmarshalArgs(params.Arguments, &a0); err != nil {
|
||||
|
@ -272,6 +280,18 @@ func NewAddImportCommand(title string, a0 AddImportArgs) (protocol.Command, erro
|
|||
}, nil
|
||||
}
|
||||
|
||||
func NewAddTelemetryCountersCommand(title string, a0 AddTelemetryCountersArgs) (protocol.Command, error) {
|
||||
args, err := MarshalArgs(a0)
|
||||
if err != nil {
|
||||
return protocol.Command{}, err
|
||||
}
|
||||
return protocol.Command{
|
||||
Title: title,
|
||||
Command: "gopls.add_telemetry_counters",
|
||||
Arguments: args,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func NewApplyFixCommand(title string, a0 ApplyFixArgs) (protocol.Command, error) {
|
||||
args, err := MarshalArgs(a0)
|
||||
if err != nil {
|
||||
|
|
|
@ -189,6 +189,12 @@ type Interface interface {
|
|||
// RunGoWorkCommand: run `go work [args...]`, and apply the resulting go.work
|
||||
// edits to the current go.work file.
|
||||
RunGoWorkCommand(context.Context, RunGoWorkArgs) error
|
||||
|
||||
// AddTelemetryCounters: update the given telemetry counters.
|
||||
//
|
||||
// Gopls will prepend "fwd/" to all the counters updated using this command
|
||||
// to avoid conflicts with other counters gopls collects.
|
||||
AddTelemetryCounters(context.Context, AddTelemetryCountersArgs) error
|
||||
}
|
||||
|
||||
type RunTestsArgs struct {
|
||||
|
@ -499,3 +505,11 @@ type RunGoWorkArgs struct {
|
|||
InitFirst bool // Whether to run `go work init` first
|
||||
Args []string // Args to pass to `go work`
|
||||
}
|
||||
|
||||
// AddTelemetryCountersArgs holds the arguments to the AddCounters command
|
||||
// that updates the telemetry counters.
|
||||
type AddTelemetryCountersArgs struct {
|
||||
// Names and Values must have the same length.
|
||||
Names []string // Name of counters.
|
||||
Values []int64 // Values added to the corresponding counters. Must be non-negative.
|
||||
}
|
||||
|
|
|
@ -709,6 +709,12 @@ var GeneratedAPIJSON = &APIJSON{
|
|||
Doc: "Ask the server to add an import path to a given Go file. The method will\ncall applyEdit on the client so that clients don't have to apply the edit\nthemselves.",
|
||||
ArgDoc: "{\n\t// ImportPath is the target import path that should\n\t// be added to the URI file\n\t\"ImportPath\": string,\n\t// URI is the file that the ImportPath should be\n\t// added to\n\t\"URI\": string,\n}",
|
||||
},
|
||||
{
|
||||
Command: "gopls.add_telemetry_counters",
|
||||
Title: "update the given telemetry counters.",
|
||||
Doc: "Gopls will prepend \"fwd/\" to all the counters updated using this command\nto avoid conflicts with other counters gopls collects.",
|
||||
ArgDoc: "{\n\t// Names and Values must have the same length.\n\t\"Names\": []string,\n\t\"Values\": []int64,\n}",
|
||||
},
|
||||
{
|
||||
Command: "gopls.apply_fix",
|
||||
Title: "Apply a fix",
|
||||
|
|
|
@ -68,3 +68,15 @@ func RecordViewGoVersion(x int) {
|
|||
name := fmt.Sprintf("gopls/goversion:1.%d", x)
|
||||
counter.Inc(name)
|
||||
}
|
||||
|
||||
// AddForwardedCounters adds the given counters on behalf of clients.
|
||||
// Names and values must have the same length.
|
||||
func AddForwardedCounters(names []string, values []int64) {
|
||||
for i, n := range names {
|
||||
v := values[i]
|
||||
if n == "" || v < 0 {
|
||||
continue // Should we report an error? Who is the audience?
|
||||
}
|
||||
counter.Add("fwd/"+n, v)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,3 +17,6 @@ func RecordClientInfo(params *protocol.ParamInitialize) {
|
|||
|
||||
func RecordViewGoVersion(x int) {
|
||||
}
|
||||
|
||||
func AddForwardedCounters(names []string, values []int64) {
|
||||
}
|
||||
|
|
|
@ -18,6 +18,8 @@ import (
|
|||
"golang.org/x/telemetry/counter/countertest" // requires go1.21+
|
||||
"golang.org/x/tools/gopls/internal/bug"
|
||||
"golang.org/x/tools/gopls/internal/hooks"
|
||||
"golang.org/x/tools/gopls/internal/lsp/command"
|
||||
"golang.org/x/tools/gopls/internal/lsp/protocol"
|
||||
. "golang.org/x/tools/gopls/internal/lsp/regtest"
|
||||
)
|
||||
|
||||
|
@ -43,8 +45,9 @@ func TestTelemetry(t *testing.T) {
|
|||
Modes(Default), // must be in-process to receive the bug report below
|
||||
Settings{"showBugReports": true},
|
||||
ClientName("Visual Studio Code"),
|
||||
).Run(t, "", func(t *testing.T, env *Env) {
|
||||
).Run(t, "", func(_ *testing.T, env *Env) {
|
||||
goversion = strconv.Itoa(env.GoVersion())
|
||||
addForwardedCounters(env, []string{"vscode/linter:a"}, []int64{1})
|
||||
const desc = "got a bug"
|
||||
bug.Report(desc) // want a stack counter with the trace starting from here.
|
||||
env.Await(ShownMessage(desc))
|
||||
|
@ -52,9 +55,11 @@ func TestTelemetry(t *testing.T) {
|
|||
|
||||
// gopls/editor:client
|
||||
// gopls/goversion:1.x
|
||||
// fwd/vscode/linter:a
|
||||
for _, c := range []*counter.Counter{
|
||||
counter.New("gopls/client:" + editor),
|
||||
counter.New("gopls/goversion:1." + goversion),
|
||||
counter.New("fwd/vscode/linter:a"),
|
||||
} {
|
||||
count, err := countertest.ReadCounter(c)
|
||||
if err != nil || count != 1 {
|
||||
|
@ -75,6 +80,23 @@ func TestTelemetry(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func addForwardedCounters(env *Env, names []string, values []int64) {
|
||||
args, err := command.MarshalArgs(command.AddTelemetryCountersArgs{
|
||||
Names: names, Values: values,
|
||||
})
|
||||
if err != nil {
|
||||
env.T.Fatal(err)
|
||||
}
|
||||
var res error
|
||||
env.ExecuteCommand(&protocol.ExecuteCommandParams{
|
||||
Command: command.AddTelemetryCounters.ID(),
|
||||
Arguments: args,
|
||||
}, res)
|
||||
if res != nil {
|
||||
env.T.Errorf("%v failed - %v", command.AddTelemetryCounters.ID(), res)
|
||||
}
|
||||
}
|
||||
|
||||
func hasEntry(counts map[string]uint64, pattern string, want uint64) bool {
|
||||
for k, v := range counts {
|
||||
if strings.Contains(k, pattern) && v == want {
|
||||
|
|
Загрузка…
Ссылка в новой задаче