Skip to content

Commit

Permalink
Merge pull request #27 from atimeofday/main
Browse files Browse the repository at this point in the history
Add integration test to Prometheus endpoint
  • Loading branch information
yonch authored Dec 26, 2024
2 parents 41e59d9 + bb2d72b commit c560512
Show file tree
Hide file tree
Showing 6 changed files with 159 additions and 30 deletions.
46 changes: 37 additions & 9 deletions cmd/collector/collector_test.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package collector
package main

import (
"fmt"
Expand All @@ -10,12 +10,40 @@ import (
"github.com/stretchr/testify/require"
)

// TODO
func TestMetricsUp() {
// testutil.ScrapeAndCompare()
// "http://localhost:2112/metrics"
// # HELP perfpod_memory_collector_up_metric Test metric to confirm skeleton application functionality.
// # TYPE perfpod_memory_collector_up_metric gauge
// perfpod_memory_collector_up_metric 1
}

func TestMetricsUp(t *testing.T) {

// Initialize module/server for standalone integration test
go main()
time.Sleep(1 * time.Second)

// Set values for standalone integration test
serverURL := "http://localhost:2112"
metricName := "perfpod_memory_collector_up_metric"
metricHelpText := "Test metric to confirm skeleton application functionality."
metricType := "gauge"
expectedMetricValue := 1

// Check for test result every 100 milliseconds with a 1 second limit
require.Eventuallyf(t, func() bool {

// Exact multiline metric template required by testutil.ScrapeAndCompare:

// # HELP perfpod_memory_collector_up_metric Test metric to confirm skeleton application functionality.
// # TYPE perfpod_memory_collector_up_metric gauge
// perfpod_memory_collector_up_metric 1

// Generalized metric template
expected := fmt.Sprintf("\n# HELP %s %s\n# TYPE %s %s\n%s %d\n", metricName, metricHelpText, metricName, metricType, metricName, expectedMetricValue)

// Check current server metrics against expected string/value
if err := testutil.ScrapeAndCompare(serverURL+"/metrics", strings.NewReader(expected), metricName); err == nil {
return true

// Returns an error and error message if the expected string/value is not found
} else {
t.Log(err.Error())
return false
}
}, time.Second, 100*time.Millisecond, "Could not find metric %s with value %d", metricName, expectedMetricValue)
}
5 changes: 5 additions & 0 deletions cmd/collector/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,17 @@ go 1.22.9
require (
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/klauspost/compress v1.17.9 // indirect
github.com/kylelemons/godebug v1.1.0 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_golang v1.20.5 // indirect
github.com/prometheus/client_model v0.6.1 // indirect
github.com/prometheus/common v0.55.0 // indirect
github.com/prometheus/procfs v0.15.1 // indirect
github.com/stretchr/testify v1.10.0 // indirect
golang.org/x/sys v0.22.0 // indirect
google.golang.org/protobuf v1.34.2 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
11 changes: 11 additions & 0 deletions cmd/collector/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,16 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y=
github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
Expand All @@ -14,7 +20,12 @@ github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G
github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8=
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
16 changes: 1 addition & 15 deletions cmd/collector/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,12 @@ package main

import (
"net/http"

"github.com/prometheus/client_golang/prometheus"
// "github.com/prometheus/client_golang/prometheus/promauto"
"github.com/prometheus/client_golang/prometheus/promhttp"
)

func recordMetrics() {
upMetric := prometheus.NewGauge(prometheus.GaugeOpts{
Namespace: "perfpod",
Subsystem: "memory_collector",
Name: "up_metric",
Help: "Test metric to confirm skeleton application functionality.",
})
prometheus.MustRegister(upMetric)

upMetric.Set(1)
}

func main() {
recordMetrics()
go recordMetrics()

http.Handle("/metrics", promhttp.Handler())
http.ListenAndServe(":2112", nil)
Expand Down
18 changes: 18 additions & 0 deletions cmd/collector/record_metrics.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package main

import (
"github.com/prometheus/client_golang/prometheus"
)


func recordMetrics() {
upMetric := prometheus.NewGauge(prometheus.GaugeOpts{
Namespace: "perfpod",
Subsystem: "memory_collector",
Name: "up_metric",
Help: "Test metric to confirm skeleton application functionality.",
})
prometheus.MustRegister(upMetric)

upMetric.Set(1)
}
93 changes: 87 additions & 6 deletions docs/devlog.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
Documentation of development steps, environment, and dependencies

Contributors: atimeofday;
Goals: Create skeleton collector with Prometheus endpoint;
Issues: https://github.com/perfpod/memory-collector/issues/19
- Contributors: atimeofday
- Goals: Create skeleton collector with Prometheus endpoint
- Issues: https://github.com/perfpod/memory-collector/issues/19

Initial environment and tools:
```
Expand Down Expand Up @@ -48,7 +48,8 @@ curl http://localhost:2112/metrics

Issue 19 objective 3: Expose the `up` metric with value 1
```
# Created, registered, and set an 'up' metric in func main()
// Created, registered, and set an 'up' metric in func main()
upMetric := prometheus.NewGauge(prometheus.GaugeOpts{
Namespace: "perfpod",
Subsystem: "memory_collector",
Expand All @@ -73,7 +74,7 @@ perfpod_memory_collector_up_metric 1

Issue 19 objective 5: Move the code into a function (not `main()`)
```
# Moved Up metric into "func recordMetrics()" and added function call in main()
// Moved Up metric into "func recordMetrics()" and added function call in main()
func main() {
recordMetrics()
Expand All @@ -82,10 +83,90 @@ func main() {
http.ListenAndServe(":2112", nil)
}
# Repeated manual verification endpoint query
// Repeated manual verification endpoint query
```

Issue 19 objective 6: Add an integration test that verifies the metrics are up, using client_golang's testutil
- TO DO
- May require assistance

---

- Issue 19 split into 5/5 done and new Issue 20
- Issue 19 5/5 PR opened and merged

---

- Contributors: atimeofday
- Goals: Add integration test to Prometheus endpoint
- Issues: https://github.com/perfpod/memory-collector/issues/20

Research & references:
```
https://go.dev/doc/tutorial/add-a-test
https://albertmoreno.dev/posts/testing-prometheus-metrics-in-integration-tests-in-golang/
https://github.com/prometheus/client_golang/blob/main/prometheus/testutil/testutil.go
https://github.com/prometheus/client_golang/blob/main/prometheus/testutil/testutil_test.go
```

```
go get github.com/prometheus/client_golang/prometheus/testutil
go get github.com/stretchr/testify/require
```

Go test format:
```
[filename]_test.go
import(
[...]
)
func [TestFunction](t *testing.T) {
// Set test values
// Perform test
}
// Perform more tests
```

1. Created skeleton test based on examples

```
func TestMetricsUp(t *testing.T) {
require.Eventuallyf(t, func() bool {
// Test values
// ??? expected format
if err := testutil.ScrapeAndCompare(serverURL+"/metrics", strings.NewReader(expected), metricName); err == nil {
return true
} else {
t.Log(err.Error())
return false
}
}, time.Second, 100*time.Millisecond, "Could not find metric %s with value %d", metricName, expectedMetricValue)
}
```

2. Checked the implementation of the testutil ScrapeAndCompare function, and notably, the implementation of its own integration test.
3. Located and implemented the exact input template required by the function, then implemented generalized code for the template.
4. Researched goroutines to allow automatically initializing the (currently local) remote server to be tested.

```
go main()
time.Sleep(1 * time.Second)
```

5. Refined logical flow from example code for improved readability.

---

- Issue 20 done

---

- Contributors:
- Goals:
- Issues:

0 comments on commit c560512

Please sign in to comment.