Skip to content

Commit

Permalink
Follow up for Add automated documentation for metrics
Browse files Browse the repository at this point in the history
-Update the readme to include monitoring

-Use go template in metricsdocs.go

- Add condition to the log messages
- Update the logs messages to use `and monitoring` only when needed.

Signed-off-by: Aviv Litman <[email protected]>
  • Loading branch information
avlitman authored and Aviv Litman committed Oct 2, 2023
1 parent d21ed64 commit 601b3f8
Show file tree
Hide file tree
Showing 5 changed files with 122 additions and 277 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import (
"github.com/operator-framework/operator-sdk/hack/generate/samples/internal/pkg"
)

// Memcached defines the Memcached Sample in GO using webhooks and monitoring code
// Memcached defines the Memcached Sample in GO using webhooks or webhooks and monitoring code
type Memcached struct {
ctx *pkg.SampleContext
}
Expand All @@ -39,25 +39,40 @@ 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 = false
if strings.HasSuffix(samplesPath, "monitoring") {
generateWithMonitoring = true
}

var logInfo, errorInfo string
if generateWithMonitoring {
logInfo = "starting to generate Go memcached sample with webhooks and monitoring"
errorInfo = "generating Go memcached with webhooks and monitoring context"
} else {
logInfo = "starting to generate Go memcached sample with webhooks"
errorInfo = "generating Go memcached with webhooks context"
}

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")
var logInfo string
if generateWithMonitoring {
logInfo = "destroying directory for Go Memcached sample with webhooks and monitoring"
} else {
logInfo = "destroying directory for Go Memcached sample with webhooks"
}
log.Infof(logInfo)
mh.ctx.Destroy()

log.Infof("creating directory")
Expand All @@ -71,7 +86,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 +945,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
11 changes: 8 additions & 3 deletions testdata/go/v3/monitoring/memcached-operator/README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# memcached-operator
// TODO(user): Add simple overview of use/purpose
# memcached-operator (with monitoring)
A Go-based Operator framework that has the goal to install, deploy, monitor and manage [Memcached](https://hub.docker.com/_/memcached) on the cluster.

## Description
// TODO(user): An in-depth paragraph about your project and overview of use
This project is based on the testdata operator and will deploy the operator with the recommended structure and tooling for metrics, alerts, runbooks and all that is needed for monitoring with Prometheus, in order to help developers start implementing monitoring and provide them with tooling, examples and best practices.

## Getting Started
You’ll need a Kubernetes cluster to run against. You can use [KIND](https://sigs.k8s.io/kind) to get a local cluster for testing, or run against a remote cluster.
Expand Down Expand Up @@ -41,6 +41,11 @@ UnDeploy the controller from the cluster:
make undeploy
```

## Monitoring
This operator follows the [Operator Observability Best Practices](https://sdk.operatorframework.io/docs/best-practices/observability-best-practices/).

The metrics documentation, see [docs/monitoring/metrics.md](https://github.com/operator-framework/operator-sdk/blob/master/testdata/go/v3/monitoring/memcached-operator/docs/monitoring/metrics.md) is auto-generated by the utility tool [monitoring/metricsdocs](https://github.com/operator-framework/operator-sdk/blob/master/testdata/go/v3/monitoring/memcached-operator/monitoring/metricsdocs/metricsdocs.go).

## Contributing
// TODO(user): Add detailed information on how you would like others to contribute to this project

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())
}
11 changes: 8 additions & 3 deletions testdata/go/v4-alpha/monitoring/memcached-operator/README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# memcached-operator
// TODO(user): Add simple overview of use/purpose
# memcached-operator (with monitoring)
A Go-based Operator framework that has the goal to install, deploy, monitor and manage [Memcached](https://hub.docker.com/_/memcached) on the cluster.

## Description
// TODO(user): An in-depth paragraph about your project and overview of use
This project is based on the testdata operator and will deploy the operator with the recommended structure and tooling for metrics, alerts, runbooks and all that is needed for monitoring with Prometheus, in order to help developers start implementing monitoring and provide them with tooling, examples and best practices.

## Getting Started
You’ll need a Kubernetes cluster to run against. You can use [KIND](https://sigs.k8s.io/kind) to get a local cluster for testing, or run against a remote cluster.
Expand Down Expand Up @@ -41,6 +41,11 @@ UnDeploy the controller from the cluster:
make undeploy
```

## Monitoring
This operator follows the [Operator Observability Best Practices](https://sdk.operatorframework.io/docs/best-practices/observability-best-practices/).

The metrics documentation, see [docs/monitoring/metrics.md](https://github.com/operator-framework/operator-sdk/blob/master/testdata/go/v4-alpha/monitoring/memcached-operator/docs/monitoring/metrics.md) is auto-generated by the utility tool [monitoring/metricsdocs](https://github.com/operator-framework/operator-sdk/blob/master/testdata/go/v4-alpha/monitoring/memcached-operator/monitoring/metricsdocs/metricsdocs.go).

## Contributing
// TODO(user): Add detailed information on how you would like others to contribute to this project

Expand Down
Loading

0 comments on commit 601b3f8

Please sign in to comment.