mirror of
https://github.com/tendermint/tendermint.git
synced 2026-01-03 11:45:18 +00:00
scripts/metricsgen: add the initial version of metricsgen (#8479)
This pull requests adds a new tool, metricsgen, for generating Tendermint metrics constructors from `Metrics` struct definitions. This tool aims to reduce the amount of boilerplate required to add additional metrics to Tendermint. Its working is fairly simple, it parses the go ast, extracts field information, and uses this field information to execute a go template. This pull request also adds a proof-of-concept of the tool's output and working by using it to generate the [indexer metrics](https://github.com/tendermint/tendermint/pull/8479/files#diff-4b0c597b6fa05332a2f9a8e0ce079e360602942fae99dc5485f1edfe71c0a29e) using `//go:generate` directives and a simple `make` target. The next steps for this tool are documented in https://github.com/tendermint/tendermint/issues/8485 and https://github.com/tendermint/tendermint/issues/8486, which detail using the tool to generate the `metrics.md` documentation file and using the tool to migrate away from `go-kit`.
This commit is contained in:
334
scripts/metricsgen/metricsgen.go
Normal file
334
scripts/metricsgen/metricsgen.go
Normal file
@@ -0,0 +1,334 @@
|
||||
// metricsgen is a code generation tool for creating constructors for Tendermint
|
||||
// metrics types.
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"flag"
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/format"
|
||||
"go/parser"
|
||||
"go/token"
|
||||
"go/types"
|
||||
"io"
|
||||
"io/fs"
|
||||
"log"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"text/template"
|
||||
)
|
||||
|
||||
func init() {
|
||||
flag.Usage = func() {
|
||||
fmt.Fprintf(os.Stderr, `Usage: %[1]s -struct <struct>
|
||||
|
||||
Generate constructors for the metrics type specified by -struct contained in
|
||||
the current directory. The tool creates a new file in the current directory
|
||||
containing the generated code.
|
||||
|
||||
Options:
|
||||
`, filepath.Base(os.Args[0]))
|
||||
flag.PrintDefaults()
|
||||
}
|
||||
}
|
||||
|
||||
const metricsPackageName = "github.com/go-kit/kit/metrics"
|
||||
|
||||
const (
|
||||
metricNameTag = "metrics_name"
|
||||
labelsTag = "metrics_labels"
|
||||
bucketTypeTag = "metrics_buckettype"
|
||||
bucketSizeTag = "metrics_bucketsizes"
|
||||
)
|
||||
|
||||
var (
|
||||
dir = flag.String("dir", ".", "Path to the directory containing the target package")
|
||||
strct = flag.String("struct", "Metrics", "Struct to parse for metrics")
|
||||
)
|
||||
|
||||
var bucketType = map[string]string{
|
||||
"exprange": "stdprometheus.ExponentialBucketsRange",
|
||||
"exp": "stdprometheus.ExponentialBuckets",
|
||||
"lin": "stdprometheus.LinearBuckets",
|
||||
}
|
||||
|
||||
var tmpl = template.Must(template.New("tmpl").Parse(`// Code generated by metricsgen. DO NOT EDIT.
|
||||
|
||||
package {{ .Package }}
|
||||
|
||||
import (
|
||||
"github.com/go-kit/kit/metrics/discard"
|
||||
prometheus "github.com/go-kit/kit/metrics/prometheus"
|
||||
stdprometheus "github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
func PrometheusMetrics(namespace string, labelsAndValues...string) *Metrics {
|
||||
labels := []string{}
|
||||
for i := 0; i < len(labelsAndValues); i += 2 {
|
||||
labels = append(labels, labelsAndValues[i])
|
||||
}
|
||||
return &Metrics{
|
||||
{{ range $metric := .ParsedMetrics }}
|
||||
{{- $metric.FieldName }}: prometheus.New{{ $metric.TypeName }}From(stdprometheus.{{$metric.TypeName }}Opts{
|
||||
Namespace: namespace,
|
||||
Subsystem: MetricsSubsystem,
|
||||
Name: "{{$metric.MetricName }}",
|
||||
Help: "{{ $metric.Description }}",
|
||||
{{ if ne $metric.HistogramOptions.BucketType "" }}
|
||||
Buckets: {{ $metric.HistogramOptions.BucketType }}({{ $metric.HistogramOptions.BucketSizes }}),
|
||||
{{ else if ne $metric.HistogramOptions.BucketSizes "" }}
|
||||
Buckets: []float64{ {{ $metric.HistogramOptions.BucketSizes }} },
|
||||
{{ end }}
|
||||
{{- if eq (len $metric.Labels) 0 }}
|
||||
}, labels).With(labelsAndValues...),
|
||||
{{ else }}
|
||||
}, append(labels, {{$metric.Labels | printf "%q" }})).With(labelsAndValues...),
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func NopMetrics() *Metrics {
|
||||
return &Metrics{
|
||||
{{- range $metric := .ParsedMetrics }}
|
||||
{{ $metric.FieldName }}: discard.New{{ $metric.TypeName }}(),
|
||||
{{- end }}
|
||||
}
|
||||
}
|
||||
`))
|
||||
|
||||
// ParsedMetricField is the data parsed for a single field of a metric struct.
|
||||
type ParsedMetricField struct {
|
||||
TypeName string
|
||||
FieldName string
|
||||
MetricName string
|
||||
Description string
|
||||
Labels string
|
||||
|
||||
HistogramOptions HistogramOpts
|
||||
}
|
||||
|
||||
type HistogramOpts struct {
|
||||
BucketType string
|
||||
BucketSizes string
|
||||
}
|
||||
|
||||
// TemplateData is all of the data required for rendering a metric file template.
|
||||
type TemplateData struct {
|
||||
Package string
|
||||
ParsedMetrics []ParsedMetricField
|
||||
}
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
if *strct == "" {
|
||||
log.Fatal("You must specify a non-empty -struct")
|
||||
}
|
||||
td, err := ParseMetricsDir(".", *strct)
|
||||
if err != nil {
|
||||
log.Fatalf("Parsing file: %v", err)
|
||||
}
|
||||
out := filepath.Join(*dir, "metrics.gen.go")
|
||||
f, err := os.Create(out)
|
||||
if err != nil {
|
||||
log.Fatalf("Opening file: %v", err)
|
||||
}
|
||||
err = GenerateMetricsFile(f, td)
|
||||
if err != nil {
|
||||
log.Fatalf("Generating code: %v", err)
|
||||
}
|
||||
}
|
||||
func ignoreTestFiles(f fs.FileInfo) bool {
|
||||
return !strings.Contains(f.Name(), "_test.go")
|
||||
}
|
||||
|
||||
// ParseMetricsDir parses the dir and scans for a struct matching structName,
|
||||
// ignoring all test files. ParseMetricsDir iterates the fields of the metrics
|
||||
// struct and builds a TemplateData using the data obtained from the abstract syntax tree.
|
||||
func ParseMetricsDir(dir string, structName string) (TemplateData, error) {
|
||||
fs := token.NewFileSet()
|
||||
d, err := parser.ParseDir(fs, dir, ignoreTestFiles, parser.ParseComments)
|
||||
if err != nil {
|
||||
return TemplateData{}, err
|
||||
}
|
||||
if len(d) > 1 {
|
||||
return TemplateData{}, fmt.Errorf("multiple packages found in %s", dir)
|
||||
}
|
||||
if len(d) == 0 {
|
||||
return TemplateData{}, fmt.Errorf("no go pacakges found in %s", dir)
|
||||
}
|
||||
|
||||
// Grab the package name.
|
||||
var pkgName string
|
||||
var pkg *ast.Package
|
||||
for pkgName, pkg = range d {
|
||||
}
|
||||
td := TemplateData{
|
||||
Package: pkgName,
|
||||
}
|
||||
// Grab the metrics struct
|
||||
m, mPkgName, err := findMetricsStruct(pkg.Files, structName)
|
||||
if err != nil {
|
||||
return TemplateData{}, err
|
||||
}
|
||||
for _, f := range m.Fields.List {
|
||||
if !isMetric(f.Type, mPkgName) {
|
||||
continue
|
||||
}
|
||||
pmf := parseMetricField(f)
|
||||
td.ParsedMetrics = append(td.ParsedMetrics, pmf)
|
||||
}
|
||||
|
||||
return td, err
|
||||
}
|
||||
|
||||
// GenerateMetricsFile executes the metrics file template, writing the result
|
||||
// into the io.Writer.
|
||||
func GenerateMetricsFile(w io.Writer, td TemplateData) error {
|
||||
b := []byte{}
|
||||
buf := bytes.NewBuffer(b)
|
||||
err := tmpl.Execute(buf, td)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
b, err = format.Source(buf.Bytes())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = io.Copy(w, bytes.NewBuffer(b))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func findMetricsStruct(files map[string]*ast.File, structName string) (*ast.StructType, string, error) {
|
||||
var (
|
||||
st *ast.StructType
|
||||
)
|
||||
for _, file := range files {
|
||||
mPkgName, err := extractMetricsPackageName(file.Imports)
|
||||
if err != nil {
|
||||
return nil, "", fmt.Errorf("unable to determine metrics package name: %v", err)
|
||||
}
|
||||
if !ast.FilterFile(file, func(name string) bool {
|
||||
return name == structName
|
||||
}) {
|
||||
continue
|
||||
}
|
||||
ast.Inspect(file, func(n ast.Node) bool {
|
||||
switch f := n.(type) {
|
||||
case *ast.TypeSpec:
|
||||
if f.Name.Name == structName {
|
||||
var ok bool
|
||||
st, ok = f.Type.(*ast.StructType)
|
||||
if !ok {
|
||||
err = fmt.Errorf("found identifier for %q of wrong type", structName)
|
||||
}
|
||||
}
|
||||
return false
|
||||
default:
|
||||
return true
|
||||
}
|
||||
})
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
if st != nil {
|
||||
return st, mPkgName, nil
|
||||
}
|
||||
}
|
||||
return nil, "", fmt.Errorf("target struct %q not found in dir", structName)
|
||||
}
|
||||
|
||||
func parseMetricField(f *ast.Field) ParsedMetricField {
|
||||
var comment string
|
||||
if f.Doc != nil {
|
||||
for _, c := range f.Doc.List {
|
||||
comment += strings.TrimPrefix(c.Text, "// ")
|
||||
}
|
||||
}
|
||||
pmf := ParsedMetricField{
|
||||
Description: comment,
|
||||
MetricName: extractFieldName(f.Names[0].String(), f.Tag),
|
||||
FieldName: f.Names[0].String(),
|
||||
TypeName: extractTypeName(f.Type),
|
||||
Labels: extractLabels(f.Tag),
|
||||
}
|
||||
if pmf.TypeName == "Histogram" {
|
||||
pmf.HistogramOptions = extractHistogramOptions(f.Tag)
|
||||
}
|
||||
return pmf
|
||||
}
|
||||
|
||||
func extractTypeName(e ast.Expr) string {
|
||||
return strings.TrimPrefix(path.Ext(types.ExprString(e)), ".")
|
||||
}
|
||||
|
||||
func isMetric(e ast.Expr, mPkgName string) bool {
|
||||
return strings.Contains(types.ExprString(e), fmt.Sprintf("%s.", mPkgName))
|
||||
}
|
||||
|
||||
func extractLabels(bl *ast.BasicLit) string {
|
||||
if bl != nil {
|
||||
t := reflect.StructTag(strings.Trim(bl.Value, "`"))
|
||||
if v := t.Get(labelsTag); v != "" {
|
||||
return v
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func extractFieldName(name string, tag *ast.BasicLit) string {
|
||||
if tag != nil {
|
||||
t := reflect.StructTag(strings.Trim(tag.Value, "`"))
|
||||
if v := t.Get(metricNameTag); v != "" {
|
||||
return v
|
||||
}
|
||||
}
|
||||
return toSnakeCase(name)
|
||||
}
|
||||
|
||||
func extractHistogramOptions(tag *ast.BasicLit) HistogramOpts {
|
||||
h := HistogramOpts{}
|
||||
if tag != nil {
|
||||
t := reflect.StructTag(strings.Trim(tag.Value, "`"))
|
||||
if v := t.Get(bucketTypeTag); v != "" {
|
||||
h.BucketType = bucketType[v]
|
||||
}
|
||||
if v := t.Get(bucketSizeTag); v != "" {
|
||||
h.BucketSizes = v
|
||||
}
|
||||
}
|
||||
return h
|
||||
}
|
||||
|
||||
func extractMetricsPackageName(imports []*ast.ImportSpec) (string, error) {
|
||||
for _, i := range imports {
|
||||
u, err := strconv.Unquote(i.Path.Value)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if u == metricsPackageName {
|
||||
if i.Name != nil {
|
||||
return i.Name.Name, nil
|
||||
}
|
||||
return path.Base(u), nil
|
||||
}
|
||||
}
|
||||
return "", nil
|
||||
}
|
||||
|
||||
var capitalChange = regexp.MustCompile("([a-z0-9])([A-Z])")
|
||||
|
||||
func toSnakeCase(str string) string {
|
||||
snake := capitalChange.ReplaceAllString(str, "${1}_${2}")
|
||||
return strings.ToLower(snake)
|
||||
}
|
||||
259
scripts/metricsgen/metricsgen_test.go
Normal file
259
scripts/metricsgen/metricsgen_test.go
Normal file
@@ -0,0 +1,259 @@
|
||||
package main_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"go/parser"
|
||||
"go/token"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
metricsgen "github.com/tendermint/tendermint/scripts/metricsgen"
|
||||
)
|
||||
|
||||
const testDataDir = "./testdata"
|
||||
|
||||
func TestSimpleTemplate(t *testing.T) {
|
||||
m := metricsgen.ParsedMetricField{
|
||||
TypeName: "Histogram",
|
||||
FieldName: "MyMetric",
|
||||
MetricName: "request_count",
|
||||
Description: "how many requests were made since the start of the process",
|
||||
Labels: "first, second, third",
|
||||
}
|
||||
td := metricsgen.TemplateData{
|
||||
Package: "mypack",
|
||||
ParsedMetrics: []metricsgen.ParsedMetricField{m},
|
||||
}
|
||||
b := bytes.NewBuffer([]byte{})
|
||||
err := metricsgen.GenerateMetricsFile(b, td)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to parse template %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFromData(t *testing.T) {
|
||||
infos, err := ioutil.ReadDir(testDataDir)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to open file %v", err)
|
||||
}
|
||||
for _, dir := range infos {
|
||||
t.Run(dir.Name(), func(t *testing.T) {
|
||||
if !dir.IsDir() {
|
||||
t.Fatalf("expected file %s to be directory", dir.Name())
|
||||
}
|
||||
dirName := path.Join(testDataDir, dir.Name())
|
||||
pt, err := metricsgen.ParseMetricsDir(dirName, "Metrics")
|
||||
if err != nil {
|
||||
t.Fatalf("unable to parse from dir %q: %v", dir, err)
|
||||
}
|
||||
outFile := path.Join(dirName, "out.go")
|
||||
if err != nil {
|
||||
t.Fatalf("unable to open file %s: %v", outFile, err)
|
||||
}
|
||||
of, err := os.Create(outFile)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to open file %s: %v", outFile, err)
|
||||
}
|
||||
defer os.Remove(outFile)
|
||||
if err := metricsgen.GenerateMetricsFile(of, pt); err != nil {
|
||||
t.Fatalf("unable to generate metrics file %s: %v", outFile, err)
|
||||
}
|
||||
if _, err := parser.ParseFile(token.NewFileSet(), outFile, nil, parser.AllErrors); err != nil {
|
||||
t.Fatalf("unable to parse generated file %s: %v", outFile, err)
|
||||
}
|
||||
bNew, err := ioutil.ReadFile(outFile)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to read generated file %s: %v", outFile, err)
|
||||
}
|
||||
goldenFile := path.Join(dirName, "metrics.gen.go")
|
||||
bOld, err := ioutil.ReadFile(goldenFile)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to read file %s: %v", goldenFile, err)
|
||||
}
|
||||
if !bytes.Equal(bNew, bOld) {
|
||||
t.Fatalf("newly generated code in file %s does not match golden file %s\n"+
|
||||
"if the output of the metricsgen tool is expected to change run the following make target: \n"+
|
||||
"\tmake metrics", outFile, goldenFile)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseMetricsStruct(t *testing.T) {
|
||||
const pkgName = "mypkg"
|
||||
metricsTests := []struct {
|
||||
name string
|
||||
shouldError bool
|
||||
metricsStruct string
|
||||
expected metricsgen.TemplateData
|
||||
}{
|
||||
{
|
||||
name: "basic",
|
||||
metricsStruct: `type Metrics struct {
|
||||
myGauge metrics.Gauge
|
||||
}`,
|
||||
expected: metricsgen.TemplateData{
|
||||
Package: pkgName,
|
||||
ParsedMetrics: []metricsgen.ParsedMetricField{
|
||||
{
|
||||
TypeName: "Gauge",
|
||||
FieldName: "myGauge",
|
||||
MetricName: "my_gauge",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "histogram",
|
||||
metricsStruct: "type Metrics struct {\n" +
|
||||
"myHistogram metrics.Histogram `metrics_buckettype:\"exp\" metrics_bucketsizes:\"1, 100, .8\"`\n" +
|
||||
"}",
|
||||
expected: metricsgen.TemplateData{
|
||||
Package: pkgName,
|
||||
ParsedMetrics: []metricsgen.ParsedMetricField{
|
||||
{
|
||||
TypeName: "Histogram",
|
||||
FieldName: "myHistogram",
|
||||
MetricName: "my_histogram",
|
||||
|
||||
HistogramOptions: metricsgen.HistogramOpts{
|
||||
BucketType: "stdprometheus.ExponentialBuckets",
|
||||
BucketSizes: "1, 100, .8",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "labeled name",
|
||||
metricsStruct: "type Metrics struct {\n" +
|
||||
"myCounter metrics.Counter `metrics_name:\"new_name\"`\n" +
|
||||
"}",
|
||||
expected: metricsgen.TemplateData{
|
||||
Package: pkgName,
|
||||
ParsedMetrics: []metricsgen.ParsedMetricField{
|
||||
{
|
||||
TypeName: "Counter",
|
||||
FieldName: "myCounter",
|
||||
MetricName: "new_name",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "metric labels",
|
||||
metricsStruct: "type Metrics struct {\n" +
|
||||
"myCounter metrics.Counter `metrics_labels:\"label1, label2\"`\n" +
|
||||
"}",
|
||||
expected: metricsgen.TemplateData{
|
||||
Package: pkgName,
|
||||
ParsedMetrics: []metricsgen.ParsedMetricField{
|
||||
{
|
||||
TypeName: "Counter",
|
||||
FieldName: "myCounter",
|
||||
MetricName: "my_counter",
|
||||
Labels: "label1, label2",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ignore non-metric field",
|
||||
metricsStruct: `type Metrics struct {
|
||||
myCounter metrics.Counter
|
||||
nonMetric string
|
||||
}`,
|
||||
expected: metricsgen.TemplateData{
|
||||
Package: pkgName,
|
||||
ParsedMetrics: []metricsgen.ParsedMetricField{
|
||||
{
|
||||
TypeName: "Counter",
|
||||
FieldName: "myCounter",
|
||||
MetricName: "my_counter",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, testCase := range metricsTests {
|
||||
t.Run(testCase.name, func(t *testing.T) {
|
||||
dir, err := os.MkdirTemp(os.TempDir(), "metricsdir")
|
||||
if err != nil {
|
||||
t.Fatalf("unable to create directory: %v", err)
|
||||
}
|
||||
defer os.Remove(dir)
|
||||
f, err := os.Create(filepath.Join(dir, "metrics.go"))
|
||||
if err != nil {
|
||||
t.Fatalf("unable to open file: %v", err)
|
||||
}
|
||||
pkgLine := fmt.Sprintf("package %s\n", pkgName)
|
||||
importClause := `
|
||||
import(
|
||||
"github.com/go-kit/kit/metrics"
|
||||
)
|
||||
`
|
||||
|
||||
_, err = io.WriteString(f, pkgLine)
|
||||
require.NoError(t, err)
|
||||
_, err = io.WriteString(f, importClause)
|
||||
require.NoError(t, err)
|
||||
_, err = io.WriteString(f, testCase.metricsStruct)
|
||||
require.NoError(t, err)
|
||||
|
||||
td, err := metricsgen.ParseMetricsDir(dir, "Metrics")
|
||||
if testCase.shouldError {
|
||||
require.Error(t, err)
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, testCase.expected, td)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseAliasedMetric(t *testing.T) {
|
||||
aliasedData := `
|
||||
package mypkg
|
||||
|
||||
import(
|
||||
mymetrics "github.com/go-kit/kit/metrics"
|
||||
)
|
||||
type Metrics struct {
|
||||
m mymetrics.Gauge
|
||||
}
|
||||
`
|
||||
dir, err := os.MkdirTemp(os.TempDir(), "metricsdir")
|
||||
if err != nil {
|
||||
t.Fatalf("unable to create directory: %v", err)
|
||||
}
|
||||
defer os.Remove(dir)
|
||||
f, err := os.Create(filepath.Join(dir, "metrics.go"))
|
||||
if err != nil {
|
||||
t.Fatalf("unable to open file: %v", err)
|
||||
}
|
||||
_, err = io.WriteString(f, aliasedData)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to write to file: %v", err)
|
||||
}
|
||||
td, err := metricsgen.ParseMetricsDir(dir, "Metrics")
|
||||
require.NoError(t, err)
|
||||
|
||||
expected :=
|
||||
metricsgen.TemplateData{
|
||||
Package: "mypkg",
|
||||
ParsedMetrics: []metricsgen.ParsedMetricField{
|
||||
{
|
||||
TypeName: "Gauge",
|
||||
FieldName: "m",
|
||||
MetricName: "m",
|
||||
},
|
||||
},
|
||||
}
|
||||
require.Equal(t, expected, td)
|
||||
}
|
||||
30
scripts/metricsgen/testdata/basic/metrics.gen.go
vendored
Normal file
30
scripts/metricsgen/testdata/basic/metrics.gen.go
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
// Code generated by metricsgen. DO NOT EDIT.
|
||||
|
||||
package basic
|
||||
|
||||
import (
|
||||
"github.com/go-kit/kit/metrics/discard"
|
||||
prometheus "github.com/go-kit/kit/metrics/prometheus"
|
||||
stdprometheus "github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
func PrometheusMetrics(namespace string, labelsAndValues ...string) *Metrics {
|
||||
labels := []string{}
|
||||
for i := 0; i < len(labelsAndValues); i += 2 {
|
||||
labels = append(labels, labelsAndValues[i])
|
||||
}
|
||||
return &Metrics{
|
||||
Height: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{
|
||||
Namespace: namespace,
|
||||
Subsystem: MetricsSubsystem,
|
||||
Name: "height",
|
||||
Help: "simple metric that tracks the height of the chain.",
|
||||
}, labels).With(labelsAndValues...),
|
||||
}
|
||||
}
|
||||
|
||||
func NopMetrics() *Metrics {
|
||||
return &Metrics{
|
||||
Height: discard.NewGauge(),
|
||||
}
|
||||
}
|
||||
11
scripts/metricsgen/testdata/basic/metrics.go
vendored
Normal file
11
scripts/metricsgen/testdata/basic/metrics.go
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
package basic
|
||||
|
||||
import "github.com/go-kit/kit/metrics"
|
||||
|
||||
//go:generate go run ../../../../scripts/metricsgen -struct=Metrics
|
||||
|
||||
// Metrics contains metrics exposed by this package.
|
||||
type Metrics struct {
|
||||
// simple metric that tracks the height of the chain.
|
||||
Height metrics.Gauge
|
||||
}
|
||||
30
scripts/metricsgen/testdata/commented/metrics.gen.go
vendored
Normal file
30
scripts/metricsgen/testdata/commented/metrics.gen.go
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
// Code generated by metricsgen. DO NOT EDIT.
|
||||
|
||||
package commented
|
||||
|
||||
import (
|
||||
"github.com/go-kit/kit/metrics/discard"
|
||||
prometheus "github.com/go-kit/kit/metrics/prometheus"
|
||||
stdprometheus "github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
func PrometheusMetrics(namespace string, labelsAndValues ...string) *Metrics {
|
||||
labels := []string{}
|
||||
for i := 0; i < len(labelsAndValues); i += 2 {
|
||||
labels = append(labels, labelsAndValues[i])
|
||||
}
|
||||
return &Metrics{
|
||||
Field: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{
|
||||
Namespace: namespace,
|
||||
Subsystem: MetricsSubsystem,
|
||||
Name: "field",
|
||||
Help: "Height of the chain.We expect multi-line comments to parse correctly.",
|
||||
}, labels).With(labelsAndValues...),
|
||||
}
|
||||
}
|
||||
|
||||
func NopMetrics() *Metrics {
|
||||
return &Metrics{
|
||||
Field: discard.NewGauge(),
|
||||
}
|
||||
}
|
||||
11
scripts/metricsgen/testdata/commented/metrics.go
vendored
Normal file
11
scripts/metricsgen/testdata/commented/metrics.go
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
package commented
|
||||
|
||||
import "github.com/go-kit/kit/metrics"
|
||||
|
||||
//go:generate go run ../../../../scripts/metricsgen -struct=Metrics
|
||||
|
||||
type Metrics struct {
|
||||
// Height of the chain.
|
||||
// We expect multi-line comments to parse correctly.
|
||||
Field metrics.Gauge
|
||||
}
|
||||
54
scripts/metricsgen/testdata/tags/metrics.gen.go
vendored
Normal file
54
scripts/metricsgen/testdata/tags/metrics.gen.go
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
// Code generated by metricsgen. DO NOT EDIT.
|
||||
|
||||
package tags
|
||||
|
||||
import (
|
||||
"github.com/go-kit/kit/metrics/discard"
|
||||
prometheus "github.com/go-kit/kit/metrics/prometheus"
|
||||
stdprometheus "github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
func PrometheusMetrics(namespace string, labelsAndValues ...string) *Metrics {
|
||||
labels := []string{}
|
||||
for i := 0; i < len(labelsAndValues); i += 2 {
|
||||
labels = append(labels, labelsAndValues[i])
|
||||
}
|
||||
return &Metrics{
|
||||
WithLabels: prometheus.NewCounterFrom(stdprometheus.CounterOpts{
|
||||
Namespace: namespace,
|
||||
Subsystem: MetricsSubsystem,
|
||||
Name: "with_labels",
|
||||
Help: "",
|
||||
}, append(labels, "step,time")).With(labelsAndValues...), WithExpBuckets: prometheus.NewHistogramFrom(stdprometheus.HistogramOpts{
|
||||
Namespace: namespace,
|
||||
Subsystem: MetricsSubsystem,
|
||||
Name: "with_exp_buckets",
|
||||
Help: "",
|
||||
|
||||
Buckets: stdprometheus.ExponentialBuckets(.1, 100, 8),
|
||||
}, labels).With(labelsAndValues...),
|
||||
WithBuckets: prometheus.NewHistogramFrom(stdprometheus.HistogramOpts{
|
||||
Namespace: namespace,
|
||||
Subsystem: MetricsSubsystem,
|
||||
Name: "with_buckets",
|
||||
Help: "",
|
||||
|
||||
Buckets: []float64{1, 2, 3, 4, 5},
|
||||
}, labels).With(labelsAndValues...),
|
||||
Named: prometheus.NewCounterFrom(stdprometheus.CounterOpts{
|
||||
Namespace: namespace,
|
||||
Subsystem: MetricsSubsystem,
|
||||
Name: "metric_with_name",
|
||||
Help: "",
|
||||
}, labels).With(labelsAndValues...),
|
||||
}
|
||||
}
|
||||
|
||||
func NopMetrics() *Metrics {
|
||||
return &Metrics{
|
||||
WithLabels: discard.NewCounter(),
|
||||
WithExpBuckets: discard.NewHistogram(),
|
||||
WithBuckets: discard.NewHistogram(),
|
||||
Named: discard.NewCounter(),
|
||||
}
|
||||
}
|
||||
12
scripts/metricsgen/testdata/tags/metrics.go
vendored
Normal file
12
scripts/metricsgen/testdata/tags/metrics.go
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
package tags
|
||||
|
||||
import "github.com/go-kit/kit/metrics"
|
||||
|
||||
//go:generate go run ../../../../scripts/metricsgen -struct=Metrics
|
||||
|
||||
type Metrics struct {
|
||||
WithLabels metrics.Counter `metrics_labels:"step,time"`
|
||||
WithExpBuckets metrics.Histogram `metrics_buckettype:"exp" metrics_bucketsizes:".1,100,8"`
|
||||
WithBuckets metrics.Histogram `metrics_bucketsizes:"1, 2, 3, 4, 5"`
|
||||
Named metrics.Counter `metrics_name:"metric_with_name"`
|
||||
}
|
||||
Reference in New Issue
Block a user