-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add metricsmd package #3
Merged
Merged
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
e834594
Add initial go.mod, vendor/ and Makefile
lambdanis b95cd5b
Add metricsmd package for generating metrics docs
chancez 2858155
Add metricsmd.NewCmd function creating a Cobra command
lambdanis 2bab2cf
Ignore empty label values
lambdanis 71b3906
Introduce Config struct
lambdanis 9eb63f3
Don't add "autogenerate" comment by default
lambdanis c6db511
Support rendering docs with a higher heading level
lambdanis 23fc556
Validate configuration
lambdanis File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
go.sum linguist-generated | ||
vendor/* linguist-vendored |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
GO := go | ||
|
||
.PHONY: all | ||
all: | ||
|
||
.PHONY: vendor | ||
vendor: | ||
$(GO) mod tidy | ||
$(GO) mod vendor | ||
$(GO) mod verify |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
module github.com/isovalent/metricstool | ||
|
||
go 1.22.0 | ||
|
||
require ( | ||
github.com/prometheus/client_golang v1.18.0 | ||
github.com/spf13/cobra v1.8.0 | ||
github.com/spf13/viper v1.18.2 | ||
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 | ||
) | ||
|
||
require ( | ||
github.com/beorn7/perks v1.0.1 // indirect | ||
github.com/cespare/xxhash/v2 v2.2.0 // indirect | ||
github.com/fsnotify/fsnotify v1.7.0 // indirect | ||
github.com/hashicorp/hcl v1.0.0 // indirect | ||
github.com/inconshreveable/mousetrap v1.1.0 // indirect | ||
github.com/magiconair/properties v1.8.7 // indirect | ||
github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect | ||
github.com/mitchellh/mapstructure v1.5.0 // indirect | ||
github.com/pelletier/go-toml/v2 v2.1.0 // indirect | ||
github.com/prometheus/client_model v0.5.0 // indirect | ||
github.com/prometheus/common v0.45.0 // indirect | ||
github.com/prometheus/procfs v0.12.0 // indirect | ||
github.com/sagikazarmark/locafero v0.4.0 // indirect | ||
github.com/sagikazarmark/slog-shim v0.1.0 // indirect | ||
github.com/sourcegraph/conc v0.3.0 // indirect | ||
github.com/spf13/afero v1.11.0 // indirect | ||
github.com/spf13/cast v1.6.0 // indirect | ||
github.com/spf13/pflag v1.0.5 // indirect | ||
github.com/subosito/gotenv v1.6.0 // indirect | ||
go.uber.org/atomic v1.9.0 // indirect | ||
go.uber.org/multierr v1.9.0 // indirect | ||
golang.org/x/sys v0.15.0 // indirect | ||
golang.org/x/text v0.14.0 // indirect | ||
google.golang.org/protobuf v1.31.0 // indirect | ||
gopkg.in/ini.v1 v1.67.0 // indirect | ||
gopkg.in/yaml.v3 v3.0.1 // indirect | ||
) |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
// SPDX-License-Identifier: Apache-2.0 | ||
// Copyright 2024 Isovalent Inc. | ||
|
||
package metricsmd | ||
|
||
import ( | ||
"fmt" | ||
"log/slog" | ||
|
||
"github.com/prometheus/client_golang/prometheus" | ||
) | ||
|
||
type LabelValues struct { | ||
Label string | ||
Values []string | ||
} | ||
|
||
type LabelOverrides struct { | ||
Metric string | ||
Overrides []LabelValues | ||
} | ||
|
||
type Config struct { | ||
CobraAnnotations map[string]string | ||
Targets map[string]string // cli argument -> docs header | ||
LabelOverrides []LabelOverrides | ||
InitMetrics func(target string, reg *prometheus.Registry, log *slog.Logger) error | ||
AutogeneratedComment bool | ||
HeadingLevel int // must be between 0 and 4 | ||
} | ||
|
||
func validateConfig(config *Config) error { | ||
if config.Targets == nil { | ||
return fmt.Errorf("config.Targets must be set") | ||
} | ||
if config.InitMetrics == nil { | ||
return fmt.Errorf("config.InitMetrics must be set") | ||
} | ||
if config.HeadingLevel < 0 || config.HeadingLevel > 4 { | ||
return fmt.Errorf("config.HeadingLevel must be between 0 and 4") | ||
} | ||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
// SPDX-License-Identifier: Apache-2.0 | ||
// Copyright 2024 Isovalent Inc. | ||
|
||
package metricsmd | ||
|
||
import ( | ||
"fmt" | ||
"io" | ||
"sort" | ||
"strings" | ||
|
||
"github.com/prometheus/client_golang/prometheus" | ||
) | ||
|
||
// Generate | ||
func Generate(reg *prometheus.Registry, w io.Writer, config *Config) error { | ||
metricsFamilies, err := reg.Gather() | ||
if err != nil { | ||
return err | ||
} | ||
sort.Slice(metricsFamilies, func(i, j int) bool { | ||
return metricsFamilies[i].GetName() < metricsFamilies[j].GetName() | ||
}) | ||
|
||
for _, metric := range metricsFamilies { | ||
// Include the metric name and help text. | ||
h := "##" | ||
for i := 0; i < config.HeadingLevel; i++ { | ||
h += "#" | ||
} | ||
io.WriteString(w, fmt.Sprintf("%s `%s`\n\n", h, metric.GetName())) | ||
io.WriteString(w, fmt.Sprintf("%s\n\n", metric.GetHelp())) | ||
// The rest is generating a list of label names and values | ||
|
||
// map of "label_name" -> set([label_values...]) | ||
labelsToValues := make(map[string]map[string]struct{}) | ||
|
||
// Iterate over the series | ||
series := metric.GetMetric() | ||
for _, m := range series { | ||
for _, label := range m.GetLabel() { | ||
// Check if the map entry exists | ||
_, ok := labelsToValues[label.GetName()] | ||
if !ok { | ||
// Initialize it | ||
labelsToValues[label.GetName()] = make(map[string]struct{}) | ||
} | ||
// Add the value to the set of values for this label | ||
if val := label.GetValue(); val != "" { | ||
labelsToValues[label.GetName()][val] = struct{}{} | ||
} | ||
} | ||
} | ||
|
||
// Support overriding the values of labels, in case they're not suitable for docs. | ||
for _, override := range config.LabelOverrides { | ||
if override.Metric != metric.GetName() { | ||
continue | ||
} | ||
for _, o := range override.Overrides { | ||
// Erase the current labels if any exist | ||
labelsToValues[o.Label] = make(map[string]struct{}) | ||
for _, overrideVal := range o.Values { | ||
labelsToValues[o.Label][overrideVal] = struct{}{} | ||
} | ||
} | ||
} | ||
|
||
// Generate a list of labels and their values | ||
var finalLabels []LabelValues | ||
for label, valuesMap := range labelsToValues { | ||
var vals []string | ||
for val := range valuesMap { | ||
vals = append(vals, val) | ||
} | ||
// Sort the values | ||
sort.Strings(vals) | ||
finalLabels = append(finalLabels, LabelValues{ | ||
Label: label, | ||
Values: vals, | ||
}) | ||
} | ||
|
||
// Write out the labels out if there are any | ||
if len(finalLabels) > 0 { | ||
sort.Slice(finalLabels, func(i, j int) bool { | ||
return finalLabels[i].Label < finalLabels[j].Label | ||
}) | ||
io.WriteString(w, "| label | values |\n") | ||
io.WriteString(w, "| ----- | ------ |\n") | ||
for _, labelVal := range finalLabels { | ||
row := fmt.Sprintf("| `%-5s` | `%5s` |\n", labelVal.Label, strings.Join(labelVal.Values, ", ")) | ||
io.WriteString(w, row) | ||
} | ||
io.WriteString(w, "\n") | ||
} | ||
} | ||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
// SPDX-License-Identifier: Apache-2.0 | ||
// Copyright 2024 Isovalent Inc. | ||
|
||
package metricsmd | ||
|
||
import ( | ||
"bytes" | ||
"fmt" | ||
"io" | ||
"log/slog" | ||
|
||
"golang.org/x/exp/maps" | ||
|
||
"github.com/prometheus/client_golang/prometheus" | ||
"github.com/spf13/cobra" | ||
"github.com/spf13/viper" | ||
) | ||
|
||
// NewCmd creates a Cobra command for generating metrics reference docs. | ||
// It's intended to be used as an add-on to applications that have a Cobra CLI | ||
// and expose Prometheus metrics. | ||
func NewCmd(vp *viper.Viper, log *slog.Logger, config *Config) (*cobra.Command, error) { | ||
err := validateConfig(config) | ||
if err != nil { | ||
return nil, err | ||
} | ||
cmd := &cobra.Command{ | ||
Use: "metrics-docs", | ||
Hidden: true, | ||
Annotations: config.CobraAnnotations, | ||
ValidArgs: maps.Keys(config.Targets), | ||
Args: cobra.MatchAll(cobra.ExactArgs(1), cobra.OnlyValidArgs), | ||
PreRunE: func(cmd *cobra.Command, _ []string) error { | ||
if vp != nil { | ||
flags := cmd.Flags() | ||
if err := vp.BindPFlags(flags); err != nil { | ||
return err | ||
} | ||
} | ||
return nil | ||
}, | ||
RunE: func(cmd *cobra.Command, args []string) error { | ||
target := args[0] | ||
reg := prometheus.NewRegistry() | ||
|
||
err := config.InitMetrics(target, reg, log) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
var b bytes.Buffer | ||
if config.AutogeneratedComment { | ||
// Comment to inform people this file is autogenerated. | ||
b.WriteString("<!-- This file is autogenerated via https://github.com/isovalent/metricstool -->\n\n") | ||
} | ||
// Document title | ||
h := "#" | ||
for i := 0; i < config.HeadingLevel; i++ { | ||
h += "#" | ||
} | ||
b.WriteString(fmt.Sprintf("%s %s Metrics\n\n", h, config.Targets[target])) | ||
// Generate metrics reference | ||
err = Generate(reg, &b, config) | ||
if err != nil { | ||
return err | ||
} | ||
io.Copy(cmd.OutOrStdout(), &b) | ||
|
||
return nil | ||
}, | ||
} | ||
return cmd, nil | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think GitHub automatically does this appropriately?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh, does it? That's cool.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ah
go.sum
is always displayed but vendored stuff is redacted except for appropriate stuff likevendor/modules.txt
. See your PR for example https://github.com/cilium/tetragon/pull/2164/files.