From 411f1cf43357aad681b6e3e6341f73f558cbdd2e Mon Sep 17 00:00:00 2001 From: George Adams Date: Thu, 12 Mar 2026 14:23:38 +0000 Subject: [PATCH 1/2] Add msgo/modulehash telemetry counter Emit a SHA-256 hash of the main module path as a numeric telemetry counter during build, install, and run commands. The module path is hashed to avoid transmitting potentially sensitive names. Re-vendor go-infra telemetry to pick up wildcard prefix support in the upload filter. --- .../0001-Vendor-external-dependencies.patch | 84 +++++++++++++------ patches/0009-Add-appinsights-telemetry.patch | 52 ++++++++++-- 2 files changed, 102 insertions(+), 34 deletions(-) diff --git a/patches/0001-Vendor-external-dependencies.patch b/patches/0001-Vendor-external-dependencies.patch index c76de32cb4a..e98e2f13801 100644 --- a/patches/0001-Vendor-external-dependencies.patch +++ b/patches/0001-Vendor-external-dependencies.patch @@ -15,7 +15,7 @@ Use a 'go' that was recently built by the current branch to ensure stable result .../microsoft/go-infra/telemetry/README.md | 9 + .../go-infra/telemetry/config/LICENSE | 21 + .../go-infra/telemetry/config/config.go | 11 + - .../go-infra/telemetry/config/config.json | 73 + + .../go-infra/telemetry/config/config.json | 76 + .../go-infra/telemetry/counter/counter.go | 63 + .../telemetry/internal/appinsights/README.md | 12 + .../telemetry/internal/appinsights/client.go | 169 ++ @@ -27,10 +27,10 @@ Use a 'go' that was recently built by the current branch to ensure stable result .../telemetry/internal/appinsights/package.go | 13 + .../internal/appinsights/telemetrycontext.go | 44 + .../internal/appinsights/transmitter.go | 172 ++ - .../telemetry/internal/config/config.go | 63 + + .../telemetry/internal/config/config.go | 78 + .../telemetry/internal/telemetry/proginfo.go | 43 + .../telemetry/internal/telemetry/telemetry.go | 32 + - .../microsoft/go-infra/telemetry/telemetry.go | 125 + + .../microsoft/go-infra/telemetry/telemetry.go | 141 + src/cmd/vendor/modules.txt | 11 + src/crypto/internal/backend/deps_ignore.go | 22 + src/go.mod | 6 + @@ -283,7 +283,7 @@ Use a 'go' that was recently built by the current branch to ensure stable result .../internal/subtle/aliasing.go | 32 + .../internal/sysdll/sys_windows.go | 55 + src/vendor/modules.txt | 23 + - 275 files changed, 34387 insertions(+), 7 deletions(-) + 275 files changed, 34421 insertions(+), 7 deletions(-) create mode 100644 src/cmd/internal/telemetry/counter/deps_ignore.go create mode 100644 src/cmd/vendor/github.com/microsoft/go-infra/telemetry/LICENSE create mode 100644 src/cmd/vendor/github.com/microsoft/go-infra/telemetry/README.md @@ -553,30 +553,30 @@ Use a 'go' that was recently built by the current branch to ensure stable result create mode 100644 src/vendor/github.com/microsoft/go-crypto-winnative/internal/sysdll/sys_windows.go diff --git a/src/cmd/go.mod b/src/cmd/go.mod -index 3bc983397186a6..6556bfdbe3f0a4 100644 +index 3bc983397186a6..ec6b9b98c21093 100644 --- a/src/cmd/go.mod +++ b/src/cmd/go.mod @@ -4,6 +4,8 @@ go 1.27 require ( github.com/google/pprof v0.0.0-20260115054156-294ebfa9ad83 -+ github.com/microsoft/go-infra/telemetry v0.0.0-20260128082012-a1498e2b57dd -+ github.com/microsoft/go-infra/telemetry/config v0.0.0-20260128082012-a1498e2b57dd ++ github.com/microsoft/go-infra/telemetry v0.0.0-20260312141037-c07bb95c5917 ++ github.com/microsoft/go-infra/telemetry/config v0.0.0-20260312141037-c07bb95c5917 golang.org/x/arch v0.23.1-0.20260109160903-657d90bd6695 golang.org/x/build v0.0.0-20260122183339-3ba88df37c64 golang.org/x/mod v0.32.0 diff --git a/src/cmd/go.sum b/src/cmd/go.sum -index 224585feb6332d..ebf6a4c11e165e 100644 +index 224585feb6332d..96c37f20e57bc5 100644 --- a/src/cmd/go.sum +++ b/src/cmd/go.sum @@ -4,6 +4,10 @@ github.com/google/pprof v0.0.0-20260115054156-294ebfa9ad83 h1:z2ogiKUYzX5Is6zr/v github.com/google/pprof v0.0.0-20260115054156-294ebfa9ad83/go.mod h1:MxpfABSjhmINe3F1It9d+8exIHFvUqtLIRCdOGNXqiI= github.com/ianlancetaylor/demangle v0.0.0-20250417193237-f615e6bd150b h1:ogbOPx86mIhFy764gGkqnkFC8m5PJA7sPzlk9ppLVQA= github.com/ianlancetaylor/demangle v0.0.0-20250417193237-f615e6bd150b/go.mod h1:gx7rwoVhcfuVKG5uya9Hs3Sxj7EIvldVofAWIUtGouw= -+github.com/microsoft/go-infra/telemetry v0.0.0-20260128082012-a1498e2b57dd h1:XE6HF7LVJ7/gD0mPMaIHJak0IFP683EUBzqx6+HxPu8= -+github.com/microsoft/go-infra/telemetry v0.0.0-20260128082012-a1498e2b57dd/go.mod h1:XQP+NhZgM1i1+asOSnAFPRzv2HhQibhk6k6FIllx8/Y= -+github.com/microsoft/go-infra/telemetry/config v0.0.0-20260128082012-a1498e2b57dd h1:vNA5PIOnvHfH7O9GUOZXKUakJpdE7+PzsF641y7Zly0= -+github.com/microsoft/go-infra/telemetry/config v0.0.0-20260128082012-a1498e2b57dd/go.mod h1:t6u8QcO4tExYT4+NEB0XqR0ObiUvLe0D8ZpxFobGuA8= ++github.com/microsoft/go-infra/telemetry v0.0.0-20260312141037-c07bb95c5917 h1:C3MvovclbWFMB95gZDjzvCZNncE8honbZqE3vKO+kuM= ++github.com/microsoft/go-infra/telemetry v0.0.0-20260312141037-c07bb95c5917/go.mod h1:XQP+NhZgM1i1+asOSnAFPRzv2HhQibhk6k6FIllx8/Y= ++github.com/microsoft/go-infra/telemetry/config v0.0.0-20260312141037-c07bb95c5917 h1:AXkUpbnzvUa0GbgNNMNIwKySPChjlJJw1sxMEXYoHII= ++github.com/microsoft/go-infra/telemetry/config v0.0.0-20260312141037-c07bb95c5917/go.mod h1:t6u8QcO4tExYT4+NEB0XqR0ObiUvLe0D8ZpxFobGuA8= github.com/yuin/goldmark v1.6.0 h1:boZcn2GTjpsynOsC0iJHnBWa4Bi0qzfJjthwauItG68= github.com/yuin/goldmark v1.6.0/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= golang.org/x/arch v0.23.1-0.20260109160903-657d90bd6695 h1:q45HsUyFzBjBk4mHGgUewJf6KKOkNiWB8wMx0X6elyA= @@ -691,10 +691,10 @@ index 00000000000000..044268a046a54d +var Config []byte diff --git a/src/cmd/vendor/github.com/microsoft/go-infra/telemetry/config/config.json b/src/cmd/vendor/github.com/microsoft/go-infra/telemetry/config/config.json new file mode 100644 -index 00000000000000..76053296e82470 +index 00000000000000..dceac4af7a8883 --- /dev/null +++ b/src/cmd/vendor/github.com/microsoft/go-infra/telemetry/config/config.json -@@ -0,0 +1,73 @@ +@@ -0,0 +1,76 @@ +{ + "GOOS": [ + "aix", @@ -763,6 +763,9 @@ index 00000000000000..76053296e82470 + }, + { + "Name": "go/cgo:{enabled,disabled}" ++ }, ++ { ++ "Name": "msgo/modulehash:*" + } + ] + } @@ -1889,10 +1892,10 @@ index 00000000000000..0299c87c81cb41 +} diff --git a/src/cmd/vendor/github.com/microsoft/go-infra/telemetry/internal/config/config.go b/src/cmd/vendor/github.com/microsoft/go-infra/telemetry/internal/config/config.go new file mode 100644 -index 00000000000000..7980b1505b2caa +index 00000000000000..1cb6c22a7bcd72 --- /dev/null +++ b/src/cmd/vendor/github.com/microsoft/go-infra/telemetry/internal/config/config.go -@@ -0,0 +1,63 @@ +@@ -0,0 +1,78 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + @@ -1942,8 +1945,12 @@ index 00000000000000..7980b1505b2caa +} + +// Expand takes a counter defined with buckets and expands it into distinct -+// strings for each bucket. ++// strings for each bucket. If the counter ends with "*" (e.g. "go/package:*"), ++// it is returned as-is to indicate a wildcard prefix match. +func Expand(counter string) []string { ++ if strings.HasSuffix(counter, "*") { ++ return []string{counter} ++ } + prefix, rest, hasBuckets := strings.Cut(counter, "{") + var counters []string + if hasBuckets { @@ -1956,6 +1963,17 @@ index 00000000000000..7980b1505b2caa + } + return counters +} ++ ++// IsWildcard reports whether the counter name is a wildcard pattern. ++func IsWildcard(name string) bool { ++ return strings.HasSuffix(name, "*") ++} ++ ++// WildcardPrefix returns the prefix of a wildcard counter name, ++// stripping the trailing "*". ++func WildcardPrefix(name string) string { ++ return strings.TrimSuffix(name, "*") ++} diff --git a/src/cmd/vendor/github.com/microsoft/go-infra/telemetry/internal/telemetry/proginfo.go b/src/cmd/vendor/github.com/microsoft/go-infra/telemetry/internal/telemetry/proginfo.go new file mode 100644 index 00000000000000..f6183bdf3dbf1b @@ -2045,10 +2063,10 @@ index 00000000000000..02d112edb8ad3e +} diff --git a/src/cmd/vendor/github.com/microsoft/go-infra/telemetry/telemetry.go b/src/cmd/vendor/github.com/microsoft/go-infra/telemetry/telemetry.go new file mode 100644 -index 00000000000000..d592037b570130 +index 00000000000000..dd1e614cfbd654 --- /dev/null +++ b/src/cmd/vendor/github.com/microsoft/go-infra/telemetry/telemetry.go -@@ -0,0 +1,125 @@ +@@ -0,0 +1,141 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + @@ -2061,6 +2079,7 @@ index 00000000000000..d592037b570130 + "runtime" + "runtime/debug" + "slices" ++ "strings" + "time" + + "github.com/microsoft/go-infra/telemetry/internal/appinsights" @@ -2102,6 +2121,7 @@ index 00000000000000..d592037b570130 +} + +var countersToUpload map[string]struct{} ++var wildcardPrefixes []string + +// Start initializes telemetry using the specified configuration. +func Start(cfg Config) { @@ -2138,12 +2158,19 @@ index 00000000000000..d592037b570130 + return // Program not configured for telemetry + } + countersToUpload = make(map[string]struct{}) ++ wildcardPrefixes = nil + for _, c := range uploadConfig.Programs[progIdx].Counters { + if c.Name == "" { + continue // Skip empty counter names + } + for _, e := range config.Expand(c.Name) { -+ countersToUpload[e] = struct{}{} ++ if config.IsWildcard(e) { ++ if prefix := config.WildcardPrefix(e); prefix != "" { ++ wildcardPrefixes = append(wildcardPrefixes, prefix) ++ } ++ } else { ++ countersToUpload[e] = struct{}{} ++ } + } + } + @@ -2171,18 +2198,25 @@ index 00000000000000..d592037b570130 +} + +func uploadFilter(name string) bool { -+ _, ok := countersToUpload[name] -+ return ok ++ if _, ok := countersToUpload[name]; ok { ++ return true ++ } ++ for _, prefix := range wildcardPrefixes { ++ if strings.HasPrefix(name, prefix) { ++ return true ++ } ++ } ++ return false +} diff --git a/src/cmd/vendor/modules.txt b/src/cmd/vendor/modules.txt -index ceed574b32b507..e29e38f7da3cb3 100644 +index ceed574b32b507..1d36e2eaaef27e 100644 --- a/src/cmd/vendor/modules.txt +++ b/src/cmd/vendor/modules.txt @@ -16,6 +16,17 @@ github.com/google/pprof/third_party/svgpan # github.com/ianlancetaylor/demangle v0.0.0-20250417193237-f615e6bd150b ## explicit; go 1.13 github.com/ianlancetaylor/demangle -+# github.com/microsoft/go-infra/telemetry v0.0.0-20260128082012-a1498e2b57dd ++# github.com/microsoft/go-infra/telemetry v0.0.0-20260312141037-c07bb95c5917 +## explicit; go 1.24 +github.com/microsoft/go-infra/telemetry +github.com/microsoft/go-infra/telemetry/counter @@ -2190,7 +2224,7 @@ index ceed574b32b507..e29e38f7da3cb3 100644 +github.com/microsoft/go-infra/telemetry/internal/appinsights/internal/contracts +github.com/microsoft/go-infra/telemetry/internal/config +github.com/microsoft/go-infra/telemetry/internal/telemetry -+# github.com/microsoft/go-infra/telemetry/config v0.0.0-20260128082012-a1498e2b57dd ++# github.com/microsoft/go-infra/telemetry/config v0.0.0-20260312141037-c07bb95c5917 +## explicit; go 1.24 +github.com/microsoft/go-infra/telemetry/config # golang.org/x/arch v0.23.1-0.20260109160903-657d90bd6695 diff --git a/patches/0009-Add-appinsights-telemetry.patch b/patches/0009-Add-appinsights-telemetry.patch index edbc0e10aa7..1679465484f 100644 --- a/patches/0009-Add-appinsights-telemetry.patch +++ b/patches/0009-Add-appinsights-telemetry.patch @@ -5,13 +5,14 @@ Subject: [PATCH] Add appinsights telemetry --- README.md | 15 ++++++ + .../internal/telemetrystats/telemetrystats.go | 14 +++++ src/cmd/go/main.go | 8 +++ src/cmd/go/mstelemetry_test.go | 52 +++++++++++++++++++ src/cmd/go/script_test.go | 8 +++ src/cmd/go/scriptcmds_test.go | 11 ++++ src/cmd/internal/telemetry/counter/counter.go | 48 ++++++++++++++++- .../telemetry/counter/counter_bootstrap.go | 3 ++ - 7 files changed, 144 insertions(+), 1 deletion(-) + 8 files changed, 158 insertions(+), 1 deletion(-) create mode 100644 src/cmd/go/mstelemetry_test.go diff --git a/README.md b/README.md @@ -38,11 +39,44 @@ index 71c9d1dc299388..8cab5daec4da54 100644 +our privacy statement. Your use of the software operates as your consent to +these practices. \ No newline at end of file +diff --git a/src/cmd/go/internal/telemetrystats/telemetrystats.go b/src/cmd/go/internal/telemetrystats/telemetrystats.go +index 81a6e1e1758461..1ef5eff53db267 100644 +--- a/src/cmd/go/internal/telemetrystats/telemetrystats.go ++++ b/src/cmd/go/internal/telemetrystats/telemetrystats.go +@@ -11,7 +11,12 @@ import ( + "cmd/go/internal/cfg" + "cmd/go/internal/modload" + "cmd/internal/telemetry/counter" ++ "crypto/sha256" ++ "math/big" ++ "os" + "strings" ++ ++ "golang.org/x/mod/modfile" + ) + + func Increment() { +@@ -39,6 +44,15 @@ func incrementConfig() { + counter.Inc("go/cgo:disabled") + } + ++ if gomod := modload.FindGoMod(base.Cwd()); gomod != "" { ++ if data, err := os.ReadFile(gomod); err == nil { ++ if f, err := modfile.ParseLax(gomod, data, nil); err == nil && f.Module != nil { ++ h := sha256.Sum256([]byte(f.Module.Mod.Path)) ++ counter.Inc("msgo/modulehash:" + new(big.Int).SetBytes(h[:]).String()) ++ } ++ } ++ } ++ + counter.Inc("go/platform/target/goos:" + cfg.Goos) + counter.Inc("go/platform/target/goarch:" + cfg.Goarch) + switch cfg.Goarch { diff --git a/src/cmd/go/main.go b/src/cmd/go/main.go -index e81969ca4a3144..67dbcb2e7a3cb9 100644 +index 8cdfd9196e4cb1..3f4a4d8f912969 100644 --- a/src/cmd/go/main.go +++ b/src/cmd/go/main.go -@@ -111,6 +111,14 @@ func main() { +@@ -110,6 +110,14 @@ func main() { } flag.Usage = base.Usage flag.Parse() @@ -116,7 +150,7 @@ index 00000000000000..6993137ad56e8c + fmt.Fprint(w, `{"itemsReceived": 1, "itemsAccepted": 1}`) +} diff --git a/src/cmd/go/script_test.go b/src/cmd/go/script_test.go -index 1345ea8bb8e530..e2b75957e21d3a 100644 +index d947c0b28454c7..d9651ae2cc5f22 100644 --- a/src/cmd/go/script_test.go +++ b/src/cmd/go/script_test.go @@ -60,6 +60,7 @@ func TestScript(t *testing.T) { @@ -127,7 +161,7 @@ index 1345ea8bb8e530..e2b75957e21d3a 100644 var ( ctx = context.Background() -@@ -254,6 +255,8 @@ func scriptEnv(srv *vcstest.Server, srvCertFile string) ([]string, error) { +@@ -253,6 +254,8 @@ func scriptEnv(srv *vcstest.Server, srvCertFile string) ([]string, error) { "HGRCPATH=", "GOTOOLCHAIN=auto", "MS_GOTOOLCHAIN_ALLOW_NON_LOCAL=1", // allow non-local toolchains, some tests expect GOTOOLCHAIN to be honored @@ -136,7 +170,7 @@ index 1345ea8bb8e530..e2b75957e21d3a 100644 "newline=\n", } -@@ -408,6 +411,11 @@ func checkCounters(t *testing.T, telemetryDir string) { +@@ -407,6 +410,11 @@ func checkCounters(t *testing.T, telemetryDir string) { t.Fatal("go was invoked but no counters were incremented") } } @@ -149,10 +183,10 @@ index 1345ea8bb8e530..e2b75957e21d3a 100644 // Copied from https://go.googlesource.com/telemetry/+/5f08a0cbff3f/internal/telemetry/mode.go#122 diff --git a/src/cmd/go/scriptcmds_test.go b/src/cmd/go/scriptcmds_test.go -index ced8d880e9ae3a..b3ad521ff94873 100644 +index 8195e830caa31b..cb59a8b278e9b4 100644 --- a/src/cmd/go/scriptcmds_test.go +++ b/src/cmd/go/scriptcmds_test.go -@@ -71,6 +71,7 @@ func scriptCC(cmdExec script.Cmd) script.Cmd { +@@ -72,6 +72,7 @@ func scriptCC(cmdExec script.Cmd) script.Cmd { } var scriptGoInvoked sync.Map // testing.TB → go command was invoked @@ -160,7 +194,7 @@ index ced8d880e9ae3a..b3ad521ff94873 100644 // scriptGo runs the go command. func scriptGo(cancel func(*exec.Cmd) error, waitDelay time.Duration) script.Cmd { -@@ -85,6 +86,16 @@ func scriptGo(cancel func(*exec.Cmd) error, waitDelay time.Duration) script.Cmd +@@ -86,6 +87,16 @@ func scriptGo(cancel func(*exec.Cmd) error, waitDelay time.Duration) script.Cmd if !dup { t.Cleanup(func() { scriptGoInvoked.Delete(t) }) } From d8147fb06f8006952b22cd3a0e019b71b16cc8e1 Mon Sep 17 00:00:00 2001 From: George Adams Date: Thu, 12 Mar 2026 15:29:04 +0000 Subject: [PATCH 2/2] PR fixup --- patches/0009-Add-appinsights-telemetry.patch | 23 ++++++++++---------- 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/patches/0009-Add-appinsights-telemetry.patch b/patches/0009-Add-appinsights-telemetry.patch index 1679465484f..a97835f4748 100644 --- a/patches/0009-Add-appinsights-telemetry.patch +++ b/patches/0009-Add-appinsights-telemetry.patch @@ -5,18 +5,18 @@ Subject: [PATCH] Add appinsights telemetry --- README.md | 15 ++++++ - .../internal/telemetrystats/telemetrystats.go | 14 +++++ + .../internal/telemetrystats/telemetrystats.go | 13 +++++ src/cmd/go/main.go | 8 +++ src/cmd/go/mstelemetry_test.go | 52 +++++++++++++++++++ src/cmd/go/script_test.go | 8 +++ src/cmd/go/scriptcmds_test.go | 11 ++++ src/cmd/internal/telemetry/counter/counter.go | 48 ++++++++++++++++- .../telemetry/counter/counter_bootstrap.go | 3 ++ - 8 files changed, 158 insertions(+), 1 deletion(-) + 8 files changed, 157 insertions(+), 1 deletion(-) create mode 100644 src/cmd/go/mstelemetry_test.go diff --git a/README.md b/README.md -index 71c9d1dc299388..8cab5daec4da54 100644 +index 71c9d1dc299388..56803b2a778296 100644 --- a/README.md +++ b/README.md @@ -40,3 +40,18 @@ places to ask questions about the Go language. @@ -38,32 +38,31 @@ index 71c9d1dc299388..8cab5daec4da54 100644 +You can learn more about data collection and use in the help documentation and +our privacy statement. Your use of the software operates as your consent to +these practices. -\ No newline at end of file diff --git a/src/cmd/go/internal/telemetrystats/telemetrystats.go b/src/cmd/go/internal/telemetrystats/telemetrystats.go -index 81a6e1e1758461..1ef5eff53db267 100644 +index 81a6e1e1758461..2761f41ac79595 100644 --- a/src/cmd/go/internal/telemetrystats/telemetrystats.go +++ b/src/cmd/go/internal/telemetrystats/telemetrystats.go -@@ -11,7 +11,12 @@ import ( +@@ -9,8 +9,12 @@ package telemetrystats + import ( + "cmd/go/internal/base" "cmd/go/internal/cfg" ++ "cmd/go/internal/gover" "cmd/go/internal/modload" "cmd/internal/telemetry/counter" + "crypto/sha256" + "math/big" + "os" "strings" -+ -+ "golang.org/x/mod/modfile" ) - func Increment() { -@@ -39,6 +44,15 @@ func incrementConfig() { +@@ -39,6 +43,15 @@ func incrementConfig() { counter.Inc("go/cgo:disabled") } + if gomod := modload.FindGoMod(base.Cwd()); gomod != "" { + if data, err := os.ReadFile(gomod); err == nil { -+ if f, err := modfile.ParseLax(gomod, data, nil); err == nil && f.Module != nil { -+ h := sha256.Sum256([]byte(f.Module.Mod.Path)) ++ if mod := gover.GoModLookup(data, "module"); mod != "" { ++ h := sha256.Sum256([]byte(mod)) + counter.Inc("msgo/modulehash:" + new(big.Int).SetBytes(h[:]).String()) + } + }