Skip to content

Commit

Permalink
Apply new experimental metrics builder for hostmetrics/cpu scraper
Browse files Browse the repository at this point in the history
Introduce new experimental metrics builder interface for metrics scrapers and apply it to hostmetrics/cpu scraper.
  • Loading branch information
dmitryax committed Dec 1, 2021
1 parent dd24470 commit 21114a8
Show file tree
Hide file tree
Showing 17 changed files with 586 additions and 219 deletions.
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

0 comments on commit 21114a8

Please sign in to comment.