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

Follow up for Add automated documentation for metrics #6588

Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,10 @@ import (
"github.com/operator-framework/operator-sdk/hack/generate/samples/internal/pkg"
)

// Memcached defines the Memcached Sample in GO using webhooks and monitoring code
// monitoringString is appended to logs and error messages to signify the inclusion of monitoring
const monitoringString = " and monitoring"

// Memcached defines the Memcached Sample in GO using webhooks or webhooks and monitoring code
type Memcached struct {
ctx *pkg.SampleContext
}
Expand All @@ -39,25 +42,36 @@ var prometheusAPIVersion = "v0.59.0"
// GenerateSample will call all actions to create the directory and generate the sample
// Note that it should NOT be called in the e2e tests.
func GenerateSample(binaryPath, samplesPath string) {
log.Infof("starting to generate Go memcached sample with webhooks and metrics documentation")
ctx, err := pkg.NewSampleContext(binaryPath, filepath.Join(samplesPath, "memcached-operator"), "GO111MODULE=on")
pkg.CheckError("generating Go memcached with webhooks and metrics documentation context", err)
generateWithMonitoring = strings.HasSuffix(samplesPath, "monitoring")

logInfo := "starting to generate Go memcached sample with webhooks"
errorInfo := "generating Go memcached with context: webhooks"

generateWithMonitoring = false
if strings.HasSuffix(samplesPath, "monitoring") {
generateWithMonitoring = true
if generateWithMonitoring {
logInfo += monitoringString
errorInfo += monitoringString
}

log.Infof(logInfo)
ctx, err := pkg.NewSampleContext(binaryPath, filepath.Join(samplesPath, "memcached-operator"), "GO111MODULE=on")
pkg.CheckError(errorInfo, err)

memcached := Memcached{&ctx}
memcached.Prepare()
memcached.Run()
}

// Prepare the Context for the Memcached with webhooks and metrics documentation Go Sample
// Prepare the Context for the Memcached with webhooks or with webhooks and monitoring Go Sample
// Note that sample directory will be re-created and the context data for the sample
// will be set such as the domain and GVK.
func (mh *Memcached) Prepare() {
log.Infof("destroying directory for Memcached with webhooks and metrics documentation Go samples")
logInfo := "destroying directory for Go Memcached sample with webhooks"

if generateWithMonitoring {
logInfo += monitoringString
}

log.Infof(logInfo)
mh.ctx.Destroy()

log.Infof("creating directory")
Expand All @@ -71,7 +85,7 @@ func (mh *Memcached) Prepare() {
mh.ctx.Kind = "Memcached"
}

// Run the steps to create the Memcached with metrics and webhooks Go Sample
// Run the steps to create the Memcached with webhooks or with webhooks and monitoring Go Sample
func (mh *Memcached) Run() {

if !mh.isV3() {
Expand Down Expand Up @@ -930,105 +944,45 @@ const metricsdocsFragment = `
package main

import (
"bytes"
"fmt"
"sort"
"text/template"

"github.com/example/memcached-operator/monitoring"
)

// please run "make generate-metricsdocs" to run this tool and update metrics documentation
const (
title = "# Operator Metrics\n"
background = "This document aims to help users that are not familiar with metrics exposed by this operator.\n" +
"The metrics documentation is auto-generated by the utility tool \"monitoring/metricsdocs\" and reflects all of the metrics that are exposed by the operator.\n\n"

KVSpecificMetrics = "## Operator Metrics List\n"

opening = title +
background +
KVSpecificMetrics

// footer
footerHeading = "## Developing new metrics\n"
footerContent = "After developing new metrics or changing old ones, please run \"make generate-metricsdocs\" to regenerate this document.\n\n" +
"If you feel that the new metric doesn't follow these rules, please change \"monitoring/metricsdocs\" according to your needs.\n"

footer = footerHeading + footerContent
)

// TODO: scaffolding these helpers with operator-lib: https://github.com/operator-framework/operator-lib.

// metricList contains the name, description, and type for each metric.
func main() {
metricList := metricDescriptionListToMetricList(monitoring.ListMetrics())
sort.Sort(metricList)
writeToStdOut(metricList)
}
metricDescriptions := monitoring.ListMetrics()
sort.Slice(metricDescriptions, func(i, j int) bool {
return metricDescriptions[i].Name < metricDescriptions[j].Name
})

tmpl, err := template.New("Operator metrics").Parse("# Operator Metrics\n" +
"This document aims to help users that are not familiar with metrics exposed by this operator.\n" +
"The metrics documentation is auto-generated by the utility tool \"monitoring/metricsdocs\" and reflects all of the metrics that are exposed by the operator.\n\n" +
"## Operator Metrics List" +
"{{range .}}\n" +
"### {{.Name}}\n" +
"{{.Help}} " +
"Type: {{.Type}}.\n" +
"{{end}}" +
"## Developing new metrics\n" +
"After developing new metrics or changing old ones, please run \"make generate-metricsdocs\" to regenerate this document.\n\n" +
"If you feel that the new metric doesn't follow these rules, please change \"monitoring/metricsdocs\" according to your needs.")

// writeToStdOut receives a list of metrics and prints them to STDOUT.
func writeToStdOut(metricsList metricList) {
fmt.Print(opening)
metricsList.writeOut()
fmt.Print(footer)
}

// Metric is an exported struct that defines the metric
// name, description, and type as a new type named Metric.
type Metric struct {
name string
description string
metricType string
}

func metricDescriptionToMetric(md monitoring.MetricDescription) Metric {
return Metric{
name: md.Name,
description: md.Help,
metricType: md.Type,
if err != nil {
panic(err)
}
}

// writeOut receives a metric of type metric and prints
// the metric name, description, and type.
func (m Metric) writeOut() {
fmt.Println("###", m.name)
fmt.Println(m.description, "Type: "+m.metricType+".")
}

// metricList is an array that contain metrics from type metric,
// as a new type named metricList.
type metricList []Metric

// metricDescriptionListToMetricList collects the metrics exposed by the
// operator, and inserts them into the metricList array.
func metricDescriptionListToMetricList(mdl []monitoring.MetricDescription) metricList {
res := make([]Metric, len(mdl))
for i, md := range mdl {
res[i] = metricDescriptionToMetric(md)
// generate the template using the sorted list of metrics
var buf bytes.Buffer
if err := tmpl.Execute(&buf, metricDescriptions); err != nil {
panic(err)
}

return res
}

// Len implements sort.Interface.Len
func (m metricList) Len() int {
return len(m)
}

// Less implements sort.Interface.Less
func (m metricList) Less(i, j int) bool {
return m[i].name < m[j].name
}

// Swap implements sort.Interface.Swap
func (m metricList) Swap(i, j int) {
m[i], m[j] = m[j], m[i]
}

func (m metricList) writeOut() {
for _, met := range m {
met.writeOut()
}
// print the generated metrics documentation
fmt.Println(buf.String())
}
`

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,103 +17,43 @@ limitations under the License.
package main

import (
"bytes"
"fmt"
"sort"
"text/template"

"github.com/example/memcached-operator/monitoring"
)

// please run "make generate-metricsdocs" to run this tool and update metrics documentation
const (
title = "# Operator Metrics\n"
background = "This document aims to help users that are not familiar with metrics exposed by this operator.\n" +
"The metrics documentation is auto-generated by the utility tool \"monitoring/metricsdocs\" and reflects all of the metrics that are exposed by the operator.\n\n"

KVSpecificMetrics = "## Operator Metrics List\n"

opening = title +
background +
KVSpecificMetrics

// footer
footerHeading = "## Developing new metrics\n"
footerContent = "After developing new metrics or changing old ones, please run \"make generate-metricsdocs\" to regenerate this document.\n\n" +
"If you feel that the new metric doesn't follow these rules, please change \"monitoring/metricsdocs\" according to your needs.\n"

footer = footerHeading + footerContent
)

// TODO: scaffolding these helpers with operator-lib: https://github.com/operator-framework/operator-lib.

// metricList contains the name, description, and type for each metric.
func main() {
metricList := metricDescriptionListToMetricList(monitoring.ListMetrics())
sort.Sort(metricList)
writeToStdOut(metricList)
}

// writeToStdOut receives a list of metrics and prints them to STDOUT.
func writeToStdOut(metricsList metricList) {
fmt.Print(opening)
metricsList.writeOut()
fmt.Print(footer)
}

// Metric is an exported struct that defines the metric
// name, description, and type as a new type named Metric.
type Metric struct {
name string
description string
metricType string
}

func metricDescriptionToMetric(md monitoring.MetricDescription) Metric {
return Metric{
name: md.Name,
description: md.Help,
metricType: md.Type,
metricDescriptions := monitoring.ListMetrics()
sort.Slice(metricDescriptions, func(i, j int) bool {
return metricDescriptions[i].Name < metricDescriptions[j].Name
})

tmpl, err := template.New("Operator metrics").Parse("# Operator Metrics\n" +
"This document aims to help users that are not familiar with metrics exposed by this operator.\n" +
"The metrics documentation is auto-generated by the utility tool \"monitoring/metricsdocs\" and reflects all of the metrics that are exposed by the operator.\n\n" +
"## Operator Metrics List" +
"{{range .}}\n" +
"### {{.Name}}\n" +
"{{.Help}} " +
"Type: {{.Type}}.\n" +
"{{end}}" +
"## Developing new metrics\n" +
"After developing new metrics or changing old ones, please run \"make generate-metricsdocs\" to regenerate this document.\n\n" +
"If you feel that the new metric doesn't follow these rules, please change \"monitoring/metricsdocs\" according to your needs.")

if err != nil {
panic(err)
}
}

// writeOut receives a metric of type metric and prints
// the metric name, description, and type.
func (m Metric) writeOut() {
fmt.Println("###", m.name)
fmt.Println(m.description, "Type: "+m.metricType+".")
}

// metricList is an array that contain metrics from type metric,
// as a new type named metricList.
type metricList []Metric

// metricDescriptionListToMetricList collects the metrics exposed by the
// operator, and inserts them into the metricList array.
func metricDescriptionListToMetricList(mdl []monitoring.MetricDescription) metricList {
res := make([]Metric, len(mdl))
for i, md := range mdl {
res[i] = metricDescriptionToMetric(md)
// generate the template using the sorted list of metrics
var buf bytes.Buffer
if err := tmpl.Execute(&buf, metricDescriptions); err != nil {
panic(err)
}

return res
}

// Len implements sort.Interface.Len
func (m metricList) Len() int {
return len(m)
}

// Less implements sort.Interface.Less
func (m metricList) Less(i, j int) bool {
return m[i].name < m[j].name
}

// Swap implements sort.Interface.Swap
func (m metricList) Swap(i, j int) {
m[i], m[j] = m[j], m[i]
}

func (m metricList) writeOut() {
for _, met := range m {
met.writeOut()
}
// print the generated metrics documentation
fmt.Println(buf.String())
}
Loading
Loading