k8s.io/kubernetes@v1.29.3/test/instrumentation/documentation/main.go (about)

     1  /*
     2  Copyright 2020 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package main
    18  
    19  import (
    20  	"bytes"
    21  	"fmt"
    22  	"os"
    23  	"sort"
    24  	"strings"
    25  	"text/template"
    26  	"time"
    27  
    28  	flag "github.com/spf13/pflag"
    29  	"gopkg.in/yaml.v2"
    30  
    31  	"k8s.io/component-base/metrics"
    32  )
    33  
    34  var (
    35  	GOROOT    string = os.Getenv("GOROOT")
    36  	GOOS      string = os.Getenv("GOOS")
    37  	KUBE_ROOT string = os.Getenv("KUBE_ROOT")
    38  	funcMap          = template.FuncMap{
    39  		"ToLower": strings.ToLower,
    40  	}
    41  )
    42  
    43  const (
    44  	templ = `---
    45  title: Kubernetes Metrics Reference
    46  content_type: reference
    47  auto_generated: true
    48  description: >-
    49    Details of the metric data that Kubernetes components export.
    50  ---
    51  
    52  ## Metrics (v{{.GeneratedVersion}})
    53  
    54  <!-- (auto-generated {{.GeneratedDate.Format "2006 Jan 02"}}) -->
    55  <!-- (auto-generated v{{.GeneratedVersion}}) -->
    56  This page details the metrics that different Kubernetes components export. You can query the metrics endpoint for these 
    57  components using an HTTP scrape, and fetch the current metrics data in Prometheus format.
    58  
    59  ### List of Stable Kubernetes Metrics
    60  
    61  Stable metrics observe strict API contracts and no labels can be added or removed from stable metrics during their lifetime.
    62  
    63  <div class="metrics">
    64  {{- range $index, $metric := .StableMetrics -}}
    65  	<div class="metric" data-stability="{{$metric.StabilityLevel | ToLower}}">
    66  	<div class="metric_name">{{with $metric}}{{.BuildFQName}}{{- end -}}</div>
    67  	<div class="metric_help">{{- $metric.Help -}}</div>
    68  	<ul>
    69  	<li><label class="metric_detail">Stability Level:</label><span class="metric_stability_level">{{- $metric.StabilityLevel -}}</span></li>
    70  	<li data-type="{{$metric.Type | ToLower}}"><label class="metric_detail">Type:</label> <span class="metric_type">{{- $metric.Type -}}</span></li>
    71  	{{if $metric.Labels }}<li class="metric_labels_varying"><label class="metric_detail">Labels:</label>{{range $label := $metric.Labels}}<span class="metric_label">{{- $label -}}</span>{{- end -}}</li>{{- end -}}
    72  	{{if $metric.ConstLabels }}<li class="metric_labels_constant"><label class="metric_detail">Const Labels:</label>{{range $key, $value := $metric.ConstLabels}}<span class="metric_label">{{$key}}:{{$value}}</span>{{- end -}}</li>{{- end -}}
    73  	{{if $metric.DeprecatedVersion }}<li class="metric_deprecated_version"><label class="metric_detail">Deprecated Versions:</label><span>{{- $metric.DeprecatedVersion -}}</span></li>{{- end -}}
    74  	</ul>
    75  	</div>{{end}}
    76  </div>
    77  
    78  ### List of Beta Kubernetes Metrics
    79  
    80  Beta metrics observe a looser API contract than its stable counterparts. No labels can be removed from beta metrics during their lifetime, however, labels can be added while the metric is in the beta stage. This offers the assurance that beta metrics will honor existing dashboards and alerts, while allowing for amendments in the future. 
    81  
    82  <div class="metrics">
    83  {{- range $index, $metric := .BetaMetrics -}}
    84  	<div class="metric" data-stability="{{$metric.StabilityLevel | ToLower}}">
    85  	<div class="metric_name">{{with $metric}}{{.BuildFQName}}{{- end -}}</div>
    86  	<div class="metric_help">{{- $metric.Help -}}</div>
    87  	<ul>
    88  	<li><label class="metric_detail">Stability Level:</label><span class="metric_stability_level">{{- $metric.StabilityLevel -}}</span></li>
    89  	<li data-type="{{$metric.Type | ToLower}}"><label class="metric_detail">Type:</label> <span class="metric_type">{{- $metric.Type -}}</span></li>
    90  	{{if $metric.Labels }}<li class="metric_labels_varying"><label class="metric_detail">Labels:</label>{{range $label := $metric.Labels}}<span class="metric_label">{{- $label -}}</span>{{- end -}}</li>{{- end -}}
    91  	{{if $metric.ConstLabels }}<li class="metric_labels_constant"><label class="metric_detail">Const Labels:</label>{{range $key, $value := $metric.ConstLabels}}<span class="metric_label">{{$key}}:{{$value}}</span>{{- end -}}</li>{{- end -}}
    92  	{{if $metric.DeprecatedVersion }}<li class="metric_deprecated_version"><label class="metric_detail">Deprecated Versions:</label><span>{{- $metric.DeprecatedVersion -}}</span></li>{{- end -}}
    93  	</ul>
    94  	</div>{{end}}
    95  </div>
    96  
    97  ### List of Alpha Kubernetes Metrics
    98  
    99  Alpha metrics do not have any API guarantees. These metrics must be used at your own risk, subsequent versions of Kubernetes may remove these metrics altogether, or mutate the API in such a way that breaks existing dashboards and alerts. 
   100  
   101  <div class="metrics">
   102  {{- range $index, $metric := .AlphaMetrics -}}
   103  	<div class="metric" data-stability="{{$metric.StabilityLevel | ToLower}}">
   104  	<div class="metric_name">{{with $metric}}{{.BuildFQName}}{{- end -}}</div>
   105  	<div class="metric_help">{{- $metric.Help -}}</div>
   106  	<ul>
   107  	<li><label class="metric_detail">Stability Level:</label><span class="metric_stability_level">{{- $metric.StabilityLevel -}}</span></li>
   108  	<li data-type="{{$metric.Type | ToLower}}"><label class="metric_detail">Type:</label> <span class="metric_type">{{- $metric.Type -}}</span></li>
   109  	{{if $metric.Labels }}<li class="metric_labels_varying"><label class="metric_detail">Labels:</label>{{range $label := $metric.Labels}}<span class="metric_label">{{- $label -}}</span>{{- end -}}</li>{{- end -}}
   110  	{{if $metric.ConstLabels }}<li class="metric_labels_constant"><label class="metric_detail">Const Labels:</label>{{range $key, $value := $metric.ConstLabels}}<span class="metric_label">{{$key}}:{{$value}}</span>{{- end -}}</li>{{- end -}}
   111  	{{if $metric.DeprecatedVersion }}<li class="metric_deprecated_version"><label class="metric_detail">Deprecated Versions:</label><span>{{- $metric.DeprecatedVersion -}}</span></li>{{- end -}}
   112  	</ul>
   113  	</div>{{end}}
   114  </div>
   115  `
   116  )
   117  
   118  type templateData struct {
   119  	AlphaMetrics     []metric
   120  	BetaMetrics      []metric
   121  	StableMetrics    []metric
   122  	GeneratedDate    time.Time
   123  	GeneratedVersion string
   124  }
   125  
   126  func main() {
   127  	var major string
   128  	var minor string
   129  	flag.StringVar(&major, "major", "", "k8s major version")
   130  	flag.StringVar(&minor, "minor", "", "k8s minor version")
   131  	flag.Parse()
   132  	println(major, minor)
   133  	dat, err := os.ReadFile("test/instrumentation/documentation/documentation-list.yaml")
   134  	if err == nil {
   135  		var parsedMetrics []metric
   136  		err = yaml.Unmarshal(dat, &parsedMetrics)
   137  		if err != nil {
   138  			println("err", err)
   139  		}
   140  		sort.Sort(byFQName(parsedMetrics))
   141  		t := template.New("t").Funcs(funcMap)
   142  		t, err := t.Parse(templ)
   143  		if err != nil {
   144  			println("err", err)
   145  		}
   146  		var tpl bytes.Buffer
   147  		for i, m := range parsedMetrics {
   148  			m.Help = strings.Join(strings.Split(m.Help, "\n"), ", ")
   149  			_ = m.BuildFQName() // ignore golint error
   150  			parsedMetrics[i] = m
   151  		}
   152  		sortedMetrics := byStabilityLevel(parsedMetrics)
   153  		data := templateData{
   154  			AlphaMetrics:     sortedMetrics["ALPHA"],
   155  			BetaMetrics:      sortedMetrics["BETA"],
   156  			StableMetrics:    sortedMetrics["STABLE"],
   157  			GeneratedDate:    time.Now(),
   158  			GeneratedVersion: fmt.Sprintf("%v.%v", major, parseMinor(minor)),
   159  		}
   160  		err = t.Execute(&tpl, data)
   161  		if err != nil {
   162  			println("err", err)
   163  		}
   164  		fmt.Print(tpl.String())
   165  	} else {
   166  		fmt.Fprintf(os.Stderr, "%s\n", err)
   167  	}
   168  
   169  }
   170  
   171  type metric struct {
   172  	Name              string              `yaml:"name" json:"name"`
   173  	Subsystem         string              `yaml:"subsystem,omitempty" json:"subsystem,omitempty"`
   174  	Namespace         string              `yaml:"namespace,omitempty" json:"namespace,omitempty"`
   175  	Help              string              `yaml:"help,omitempty" json:"help,omitempty"`
   176  	Type              string              `yaml:"type,omitempty" json:"type,omitempty"`
   177  	DeprecatedVersion string              `yaml:"deprecatedVersion,omitempty" json:"deprecatedVersion,omitempty"`
   178  	StabilityLevel    string              `yaml:"stabilityLevel,omitempty" json:"stabilityLevel,omitempty"`
   179  	Labels            []string            `yaml:"labels,omitempty" json:"labels,omitempty"`
   180  	Buckets           []float64           `yaml:"buckets,omitempty" json:"buckets,omitempty"`
   181  	Objectives        map[float64]float64 `yaml:"objectives,omitempty" json:"objectives,omitempty"`
   182  	AgeBuckets        uint32              `yaml:"ageBuckets,omitempty" json:"ageBuckets,omitempty"`
   183  	BufCap            uint32              `yaml:"bufCap,omitempty" json:"bufCap,omitempty"`
   184  	MaxAge            int64               `yaml:"maxAge,omitempty" json:"maxAge,omitempty"`
   185  	ConstLabels       map[string]string   `yaml:"constLabels,omitempty" json:"constLabels,omitempty"`
   186  }
   187  
   188  func (m metric) BuildFQName() string {
   189  	return metrics.BuildFQName(m.Namespace, m.Subsystem, m.Name)
   190  }
   191  
   192  type byFQName []metric
   193  
   194  func (ms byFQName) Len() int { return len(ms) }
   195  func (ms byFQName) Less(i, j int) bool {
   196  	if ms[i].StabilityLevel < ms[j].StabilityLevel {
   197  		return true
   198  	} else if ms[i].StabilityLevel > ms[j].StabilityLevel {
   199  		return false
   200  	}
   201  	return ms[i].BuildFQName() < ms[j].BuildFQName()
   202  }
   203  func (ms byFQName) Swap(i, j int) {
   204  	ms[i], ms[j] = ms[j], ms[i]
   205  }
   206  
   207  func byStabilityLevel(ms []metric) map[string][]metric {
   208  	res := map[string][]metric{}
   209  	for _, m := range ms {
   210  		if _, ok := res[m.StabilityLevel]; !ok {
   211  			res[m.StabilityLevel] = []metric{}
   212  		}
   213  		res[m.StabilityLevel] = append(res[m.StabilityLevel], m)
   214  	}
   215  	return res
   216  }
   217  
   218  func parseMinor(m string) string {
   219  	return strings.Trim(m, `+`)
   220  }