[#29] Add type to metrics description

Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
This commit is contained in:
Denis Kirillov 2023-04-10 12:22:11 +03:00
parent 6c6fd0e9a5
commit 385f336a17
4 changed files with 48 additions and 16 deletions

2
go.mod
View file

@ -8,6 +8,7 @@ require (
github.com/fasthttp/router v1.4.1
github.com/nspcc-dev/neo-go v0.101.0
github.com/prometheus/client_golang v1.13.0
github.com/prometheus/client_model v0.2.0
github.com/spf13/pflag v1.0.5
github.com/spf13/viper v1.15.0
github.com/stretchr/testify v1.8.1
@ -68,7 +69,6 @@ require (
github.com/pelletier/go-toml/v2 v2.0.6 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_model v0.2.0 // indirect
github.com/prometheus/common v0.37.0 // indirect
github.com/prometheus/procfs v0.8.0 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect

View file

@ -4,17 +4,20 @@ import (
"encoding/json"
"github.com/prometheus/client_golang/prometheus"
dto "github.com/prometheus/client_model/go"
)
var appMetricsDesc = map[string]map[string]Description{
poolSubsystem: {
overallErrorsMetric: Description{
Type: dto.MetricType_GAUGE,
Namespace: namespace,
Subsystem: poolSubsystem,
Name: overallErrorsMetric,
Help: "Total number of errors in pool",
},
overallNodeErrorsMetric: Description{
Type: dto.MetricType_GAUGE,
Namespace: namespace,
Subsystem: poolSubsystem,
Name: overallNodeErrorsMetric,
@ -22,6 +25,7 @@ var appMetricsDesc = map[string]map[string]Description{
VariableLabels: []string{"node"},
},
overallNodeRequestsMetric: Description{
Type: dto.MetricType_GAUGE,
Namespace: namespace,
Subsystem: poolSubsystem,
Name: overallNodeRequestsMetric,
@ -29,6 +33,7 @@ var appMetricsDesc = map[string]map[string]Description{
VariableLabels: []string{"node"},
},
currentErrorMetric: Description{
Type: dto.MetricType_GAUGE,
Namespace: namespace,
Subsystem: poolSubsystem,
Name: currentErrorMetric,
@ -36,6 +41,7 @@ var appMetricsDesc = map[string]map[string]Description{
VariableLabels: []string{"node"},
},
avgRequestDurationMetric: Description{
Type: dto.MetricType_GAUGE,
Namespace: namespace,
Subsystem: poolSubsystem,
Name: avgRequestDurationMetric,
@ -45,12 +51,14 @@ var appMetricsDesc = map[string]map[string]Description{
},
stateSubsystem: {
healthMetric: Description{
Type: dto.MetricType_GAUGE,
Namespace: namespace,
Subsystem: stateSubsystem,
Name: healthMetric,
Help: "Current HTTP gateway state",
},
versionInfoMetric: Description{
Type: dto.MetricType_GAUGE,
Namespace: namespace,
Subsystem: stateSubsystem,
Name: versionInfoMetric,
@ -61,6 +69,7 @@ var appMetricsDesc = map[string]map[string]Description{
}
type Description struct {
Type dto.MetricType
Namespace string
Subsystem string
Name string
@ -76,11 +85,13 @@ type KeyValue struct {
func (d *Description) MarshalJSON() ([]byte, error) {
return json.Marshal(&struct {
Type string `json:"type"`
FQName string `json:"name"`
Help string `json:"help"`
ConstantLabels []KeyValue `json:"constant_labels"`
VariableLabels []string `json:"variable_labels"`
}{
Type: d.Type.String(),
FQName: d.BuildFQName(),
Help: d.Help,
ConstantLabels: d.ConstantLabels,
@ -122,13 +133,19 @@ func newOpts(description Description) prometheus.Opts {
}
}
func newGauge(description Description) prometheus.Gauge {
func mustNewGauge(description Description) prometheus.Gauge {
if description.Type != dto.MetricType_GAUGE {
panic("invalid metric type")
}
return prometheus.NewGauge(
prometheus.GaugeOpts(newOpts(description)),
)
}
func newGaugeVec(description Description) *prometheus.GaugeVec {
func mustNewGaugeVec(description Description) *prometheus.GaugeVec {
if description.Type != dto.MetricType_GAUGE {
panic("invalid metric type")
}
return prometheus.NewGaugeVec(
prometheus.GaugeOpts(newOpts(description)),
description.VariableLabels,

View file

@ -8,17 +8,28 @@ import (
"os"
"testing"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/pool"
"github.com/stretchr/testify/require"
)
type mock struct{}
func (m mock) Statistic() pool.Statistic {
return pool.Statistic{}
}
var metricsPath = flag.String("out", "", "File to export http gateway metrics to.")
func TestDescribeAll(t *testing.T) {
// to check correct metrics type mapping
_ = NewGateMetrics(mock{})
flag.Parse()
require.NotEmpty(t, metricsPath, "flag 'out' must be provided to dump metrics description")
data, err := json.Marshal(DescribeAll())
desc := DescribeAll()
data, err := json.Marshal(desc)
require.NoError(t, err)
err = os.WriteFile(*metricsPath, data, 0644)

View file

@ -56,6 +56,10 @@ const (
HealthStatusShuttingDown HealthStatus = 3
)
type StatisticScraper interface {
Statistic() pool.Statistic
}
type GateMetrics struct {
stateMetrics
poolMetricsCollector
@ -67,7 +71,7 @@ type stateMetrics struct {
}
type poolMetricsCollector struct {
pool *pool.Pool
scraper StatisticScraper
overallErrors prometheus.Gauge
overallNodeErrors *prometheus.GaugeVec
overallNodeRequests *prometheus.GaugeVec
@ -76,7 +80,7 @@ type poolMetricsCollector struct {
}
// NewGateMetrics creates new metrics for http gate.
func NewGateMetrics(p *pool.Pool) *GateMetrics {
func NewGateMetrics(p StatisticScraper) *GateMetrics {
stateMetric := newStateMetrics()
stateMetric.register()
@ -96,8 +100,8 @@ func (g *GateMetrics) Unregister() {
func newStateMetrics() *stateMetrics {
return &stateMetrics{
healthCheck: newGauge(appMetricsDesc[stateSubsystem][healthMetric]),
versionInfo: newGaugeVec(appMetricsDesc[stateSubsystem][versionInfoMetric]),
healthCheck: mustNewGauge(appMetricsDesc[stateSubsystem][healthMetric]),
versionInfo: mustNewGaugeVec(appMetricsDesc[stateSubsystem][versionInfoMetric]),
}
}
@ -119,14 +123,14 @@ func (m stateMetrics) SetVersion(ver string) {
m.versionInfo.WithLabelValues(ver).Set(1)
}
func newPoolMetricsCollector(p *pool.Pool) *poolMetricsCollector {
func newPoolMetricsCollector(p StatisticScraper) *poolMetricsCollector {
return &poolMetricsCollector{
pool: p,
overallErrors: newGauge(appMetricsDesc[poolSubsystem][overallErrorsMetric]),
overallNodeErrors: newGaugeVec(appMetricsDesc[poolSubsystem][overallNodeErrorsMetric]),
overallNodeRequests: newGaugeVec(appMetricsDesc[poolSubsystem][overallNodeRequestsMetric]),
currentErrors: newGaugeVec(appMetricsDesc[poolSubsystem][currentErrorMetric]),
requestDuration: newGaugeVec(appMetricsDesc[poolSubsystem][avgRequestDurationMetric]),
scraper: p,
overallErrors: mustNewGauge(appMetricsDesc[poolSubsystem][overallErrorsMetric]),
overallNodeErrors: mustNewGaugeVec(appMetricsDesc[poolSubsystem][overallNodeErrorsMetric]),
overallNodeRequests: mustNewGaugeVec(appMetricsDesc[poolSubsystem][overallNodeRequestsMetric]),
currentErrors: mustNewGaugeVec(appMetricsDesc[poolSubsystem][currentErrorMetric]),
requestDuration: mustNewGaugeVec(appMetricsDesc[poolSubsystem][avgRequestDurationMetric]),
}
}
@ -152,7 +156,7 @@ func (m *poolMetricsCollector) register() {
}
func (m *poolMetricsCollector) updateStatistic() {
stat := m.pool.Statistic()
stat := m.scraper.Statistic()
m.overallNodeErrors.Reset()
m.overallNodeRequests.Reset()