Skip to content

Commit

Permalink
feat: 添加度量值检查器并更新配置
Browse files Browse the repository at this point in the history
- 在README文件中更新asciicast链接
- 更新“wait”和“startup_wait”配置选项的默认值
- 在“metric-checker”函数中添加“wait”配置选项
- 在“MetricFamiliesCheckerBuilder”结构中添加新方法`MetricValueChecker`
- 实现`MetricValueChecker`类型以检查度量值
- 使用新网络和更新的环境变量更新docker-compose文件
- 使用更改的值和新度量指标更新配置文件
- 在`Runner`和`MetricChecker`结构中添加新字段和方法
  • Loading branch information
MrLYC committed Apr 16, 2024
1 parent 3c1942e commit 791c26f
Show file tree
Hide file tree
Showing 7 changed files with 76 additions and 29 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Prometheus exporter integration testing tools.

Heracles automatically launches the relevant services based on the docker compose configuration, automatically collects metrics from the exporter service, and performs validation according to the configuration file requirements.

[![asciicast](https://asciinema.org/a/wFU8xmJ2NHSWgwIhmzpSTzzMn.svg)](https://asciinema.org/a/wFU8xmJ2NHSWgwIhmzpSTzzMn)
[![asciicast](https://asciinema.org/a/2aqzeLpVLBMKpUKOm7pxYxbcJ.svg)](https://asciinema.org/a/2aqzeLpVLBMKpUKOm7pxYxbcJ)

## Configuration

Expand Down
9 changes: 5 additions & 4 deletions cmd/check.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ var checkCmd = &cobra.Command{
config.SetDefault("compose_file", "docker-compose.yml")
config.SetDefault("service", "exporter")
config.SetDefault("path", "/metrics")
config.SetDefault("startup_wait", time.Second)
config.SetDefault("wait", 3*time.Second)
config.SetDefault("allow_empty", false)
config.SetDefault("disallowed_metrics", nil)
config.SetDefault("metrics", nil)
Expand All @@ -49,17 +49,17 @@ var checkCmd = &cobra.Command{
return core.NewDockerComposeExporter(
compose,
config.GetString("service"),
config.GetDuration("startup_wait"),
config.GetDuration("wait"),
)
},
"metrics-config": func(config *viper.Viper) ([]core.MetricsConfig, error) {
var metrics []core.MetricsConfig
err := config.UnmarshalKey("exporter.metrics", &metrics)
err := config.UnmarshalKey("metrics", &metrics)
return metrics, eris.Wrap(err, "metrics-config unmarshaling failed")
},
"script-fixtures": func(config *viper.Viper) ([]core.ScriptFixture, error) {
var scriptFixtures []core.ScriptFixture
err := config.UnmarshalKey("exporter.hooks", &scriptFixtures)
err := config.UnmarshalKey("hooks", &scriptFixtures)
return scriptFixtures, eris.Wrap(err, "script-fixtures unmarshaling failed")
},
"fixtures": func(compose *core.DockerCompose, scriptFixtures []core.ScriptFixture) []core.Fixture {
Expand All @@ -78,6 +78,7 @@ var checkCmd = &cobra.Command{
config.GetStringSlice("disallowed_metrics"),
config.GetBool("allow_empty"),
metrics,
config.GetDuration("wait"),
)
},
} {
Expand Down
19 changes: 6 additions & 13 deletions config-example.yml
Original file line number Diff line number Diff line change
@@ -1,28 +1,21 @@
exporter:
compose_file: docker-compose-example.yml
service: exporter
startup_wait: 1s
hooks:
- name: echo
setup: echo setup
teardown: echo teardown
wait: 3s
path: /metrics
allow_empty: false
disallowed_metrics:
- example_metric
metrics:
- name: pg_up
type: gauge
value: 1
- name: pg_exporter_scrapes_total
type: counter
disallowed_metrics:
- not_exist
- name: postgres_exporter_build_info
- name: pg_database_size_bytes
labels:
- branch
- goarch
- goos
- goversion
- revision
- version
- tags
- datname
- name: go_gc_duration_seconds
type: summary
5 changes: 5 additions & 0 deletions core/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@ func (b *MetricFamiliesCheckerBuilder) MetricLabelChecker(metric string, label .
b.MetricsCheckers(metric, NewMetricLabelChecker(metric, label))
}

// MetricLabelDisallowChecker 添加一个指定指标值的检查器。
func (b *MetricFamiliesCheckerBuilder) MetricValueChecker(metric string, value float64) {
b.MetricsCheckers(metric, NewMetricValueChecker(metric, value))
}

// MetricLabelDisallowChecker 添加一个禁止指定指标的指定标签的检查器。
func (b *MetricFamiliesCheckerBuilder) MetricLabelDisallowChecker(metric string, label ...string) {
b.MetricsCheckers(metric, NewMetricLabelDisallowChecker(metric, label))
Expand Down
34 changes: 34 additions & 0 deletions core/checker.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,3 +166,37 @@ func (c *MetricLabelDisallowChecker) Check(metricFamilies map[string]*dto.Metric
}
return true, ""
}

type MetricValueChecker struct {
expectedMetric string
expectedValue float64
}

func (m MetricValueChecker) String() string {
return fmt.Sprintf("MetricValueChecker{expectedMetric: %s, expectedValue: %f}", m.expectedMetric, m.expectedValue)
}

func NewMetricValueChecker(expectedMetric string, expectedValue float64) *MetricValueChecker {
return &MetricValueChecker{
expectedMetric: expectedMetric,
expectedValue: expectedValue,
}
}

func (c *MetricValueChecker) Check(metricFamilies map[string]*dto.MetricFamily) (bool, string) {
metricFamily, ok := metricFamilies[c.expectedMetric]
if !ok {
return false, fmt.Sprintf("expected metric %s is missing", c.expectedMetric)
}

for _, metric := range metricFamily.GetMetric() {
gauge := metric.GetGauge()
if gauge == nil {
return false, fmt.Sprintf("expected metric %s is not a gauge", c.expectedMetric)
}
if gauge.GetValue() != c.expectedValue {
return false, fmt.Sprintf("expected metric %s to have value %f, but has %f", c.expectedMetric, c.expectedValue, gauge.GetValue())
}
}
return true, ""
}
32 changes: 22 additions & 10 deletions core/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"net/http"
"net/url"
"strings"
"time"

"github.com/mrlyc/heracles/log"
dto "github.com/prometheus/client_model/go"
Expand All @@ -18,15 +19,17 @@ var ErrCheck = errors.New("check failed")
type MetricsConfig struct {
Name string `mapstructure:"name"`
Type string `mapstructure:"type"`
Value *float64 `mapstructure:"value"`
Labels []string `mapstructure:"labels"`
DisallowedLabels []string `mapstructure:"disallowed_labels"`
}

type Runner struct {
exporter Exporter
fixtures []Fixture
httpClient HTTPClient
metricPath string
exporter Exporter
fixtures []Fixture
httpClient HTTPClient
metricPath string
waitDuration time.Duration
}

func (r *Runner) SetupFixtures(ctx context.Context) error {
Expand Down Expand Up @@ -97,6 +100,9 @@ func (r *Runner) Run(ctx context.Context, callback func(ctx context.Context, met
return eris.Wrap(err, "failed to start exporter")
}

log.Infof("waiting for %s", r.waitDuration)
time.Sleep(r.waitDuration)

metricFamilies, err := r.FetchMetricFamilies(ctx, baseUrl)
if err != nil {
return eris.Wrap(err, "failed to fetch metrics")
Expand All @@ -110,12 +116,13 @@ func (r *Runner) Run(ctx context.Context, callback func(ctx context.Context, met
return nil
}

func NewRunner(exporter Exporter, fixtures []Fixture, metricPath string) *Runner {
func NewRunner(exporter Exporter, fixtures []Fixture, metricPath string, waitDuration time.Duration) *Runner {
return &Runner{
exporter: exporter,
fixtures: fixtures,
httpClient: http.DefaultClient,
metricPath: metricPath,
exporter: exporter,
fixtures: fixtures,
httpClient: http.DefaultClient,
metricPath: metricPath,
waitDuration: waitDuration,
}
}

Expand Down Expand Up @@ -168,6 +175,10 @@ func (c *MetricChecker) BuildChecker() ([]MetricFamiliesChecker, error) {
checkerBuilder.MetricTypeChecker(metric.Name, metric.Type)
}

if metric.Value != nil {
checkerBuilder.MetricValueChecker(metric.Name, *metric.Value)
}

if len(metric.Labels) != 0 {
checkerBuilder.MetricLabelChecker(metric.Name, metric.Labels...)
}
Expand All @@ -191,9 +202,10 @@ func NewMetricChecker(
disallowedMetrics []string,
allowEmpty bool,
metrics []MetricsConfig,
waitDuration time.Duration,
) *MetricChecker {
return &MetricChecker{
Runner: NewRunner(exporter, fixtures, metricPath),
Runner: NewRunner(exporter, fixtures, metricPath, waitDuration),
disallowedMetrics: disallowedMetrics,
allowEmpty: allowEmpty,
metrics: metrics,
Expand Down
4 changes: 3 additions & 1 deletion docker-compose-example.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@ services:
- POSTGRES_PASSWORD=heracles
- POSTGRES_USER=mrlyc
- POSTGRES_DB=example
networks:
- postgres_network

exporter:
image: quay.io/prometheuscommunity/postgres-exporter
environment:
- DATA_SOURCE_NAME=postgresql://mrlyc:heracles@postgres/example?sslmode=disable
- DATA_SOURCE_NAME=postgresql://mrlyc:heracles@postgres:5432/example?sslmode=disable
ports:
- "9187:9187"
depends_on:
Expand Down

0 comments on commit 791c26f

Please sign in to comment.