internal/graphconfig: rename to chartconfig, and display at /config This CL contains a few changes to improve the visibility and coherency of the "graph config": - rename to "chart config", since elsewhere we speak of telemetry.go.dev as hosting charts, and "graph" is an overloaded term - move the config.txt file into the chartconfig package, and expose it via embedding - display the chart config at the /config endpoint, since it is easier to read than the upload config - link to the current config in the overview of telemetry.go.dev Fixes golang/go#63418 Change-Id: Ia3cef815cb18b0b78f9f7c4d2e8fc82297e82f75 Reviewed-on: https://go-review.googlesource.com/c/telemetry/+/572335 LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
diff --git a/cmd/gotelemetry/internal/view/view.go b/cmd/gotelemetry/internal/view/view.go index 4b29f97..25232d7 100644 --- a/cmd/gotelemetry/internal/view/view.go +++ b/cmd/gotelemetry/internal/view/view.go
@@ -3,7 +3,7 @@ // license that can be found in the LICENSE file. // The view command is a server intended to be run on a user's machine to -// display the local counters and time series graphs of counters. +// display the local counters and time series charts of counters. package view import (
diff --git a/cmd/gotelemetry/internal/view/view_test.go b/cmd/gotelemetry/internal/view/view_test.go index 1f4410c..b35395a 100644 --- a/cmd/gotelemetry/internal/view/view_test.go +++ b/cmd/gotelemetry/internal/view/view_test.go
@@ -3,7 +3,7 @@ // license that can be found in the LICENSE file. // The view command is a server intended to be run on a users machine to -// display the local counters and time series graphs of counters. +// display the local counters and time series charts of counters. package view import (
diff --git a/godev/cmd/telemetrygodev/main.go b/godev/cmd/telemetrygodev/main.go index be74d45..47411de 100644 --- a/godev/cmd/telemetrygodev/main.go +++ b/godev/cmd/telemetrygodev/main.go
@@ -28,6 +28,7 @@ ilog "golang.org/x/telemetry/godev/internal/log" "golang.org/x/telemetry/godev/internal/middleware" "golang.org/x/telemetry/godev/internal/storage" + "golang.org/x/telemetry/internal/chartconfig" tconfig "golang.org/x/telemetry/internal/config" contentfs "golang.org/x/telemetry/internal/content" "golang.org/x/telemetry/internal/telemetry" @@ -230,6 +231,7 @@ } func handleConfig(fsys fs.FS, ucfg *tconfig.Config) content.HandlerFunc { + ccfg := chartconfig.Raw() cfg := ucfg.UploadConfig version := "default" @@ -240,10 +242,12 @@ } data := struct { Version string - PrettyConfig string + ChartConfig string + UploadConfig string }{ Version: version, - PrettyConfig: string(cfgJSON), + ChartConfig: string(ccfg), + UploadConfig: string(cfgJSON), } return content.Template(w, fsys, "config.html", data, http.StatusOK) }
diff --git a/godev/cmd/worker/main.go b/godev/cmd/worker/main.go index cf2f840..81cb70b 100644 --- a/godev/cmd/worker/main.go +++ b/godev/cmd/worker/main.go
@@ -283,7 +283,7 @@ ) for _, c := range p.Counters { // TODO: add support for histogram counters by getting the counter type - // from the graph config. + // from the chart config. prog.Charts = append(prog.Charts, partition(d, p.Name, c.Name, tconfig.Expand(c.Name), xs), )
diff --git a/internal/graphconfig/graphconfig.go b/internal/chartconfig/chartconfig.go similarity index 73% rename from internal/graphconfig/graphconfig.go rename to internal/chartconfig/chartconfig.go index abab80b..6d5a11d 100644 --- a/internal/graphconfig/graphconfig.go +++ b/internal/chartconfig/chartconfig.go
@@ -2,11 +2,11 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// The graphconfig package defines the GraphConfig type, representing telemetry -// graph configuration, as well as utilities for parsing and validating this +// The chartconfig package defines the ChartConfig type, representing telemetry +// chart configuration, as well as utilities for parsing and validating this // configuration. // -// Graph configuration defines the set of aggregations active on the telemetry +// Chart configuration defines the set of aggregations active on the telemetry // server, and are used to derive which data needs to be uploaded by users. // See the original blog post for more details: // @@ -24,20 +24,20 @@ // The following keys are supported. Any entry not marked as (optional) must be // provided. // -// - title: the graph title. -// - description: (optional) a longer description of the graph. -// - issue: a go issue tracker URL proposing the graph configuration. +// - title: the chart title. +// - description: (optional) a longer description of the chart. +// - issue: a go issue tracker URL proposing the chart configuration. // Multiple issues may be provided by including additional 'issue:' lines. // All proposals must be in the 'accepted' state. -// - type: the graph type: currently only partition, histogram, and stack are +// - type: the chart type: currently only partition, histogram, and stack are // supported. -// - program: the package path of the program for which this graph applies. -// - version: (optional) the first version for which this graph applies. Must +// - program: the package path of the program for which this chart applies. +// - version: (optional) the first version for which this chart applies. Must // be a valid semver value. -// - counter: the primary counter this graph illustrates, including buckets -// for histogram and partition graphs +// - counter: the primary counter this chart illustrates, including buckets +// for histogram and partition charts. // - depth: (optional) stack counters only; the maximum stack depth to collect -// - error: (optional) the desired error rate for this graph, which +// - error: (optional) the desired error rate for this chart, which // determines collection rate // // Multiple records are separated by "---" lines. @@ -66,13 +66,13 @@ // type: stack // program: golang.org/x/tools/gopls // depth: 10 -package graphconfig +package chartconfig -// A GraphConfig defines the configuration for a single graph/collection on the +// A ChartConfig defines the configuration for a single chart/collection on the // telemetry server. // // See the package documentation for field definitions. -type GraphConfig struct { +type ChartConfig struct { Title string Description string Issue []string
diff --git a/internal/configgen/config.txt b/internal/chartconfig/config.txt similarity index 90% rename from internal/configgen/config.txt rename to internal/chartconfig/config.txt index b4e697e..bd2bc21 100644 --- a/internal/configgen/config.txt +++ b/internal/chartconfig/config.txt
@@ -1,5 +1,5 @@ -# Note: this is an approved graph config. This is embedded in the configgen program. -# For the graph config file format, see golang.org/x/telemetry/internal/graphconfig. +# Note: these are approved chart configs, used to generate the upload config. +# For the chart config file format, see chartconfig.go. title: Editor Distribution counter: gopls/client:{vscode,vscodium,vscode-insiders,code-server,eglot,govim,neovim,coc.nvim,sublimetext,other}
diff --git a/internal/graphconfig/parse.go b/internal/chartconfig/load.go similarity index 85% rename from internal/graphconfig/parse.go rename to internal/chartconfig/load.go index f391130..e83cbab 100644 --- a/internal/graphconfig/parse.go +++ b/internal/chartconfig/load.go
@@ -2,9 +2,10 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package graphconfig +package chartconfig import ( + _ "embed" "fmt" "reflect" "sort" @@ -12,21 +13,33 @@ "strings" ) -// Parse parses GraphConfig records from the provided raw data, returning an +//go:embed config.txt +var chartConfig []byte + +func Raw() []byte { + return chartConfig +} + +// Load loads and parses the current chart config. +func Load() ([]ChartConfig, error) { + return Parse(chartConfig) +} + +// Parse parses ChartConfig records from the provided raw data, returning an // error if the config has invalid syntax. See the package documentation for a // description of the record syntax. // -// Even with correct syntax, the resulting GraphConfig may not meet all the +// Even with correct syntax, the resulting chart config may not meet all the // requirements described in the package doc. Call [Validate] to check whether // the config data is coherent. -func Parse(data []byte) ([]GraphConfig, error) { +func Parse(data []byte) ([]ChartConfig, error) { // Collect field information for the record type. var ( prefixes []string // for parse errors fields = make(map[string]reflect.StructField) // key -> struct field ) { - typ := reflect.TypeOf(GraphConfig{}) + typ := reflect.TypeOf(ChartConfig{}) for i := 0; i < typ.NumField(); i++ { f := typ.Field(i) key := strings.ToLower(f.Name) @@ -41,15 +54,15 @@ // Read records, separated by '---' var ( - records []GraphConfig - inProgress = new(GraphConfig) // record value currently being parsed + records []ChartConfig + inProgress = new(ChartConfig) // record value currently being parsed set = make(map[string]bool) // fields that are set so far; empty records are skipped ) flushRecord := func() { if len(set) > 0 { // only flush non-empty records records = append(records, *inProgress) } - inProgress = new(GraphConfig) + inProgress = new(ChartConfig) set = make(map[string]bool) }
diff --git a/internal/graphconfig/parse_test.go b/internal/chartconfig/load_test.go similarity index 85% rename from internal/graphconfig/parse_test.go rename to internal/chartconfig/load_test.go index 19d74fc..b00acf2 100644 --- a/internal/graphconfig/parse_test.go +++ b/internal/chartconfig/load_test.go
@@ -2,23 +2,23 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package graphconfig_test +package chartconfig_test import ( "reflect" "testing" - "golang.org/x/telemetry/internal/graphconfig" + "golang.org/x/telemetry/internal/chartconfig" ) func TestParse(t *testing.T) { tests := []struct { name string input string - want []graphconfig.GraphConfig + want []chartconfig.ChartConfig }{ {"empty", "", nil}, - {"single field", "title: A", []graphconfig.GraphConfig{{Title: "A"}}}, + {"single field", "title: A", []chartconfig.ChartConfig{{Title: "A"}}}, { "basic", ` title: A @@ -32,7 +32,7 @@ error: 0.1 version: v2.0.0 `, - []graphconfig.GraphConfig{{ + []chartconfig.ChartConfig{{ Title: "A", Description: "B", Type: "C", @@ -49,7 +49,7 @@ title: A description: B `, - []graphconfig.GraphConfig{ + []chartconfig.ChartConfig{ {Title: "A", Description: "B"}, }, }, @@ -64,7 +64,7 @@ `, - []graphconfig.GraphConfig{ + []chartconfig.ChartConfig{ {Title: "A", Description: "B"}, }, }, @@ -80,7 +80,7 @@ title: C description: D `, - []graphconfig.GraphConfig{ + []chartconfig.ChartConfig{ {Title: "A", Description: "B"}, {Title: "C", Description: "D"}, }, @@ -94,7 +94,7 @@ issue: TBD program: golang.org/x/tools/gopls `, - []graphconfig.GraphConfig{ + []chartconfig.ChartConfig{ { Title: "Editor Distribution", Description: "measure editor distribution for gopls users.", @@ -109,7 +109,7 @@ for _, test := range tests { t.Run(test.name, func(t *testing.T) { - got, err := graphconfig.Parse([]byte(test.input)) + got, err := chartconfig.Parse([]byte(test.input)) if err != nil { t.Fatalf("Parse(...) failed: %v", err) } @@ -161,7 +161,7 @@ for _, test := range tests { t.Run(test.name, func(t *testing.T) { - _, err := graphconfig.Parse([]byte(test.input)) + _, err := chartconfig.Parse([]byte(test.input)) if err == nil { t.Fatalf("Parse(...) succeeded unexpectedly") }
diff --git a/internal/graphconfig/validate.go b/internal/chartconfig/validate.go similarity index 82% rename from internal/graphconfig/validate.go rename to internal/chartconfig/validate.go index 15b7b71..74106b9 100644 --- a/internal/graphconfig/validate.go +++ b/internal/chartconfig/validate.go
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package graphconfig +package chartconfig import ( "errors" @@ -11,9 +11,9 @@ "golang.org/x/mod/semver" ) -// Validate checks that a graph config is complete and coherent, returning an +// Validate checks that a ChartConfig is complete and coherent, returning an // error describing all problems encountered, or nil. -func Validate(cfg GraphConfig) error { +func Validate(cfg ChartConfig) error { var errs []error reportf := func(format string, args ...any) { errs = append(errs, fmt.Errorf(format, args...)) @@ -37,7 +37,7 @@ reportf("invalid depth %d: must be non-negative", cfg.Depth) } if cfg.Depth != 0 && cfg.Type != "stack" { - reportf("depth can only be set for \"stack\" graph types") + reportf("depth can only be set for \"stack\" chart types") } if cfg.Version != "" && !semver.IsValid(cfg.Version) { reportf("%q is not valid semver", cfg.Version)
diff --git a/internal/graphconfig/validate_test.go b/internal/chartconfig/validate_test.go similarity index 81% rename from internal/graphconfig/validate_test.go rename to internal/chartconfig/validate_test.go index 25533ef..01fc557 100644 --- a/internal/graphconfig/validate_test.go +++ b/internal/chartconfig/validate_test.go
@@ -2,17 +2,17 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package graphconfig_test +package chartconfig_test import ( "strings" "testing" - "golang.org/x/telemetry/internal/graphconfig" + "golang.org/x/telemetry/internal/chartconfig" ) func TestValidateOK(t *testing.T) { - // A minimally valid graph config. + // A minimally valid chart config. const input = ` title: Editor Distribution counter: gopls/editor:{emacs,vim,vscode,other} @@ -20,14 +20,14 @@ issue: https://go.dev/issue/12345 program: golang.org/x/tools/gopls ` - records, err := graphconfig.Parse([]byte(input)) + records, err := chartconfig.Parse([]byte(input)) if err != nil { t.Fatal(err) } if len(records) != 1 { t.Fatalf("Parse(%q) returned %d records, want exactly 1", input, len(records)) } - if err := graphconfig.Validate(records[0]); err != nil { + if err := chartconfig.Validate(records[0]); err != nil { t.Errorf("Validate(%q) = %v, want nil", input, err) } } @@ -45,14 +45,14 @@ } for input, wantErrs := range tests { - records, err := graphconfig.Parse([]byte(input)) + records, err := chartconfig.Parse([]byte(input)) if err != nil { t.Fatal(err) } if len(records) != 1 { t.Fatalf("Parse(%q) returned %d records, want exactly 1", input, len(records)) } - err = graphconfig.Validate(records[0]) + err = chartconfig.Validate(records[0]) if err == nil { t.Fatalf("Validate(%q) succeeded unexpectedly", input) }
diff --git a/internal/configgen/main.go b/internal/configgen/main.go index f49dd48..5658fc8 100644 --- a/internal/configgen/main.go +++ b/internal/configgen/main.go
@@ -7,7 +7,7 @@ //go:build go1.21 // Package configgen generates the upload config file stored in the config.json -// file of golang.org/x/telemetry/config based on the graphconfig stored in +// file of golang.org/x/telemetry/config based on the chartconfig stored in // config.txt. package main @@ -25,10 +25,8 @@ "sort" "strings" - _ "embed" - "golang.org/x/mod/semver" - "golang.org/x/telemetry/internal/graphconfig" + "golang.org/x/telemetry/internal/chartconfig" "golang.org/x/telemetry/internal/telemetry" ) @@ -40,16 +38,18 @@ SamplingRate = 1.0 ) -//go:embed config.txt -var graphConfig []byte - func main() { flag.Parse() + gcfgs, err := chartconfig.Load() + if err != nil { + log.Fatal(err) + } + // The padding heuristics below are based on the example of gopls. // // The goal is to pad enough versions for a quarter. - cfg, err := generate(graphConfig, padding{ + uCfg, err := generate(gcfgs, padding{ // 6 releases into the future translates to approximately three months for gopls. releases: 6, // We may release gopls 1.0, but won't release 2.0 in a three month timespan! @@ -66,7 +66,7 @@ if err != nil { log.Fatal(err) } - cfgJSON, err := json.MarshalIndent(cfg, "", "\t") + cfgJSON, err := json.MarshalIndent(uCfg, "", "\t") if err != nil { log.Fatal(err) } @@ -87,7 +87,7 @@ log.Fatal(err) } // Guarantee that we have enough padding to do two patches releases tomorrow. - minCfg, err := generate(graphConfig, padding{ + minCfg, err := generate(gcfgs, padding{ releases: 2, maj: 1, majmin: 1, // we're not ever going to do more than one major/minor release in a day @@ -138,9 +138,9 @@ return cfg, nil } -// generate computes the upload config from graph configs and module +// generate computes the upload config from chart configs and module // information, returning the resulting formatted JSON. -func generate(graphConfig []byte, padding padding) (*telemetry.UploadConfig, error) { +func generate(gcfgs []chartconfig.ChartConfig, padding padding) (*telemetry.UploadConfig, error) { ucfg := &telemetry.UploadConfig{ GOOS: goos(), GOARCH: goarch(), @@ -153,16 +153,11 @@ return nil, fmt.Errorf("querying go info: %v", err) } - gcfgs, err := graphconfig.Parse(graphConfig) - if err != nil { - return nil, fmt.Errorf("parsing graph config records: %v", err) - } - for i, r := range gcfgs { - if err := graphconfig.Validate(r); err != nil { + if err := chartconfig.Validate(r); err != nil { // TODO(rfindley): this is a poor way to identify the faulty record. We - // should probably store position information in the GraphConfig. - return nil, fmt.Errorf("graph config #%d (%q): %v", i, r.Title, err) + // should probably store position information in the ChartConfig. + return nil, fmt.Errorf("chart config #%d (%q): %v", i, r.Title, err) } }
diff --git a/internal/configgen/main_test.go b/internal/configgen/main_test.go index 5764871..08d5c13 100644 --- a/internal/configgen/main_test.go +++ b/internal/configgen/main_test.go
@@ -12,6 +12,7 @@ "sort" "testing" + "golang.org/x/telemetry/internal/chartconfig" "golang.org/x/telemetry/internal/telemetry" ) @@ -23,7 +24,7 @@ "golang.org/toolchain": {"v0.0.1-go1.21.0.linux-arm", "v0.0.1-go1.20.linux-arm"}, "golang.org/x/tools/gopls": {"v0.13.0", "v0.14.0", "v0.15.0-pre.1", "v0.15.0"}, } - const gcfg = ` + const raw = ` title: Editor Distribution counter: gopls/editor:{emacs,vim,vscode,other} description: measure editor distribution for gopls users. @@ -32,7 +33,11 @@ program: golang.org/x/tools/gopls version: v0.14.0 ` - got, err := generate([]byte(gcfg), padding{2, 1, 1, 2, 2}) + gcfgs, err := chartconfig.Parse([]byte(raw)) + if err != nil { + t.Fatal(err) + } + got, err := generate(gcfgs, padding{2, 1, 1, 2, 2}) if err != nil { t.Fatal(err) }
diff --git a/internal/content/telemetrygodev/config.html b/internal/content/telemetrygodev/config.html index a83659a..8790eaa 100644 --- a/internal/content/telemetrygodev/config.html +++ b/internal/content/telemetrygodev/config.html
@@ -10,16 +10,29 @@ {{define "content"}} <main id="main"> - <section class="Config"> - <h2 id="config">Config</h2> - <p> - The config contains the list of active counters for each program - and allowed report metadata. - </p> - <label> - Version: {{.Version}} - </label> - <pre style="max-height: 100rem">{{.PrettyConfig}}</pre> - </section> + <section class="Chart Config"> + <h2 id="config">Chart Config</h2> + <p> + The chart config contains the list of approved charts to display on + telemetry.go.dev. The chart config format is documented by the + <a href="https://pkg.go.dev/golang.org/x/telemetry/internal/chartconfig"> + <code>chartconfig</code> + </a> package documentation. + </p> + <pre style="max-height: 100rem">{{.ChartConfig}}</pre> + </section> + + <section class="Upload Config"> + <h2 id="config">Upload Config</h2> + <p> + The upload config contains the list of active counters for each program + and allowed report metadata. This is generated from the chart config + above. + </p> + <label> + Version: {{.Version}} + </label> + <pre style="max-height: 100rem">{{.UploadConfig}}</pre> + </section> </main> -{{end}} \ No newline at end of file +{{end}}
diff --git a/internal/content/telemetrygodev/index.html b/internal/content/telemetrygodev/index.html index 1412d75..c2d81f4 100644 --- a/internal/content/telemetrygodev/index.html +++ b/internal/content/telemetrygodev/index.html
@@ -15,12 +15,22 @@ <h2>Overview</h2> <p> Go Telemetry is a way for Go toolchain programs to collect data about their - performance and usage. Uploaded data is used to help improve the Go toolchain - and related tools. Go Telemetry is not built into users' binaries. - <a href="/privacy#collection">See what Go Telemetry collects</a>. + performance and usage. Uploaded data is used to help improve the Go + toolchain and related tools. Go Telemetry is not built into users' + binaries. Learn more about Go telemetry at + <a href="https://go.dev/doc/telemetry">go.dev/doc/telemetry</a>. </p> - </p>For privacy information about this service, see <a href="/privacy">telemetry.go.dev/privacy</a>.</p> + <p> + Users who have opted in will upload an approved subset of telemetry + data approximately once a week. This subset is determined by the current + <a href="/config">upload configuration</a>. + </p> + + <p> + For privacy information about this service, see + <a href="/privacy">telemetry.go.dev/privacy</a>. + </p> </section> <section> <h2>Charts</h2> @@ -41,4 +51,4 @@ </ul> </section> </main> -{{end}} \ No newline at end of file +{{end}}