Skip to content
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

Apply new experimental metrics builder to hostmetrics/cpu scraper #6418

Merged
merged 1 commit into from
Dec 2, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions cmd/mdatagen/loader.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,20 @@ func (mn metricName) Render() (string, error) {
return formatIdentifier(string(mn), true)
}

func (mn metricName) RenderUnexported() (string, error) {
return formatIdentifier(string(mn), false)
}

type attributeName string

func (mn attributeName) Render() (string, error) {
return formatIdentifier(string(mn), true)
}

type metric struct {
// Enabled defines whether the metric is enabled by default.
Enabled bool `yaml:"enabled"`

// Description of the metric.
Description string `validate:"required,notblank"`

Expand Down Expand Up @@ -98,6 +105,8 @@ type templateContext struct {
metadata
// Package name for generated code.
Package string
// ExpFileNote contains a note about experimental metrics builder.
ExpFileNote string
}

func loadMetadata(ymlData []byte) (metadata, error) {
Expand Down
38 changes: 29 additions & 9 deletions cmd/mdatagen/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,23 @@ import (
"text/template"
)

const (
tmplFileV1 = "metrics.tmpl"
outputFileV1 = "generated_metrics.go"
tmplFileV2 = "metrics_v2.tmpl"
outputFileV2 = "generated_metrics_v2.go"
)

func main() {
useExpGen := flag.Bool("experimental-gen", false, "Use experimental generator")
flag.Parse()
yml := flag.Arg(0)
if err := run(yml); err != nil {
if err := run(yml, *useExpGen); err != nil {
log.Fatal(err)
}
}

func run(ymlPath string) error {
func run(ymlPath string, useExpGen bool) error {
if ymlPath == "" {
return errors.New("argument must be metadata.yaml file")
}
Expand All @@ -61,22 +69,29 @@ func run(ymlPath string) error {
}
thisDir := path.Dir(filename)

if err = generateMetrics(ymlDir, thisDir, md); err != nil {
if err = generateMetrics(ymlDir, thisDir, md, useExpGen); err != nil {
return err
}
return generateDocumentation(ymlDir, thisDir, md)
}

func generateMetrics(ymlDir string, thisDir string, md metadata) error {
func generateMetrics(ymlDir string, thisDir string, md metadata, useExpGen bool) error {
tmplFile := tmplFileV1
outputFile := outputFileV1
if useExpGen {
tmplFile = tmplFileV2
outputFile = outputFileV2
}

tmpl := template.Must(
template.
New("metrics.tmpl").
New(tmplFile).
Option("missingkey=error").
Funcs(map[string]interface{}{
"publicVar": func(s string) (string, error) {
return formatIdentifier(s, true)
},
}).ParseFiles(path.Join(thisDir, "metrics.tmpl")))
}).ParseFiles(path.Join(thisDir, tmplFile)))
buf := bytes.Buffer{}

if err := tmpl.Execute(&buf, templateContext{metadata: md, Package: "metadata"}); err != nil {
Expand All @@ -95,12 +110,17 @@ func generateMetrics(ymlDir string, thisDir string, md metadata) error {
}

outputDir := path.Join(ymlDir, "internal", "metadata")
outputFile := path.Join(outputDir, "generated_metrics.go")
if err := os.MkdirAll(outputDir, 0700); err != nil {
return fmt.Errorf("unable to create output directory %q: %v", outputDir, err)
}
if err := ioutil.WriteFile(outputFile, formatted, 0600); err != nil {
return fmt.Errorf("failed writing %q: %v", outputFile, err)
for _, f := range []string{path.Join(outputDir, outputFileV1), path.Join(outputDir, outputFileV2)} {
if err := os.Remove(f); err != nil && !errors.Is(err, os.ErrNotExist) {
return fmt.Errorf("unable to remove genererated file %q: %v", f, err)
}
}
outputFilepath := path.Join(outputDir, outputFile)
if err := ioutil.WriteFile(outputFilepath, formatted, 0600); err != nil {
return fmt.Errorf("failed writing %q: %v", outputFilepath, err)
}

return nil
Expand Down
25 changes: 19 additions & 6 deletions cmd/mdatagen/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,15 @@ metrics:
unit: s
sum:
aggregation: cumulative
number_type: double
attributes: []
`
)

func Test_runContents(t *testing.T) {
type args struct {
yml string
yml string
useExpGen bool
}
tests := []struct {
name string
Expand All @@ -49,12 +51,17 @@ func Test_runContents(t *testing.T) {
}{
{
name: "valid metadata",
args: args{validMetadata},
args: args{validMetadata, false},
want: "",
},
{
name: "valid metadata v2",
args: args{validMetadata, true},
want: "",
},
{
name: "invalid yaml",
args: args{"invalid"},
args: args{"invalid", false},
want: "",
wantErr: "cannot unmarshal",
},
Expand All @@ -70,13 +77,19 @@ func Test_runContents(t *testing.T) {
metadataFile := path.Join(tmpdir, "metadata.yaml")
require.NoError(t, ioutil.WriteFile(metadataFile, []byte(tt.args.yml), 0600))

err = run(metadataFile)
err = run(metadataFile, tt.args.useExpGen)

if tt.wantErr != "" {
require.Regexp(t, tt.wantErr, err)
} else {
require.NoError(t, err)
require.FileExists(t, path.Join(tmpdir, "internal/metadata/generated_metrics.go"))

genFilePath := path.Join(tmpdir, "internal/metadata/generated_metrics.go")
if tt.args.useExpGen {
genFilePath = path.Join(tmpdir, "internal/metadata/generated_metrics_v2.go")
}
require.FileExists(t, genFilePath)

require.FileExists(t, path.Join(tmpdir, "documentation.md"))
}
})
Expand Down Expand Up @@ -105,7 +118,7 @@ func Test_run(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if err := run(tt.args.ymlPath); (err != nil) != tt.wantErr {
if err := run(tt.args.ymlPath, false); (err != nil) != tt.wantErr {
t.Errorf("run() error = %v, wantErr %v", err, tt.wantErr)
}
})
Expand Down
47 changes: 45 additions & 2 deletions cmd/mdatagen/metricdata.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@

package main

import (
"fmt"
"strings"
)

var (
_ MetricData = &gauge{}
_ MetricData = &sum{}
Expand All @@ -25,6 +30,7 @@ type MetricData interface {
Type() string
HasMonotonic() bool
HasAggregated() bool
HasNumberDataPoints() bool
}

// Aggregated defines a metric aggregation type.
Expand Down Expand Up @@ -52,6 +58,30 @@ type Mono struct {
Monotonic bool `yaml:"monotonic"`
}

// NumberDataPoints defines the metric number type.
type NumberDataPoints struct {
// Type is type of the metric number, options are "double", "int".
// TODO: Add validation once the metric number type added to all metadata files.
NumberType string `yaml:"number_type"`
}

// Type returns name of the datapoint type.
func (ndp NumberDataPoints) Type() string {
return strings.Title(ndp.NumberType)
}

// BasicType returns name of a golang basic type for the datapoint type.
func (ndp NumberDataPoints) BasicType() string {
switch ndp.NumberType {
case "int":
return "int64"
case "double":
return "float64"
default:
panic(fmt.Sprintf("unknown number data point type: %v", ndp.NumberType))
}
}

type gauge struct {
}

Expand All @@ -67,9 +97,14 @@ func (d gauge) HasAggregated() bool {
return false
}

func (d gauge) HasNumberDataPoints() bool {
return true
}

type sum struct {
Aggregated `yaml:",inline"`
Mono `yaml:",inline"`
Aggregated `yaml:",inline"`
Mono `yaml:",inline"`
NumberDataPoints `yaml:",inline"`
}

func (d sum) Type() string {
Expand All @@ -84,6 +119,10 @@ func (d sum) HasAggregated() bool {
return true
}

func (d sum) HasNumberDataPoints() bool {
return true
}

type histogram struct {
Aggregated `yaml:",inline"`
}
Expand All @@ -99,3 +138,7 @@ func (d histogram) HasMonotonic() bool {
func (d histogram) HasAggregated() bool {
return true
}

func (d histogram) HasNumberDataPoints() bool {
return false
}
Loading