import (
"cmd/go/internal/base"
+ "cmd/go/internal/cfg"
"flag"
+ "go/build"
"internal/diff"
"os"
"slices"
// for all subcommands, but it's also valid to invoke go help without any arguments.
counters = append(counters, "go/subcommand:help")
for _, cmd := range base.Go.Commands {
- counters = append(counters, cmdcounters(nil, cmd)...)
+ cmdcounters, err := cmdcounters(nil, cmd)
+ if err != nil {
+ t.Fatal(err)
+ }
+ counters = append(counters, cmdcounters...)
}
counters = append(counters, base.RegisteredCounterNames()...)
return counters
}
-func cmdcounters(previous []string, cmd *base.Command) []string {
+func cmdcounters(previous []string, cmd *base.Command) ([]string, error) {
const subcommandPrefix = "go/subcommand:"
const flagPrefix = "go/flag:"
var counters []string
previousComponent += "-"
}
if cmd.Runnable() {
+ if cmd.Name() == "tool" {
+ // TODO(matloob): Do we expect the same tools to be present on all
+ // platforms/configurations? Should we only run this on certain
+ // platforms?
+ tools, err := toolNames()
+ if err != nil {
+ return nil, err
+ }
+ for _, t := range tools {
+ counters = append(counters, subcommandPrefix+previousComponent+cmd.Name()+"-"+t)
+ }
+ counters = append(counters, subcommandPrefix+previousComponent+cmd.Name()+"-unknown")
+ }
counters = append(counters, subcommandPrefix+previousComponent+cmd.Name())
}
counters = append(counters, flagscounters(flagPrefix+previousComponent+cmd.Name()+"-", cmd.Flag)...)
counters = append(counters, subcommandPrefix+"help-"+previousComponent+cmd.Name())
for _, subcmd := range cmd.Commands {
- counters = append(counters, cmdcounters(append(slices.Clone(previous), cmd.Name()), subcmd)...)
+ subcmdcounters, err := cmdcounters(append(slices.Clone(previous), cmd.Name()), subcmd)
+ if err != nil {
+ return nil, err
+ }
+ counters = append(counters, subcmdcounters...)
}
- return counters
+ return counters, nil
+}
+
+// toolNames returns the list of basenames of executables in the tool dir.
+func toolNames() ([]string, error) {
+ entries, err := os.ReadDir(build.ToolDir)
+ if err != nil {
+ return nil, err
+ }
+ var names []string
+ for _, e := range entries {
+ if e.IsDir() {
+ continue
+ }
+ name := strings.TrimSuffix(e.Name(), cfg.ToolExeSuffix())
+ names = append(names, name)
+ }
+ return names, nil
}
package tool
import (
+ "cmd/internal/telemetry"
"context"
"encoding/json"
"flag"
func runTool(ctx context.Context, cmd *base.Command, args []string) {
if len(args) == 0 {
+ telemetry.Inc("go/subcommand:tool")
listTools()
return
}
//
// If the dist tool does not exist, impersonate this command.
if impersonateDistList(args[2:]) {
+ // If it becomes necessary, we could increment an additional counter to indicate
+ // that we're impersonating dist list if knowing that becomes important?
+ telemetry.Inc("go/subcommand:tool-dist")
return
}
}
+ telemetry.Inc("go/subcommand:tool-unknown")
// Emit the usual error for the missing tool.
_ = base.Tool(toolName)
+ } else {
+ // Increment a counter for the tool subcommand with the tool name.
+ telemetry.Inc("go/subcommand:tool-" + toolName)
}
if toolN {
base.SetExitStatus(2)
base.Exit()
}
- telemetry.Inc("go/subcommand:" + strings.ReplaceAll(cfg.CmdName, " ", "-"))
+ // Increment a subcommand counter for the subcommand we're running.
+ // Don't increment the counter for the tool subcommand here: we'll
+ // increment in the tool subcommand's Run function because we need
+ // to do the flag processing in invoke first.
+ if cfg.CmdName != "tool" {
+ telemetry.Inc("go/subcommand:" + strings.ReplaceAll(cfg.CmdName, " ", "-"))
+ }
invoke(cmd, args[used-1:])
base.Exit()
}
go/flag:test-work
go/flag:test-x
go/subcommand:help-test
+go/subcommand:tool-addr2line
+go/subcommand:tool-asm
+go/subcommand:tool-buildid
+go/subcommand:tool-cgo
+go/subcommand:tool-compile
+go/subcommand:tool-covdata
+go/subcommand:tool-cover
+go/subcommand:tool-dist
+go/subcommand:tool-distpack
+go/subcommand:tool-doc
+go/subcommand:tool-fix
+go/subcommand:tool-link
+go/subcommand:tool-nm
+go/subcommand:tool-objdump
+go/subcommand:tool-pack
+go/subcommand:tool-pprof
+go/subcommand:tool-preprofile
+go/subcommand:tool-test2json
+go/subcommand:tool-trace
+go/subcommand:tool-vet
+go/subcommand:tool-unknown
go/subcommand:tool
go/flag:tool-C
go/flag:tool-n