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

loadtest: add support for push metrics #662

Closed
Closed
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
38 changes: 38 additions & 0 deletions itest/loadtest/config.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package loadtest

import (
"fmt"
"time"

"github.com/jessevdk/go-flags"
Expand Down Expand Up @@ -44,6 +45,15 @@ type BitcoinConfig struct {
TLSPath string `long:"tlspath" description:"Path to btcd's TLS certificate, if TLS is enabled"`
}

// PrometheusGatewayConfig defines exported config options for connecting to the
// Prometheus PushGateway.
type PrometheusGatewayConfig struct {
Enabled bool `long:"enabled" description:"Enable pushing metrics to Prometheus PushGateway"`
Host string `long:"host" description:"Prometheus PushGateway host address"`
Port int `long:"port" description:"Prometheus PushGateway port"`
PushURL string
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: I think you should add a doc comment to describe PushURL.

}

// Config holds the main configuration for the performance testing binary.
type Config struct {
// TestCases is a comma separated list of test cases that will be
Expand Down Expand Up @@ -80,6 +90,9 @@ type Config struct {

// TestTimeout is the timeout for each test.
TestTimeout time.Duration `long:"test-timeout" description:"the timeout for each test"`

// PrometheusGateway is the configuration for the Prometheus PushGateway.
PrometheusGateway *PrometheusGatewayConfig `group:"prometheus-gateway" namespace:"prometheus-gateway" description:"Prometheus PushGateway configuration"`
}

// DefaultConfig returns the default configuration for the performance testing
Expand All @@ -102,6 +115,11 @@ func DefaultConfig() Config {
SendType: taprpc.AssetType_COLLECTIBLE,
TestSuiteTimeout: defaultSuiteTimeout,
TestTimeout: defaultTestTimeout,
PrometheusGateway: &PrometheusGatewayConfig{
Enabled: false,
Host: "localhost",
Port: 9091,
},
}
}

Expand Down Expand Up @@ -138,5 +156,25 @@ func LoadConfig() (*Config, error) {
// of it with sane defaults.
func ValidateConfig(cfg Config) (*Config, error) {
// TODO (positiveblue): add validation logic.

// Validate Prometheus PushGateway configuration.
if cfg.PrometheusGateway.Enabled {
gatewayHost := cfg.PrometheusGateway.Host
gatewayPort := cfg.PrometheusGateway.Port

if gatewayHost == "" {
return nil, fmt.Errorf("gateway hostname may not be empty")
}

if gatewayPort == 0 {
return nil, fmt.Errorf("gateway port is not set")
}

// Construct the endpoint for Prometheus PushGateway.
cfg.PrometheusGateway.PushURL = fmt.Sprintf(
"%s:%d", gatewayHost, gatewayPort,
)
}

return &cfg, nil
}
43 changes: 43 additions & 0 deletions itest/loadtest/load_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,28 @@ package loadtest
import (
"context"
"testing"
"time"

"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/push"
"github.com/stretchr/testify/require"
)

var (
testDuration = prometheus.NewGaugeVec(
prometheus.GaugeOpts{
Name: "test_duration_seconds",
Help: "Duration of the test execution, in seconds",
},
[]string{"test_name"},
)
)

func init() {
// Register the metric with Prometheus's default registry.
prometheus.MustRegister(testDuration)
}

type testCase struct {
name string
fn func(t *testing.T, ctx context.Context, cfg *Config)
Expand Down Expand Up @@ -44,6 +62,9 @@ func TestPerformance(t *testing.T) {
continue
}

// Record the start time of the test case.
startTime := time.Now()

success := t.Run(tc.name, func(tt *testing.T) {
ctxt, cancel := context.WithTimeout(
ctxt, cfg.TestTimeout,
Expand All @@ -55,6 +76,28 @@ func TestPerformance(t *testing.T) {
if !success {
t.Fatalf("test case %v failed", tc.name)
}

// Calculate the test duration and push metrics if the test case succeeded.
if cfg.PrometheusGateway.Enabled {
duration := time.Since(startTime).Seconds()

// Update the metric with the test duration.
testDuration.WithLabelValues(tc.name).Set(duration)

// Create a new pusher to push the metrics.
pusher := push.New(cfg.PrometheusGateway.PushURL, "load_test").
Collector(testDuration).
Grouping("test_case", tc.name)

// Push the metrics to Prometheus PushGateway.
if err := pusher.Push(); err != nil {
t.Logf("Could not push metrics to Prometheus PushGateway: %v",
err)
} else {
t.Logf("Metrics pushed for test case '%s': duration = %v seconds",
tc.name, duration)
}
}
}
}

Expand Down