mirror of
https://github.com/kubernetes-sigs/external-dns.git
synced 2025-08-06 09:36:58 +02:00
feat(metrics): publish build_info metric (#5643)
* feat(metrics): publish build_info metric Signed-off-by: ivan katliarchuk <ivan.katliarchuk@gmail.com> * feat(metrics): publish build_info metric Signed-off-by: ivan katliarchuk <ivan.katliarchuk@gmail.com> * feat(metrics): publish build_info metric Co-authored-by: Michel Loiseleur <97035654+mloiseleur@users.noreply.github.com> * feat(metrics): publish build_info metric Signed-off-by: ivan katliarchuk <ivan.katliarchuk@gmail.com> --------- Signed-off-by: ivan katliarchuk <ivan.katliarchuk@gmail.com> Co-authored-by: Michel Loiseleur <97035654+mloiseleur@users.noreply.github.com>
This commit is contained in:
parent
faeee1226e
commit
b93d1e9abb
@ -37,7 +37,6 @@ import (
|
||||
var (
|
||||
registryErrorsTotal = metrics.NewCounterWithOpts(
|
||||
prometheus.CounterOpts{
|
||||
Namespace: "external_dns",
|
||||
Subsystem: "registry",
|
||||
Name: "errors_total",
|
||||
Help: "Number of Registry errors.",
|
||||
@ -45,7 +44,6 @@ var (
|
||||
)
|
||||
sourceErrorsTotal = metrics.NewCounterWithOpts(
|
||||
prometheus.CounterOpts{
|
||||
Namespace: "external_dns",
|
||||
Subsystem: "source",
|
||||
Name: "errors_total",
|
||||
Help: "Number of Source errors.",
|
||||
@ -53,7 +51,6 @@ var (
|
||||
)
|
||||
sourceEndpointsTotal = metrics.NewGaugeWithOpts(
|
||||
prometheus.GaugeOpts{
|
||||
Namespace: "external_dns",
|
||||
Subsystem: "source",
|
||||
Name: "endpoints_total",
|
||||
Help: "Number of Endpoints in all sources",
|
||||
@ -61,7 +58,6 @@ var (
|
||||
)
|
||||
registryEndpointsTotal = metrics.NewGaugeWithOpts(
|
||||
prometheus.GaugeOpts{
|
||||
Namespace: "external_dns",
|
||||
Subsystem: "registry",
|
||||
Name: "endpoints_total",
|
||||
Help: "Number of Endpoints in the registry",
|
||||
@ -69,7 +65,6 @@ var (
|
||||
)
|
||||
lastSyncTimestamp = metrics.NewGaugeWithOpts(
|
||||
prometheus.GaugeOpts{
|
||||
Namespace: "external_dns",
|
||||
Subsystem: "controller",
|
||||
Name: "last_sync_timestamp_seconds",
|
||||
Help: "Timestamp of last successful sync with the DNS provider",
|
||||
@ -77,7 +72,6 @@ var (
|
||||
)
|
||||
lastReconcileTimestamp = metrics.NewGaugeWithOpts(
|
||||
prometheus.GaugeOpts{
|
||||
Namespace: "external_dns",
|
||||
Subsystem: "controller",
|
||||
Name: "last_reconcile_timestamp_seconds",
|
||||
Help: "Timestamp of last attempted sync with the DNS provider",
|
||||
@ -85,7 +79,6 @@ var (
|
||||
)
|
||||
controllerNoChangesTotal = metrics.NewCounterWithOpts(
|
||||
prometheus.CounterOpts{
|
||||
Namespace: "external_dns",
|
||||
Subsystem: "controller",
|
||||
Name: "no_op_runs_total",
|
||||
Help: "Number of reconcile loops ending up with no changes on the DNS provider side.",
|
||||
@ -108,7 +101,6 @@ var (
|
||||
|
||||
registryRecords = metrics.NewGaugedVectorOpts(
|
||||
prometheus.GaugeOpts{
|
||||
Namespace: "external_dns",
|
||||
Subsystem: "registry",
|
||||
Name: "records",
|
||||
Help: "Number of registry records partitioned by label name (vector).",
|
||||
@ -118,7 +110,6 @@ var (
|
||||
|
||||
sourceRecords = metrics.NewGaugedVectorOpts(
|
||||
prometheus.GaugeOpts{
|
||||
Namespace: "external_dns",
|
||||
Subsystem: "source",
|
||||
Name: "records",
|
||||
Help: "Number of source records partitioned by label name (vector).",
|
||||
@ -128,7 +119,6 @@ var (
|
||||
|
||||
verifiedRecords = metrics.NewGaugedVectorOpts(
|
||||
prometheus.GaugeOpts{
|
||||
Namespace: "external_dns",
|
||||
Subsystem: "controller",
|
||||
Name: "verified_records",
|
||||
Help: "Number of DNS records that exists both in source and registry (vector).",
|
||||
@ -138,7 +128,6 @@ var (
|
||||
|
||||
consecutiveSoftErrors = metrics.NewGaugeWithOpts(
|
||||
prometheus.GaugeOpts{
|
||||
Namespace: "external_dns",
|
||||
Subsystem: "controller",
|
||||
Name: "consecutive_soft_errors",
|
||||
Help: "Number of consecutive soft errors in reconciliation loop.",
|
||||
|
@ -20,6 +20,7 @@ curl https://localhost:7979/metrics
|
||||
|
||||
| Name | Metric Type | Subsystem | Help |
|
||||
|:---------------------------------|:------------|:------------|:------------------------------------------------------|
|
||||
| build_info | Gauge | | A metric with a constant '1' value labeled with 'version' and 'revision' of external_dns and the 'go_version', 'os' and the 'arch' used the build. |
|
||||
| consecutive_soft_errors | Gauge | controller | Number of consecutive soft errors in reconciliation loop. |
|
||||
| last_reconcile_timestamp_seconds | Gauge | controller | Timestamp of last attempted sync with the DNS provider |
|
||||
| last_sync_timestamp_seconds | Gauge | controller | Timestamp of last successful sync with the DNS provider |
|
||||
|
@ -37,7 +37,7 @@ func TestComputeMetrics(t *testing.T) {
|
||||
t.Errorf("Expected not empty metrics registry, got %d", len(reg.Metrics))
|
||||
}
|
||||
|
||||
assert.Len(t, reg.Metrics, 19)
|
||||
assert.Len(t, reg.Metrics, 20)
|
||||
}
|
||||
|
||||
func TestGenerateMarkdownTableRenderer(t *testing.T) {
|
||||
|
@ -17,25 +17,44 @@ limitations under the License.
|
||||
package metrics
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
"fmt"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/common/version"
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
cfg "sigs.k8s.io/external-dns/pkg/apis/externaldns"
|
||||
)
|
||||
|
||||
const (
|
||||
Namespace = "external_dns"
|
||||
)
|
||||
|
||||
var (
|
||||
RegisterMetric = NewMetricsRegister()
|
||||
)
|
||||
|
||||
func init() {
|
||||
RegisterMetric.MustRegister(NewGaugeFuncMetric(prometheus.GaugeOpts{
|
||||
Namespace: Namespace,
|
||||
Name: "build_info",
|
||||
Help: fmt.Sprintf(
|
||||
"A metric with a constant '1' value labeled with 'version' and 'revision' of %s and the 'go_version', 'os' and the 'arch' used the build.",
|
||||
Namespace,
|
||||
),
|
||||
ConstLabels: prometheus.Labels{
|
||||
"version": cfg.Version,
|
||||
"revision": version.GetRevision(),
|
||||
"go_version": version.GoVersion,
|
||||
"os": version.GoOS,
|
||||
"arch": version.GoArch,
|
||||
},
|
||||
}))
|
||||
}
|
||||
|
||||
func NewMetricsRegister() *MetricRegistry {
|
||||
reg := prometheus.WrapRegistererWith(
|
||||
prometheus.Labels{
|
||||
"version": cfg.Version,
|
||||
"arch": runtime.GOARCH,
|
||||
"go_version": runtime.Version(),
|
||||
},
|
||||
prometheus.Labels{},
|
||||
prometheus.DefaultRegisterer)
|
||||
return &MetricRegistry{
|
||||
Registerer: reg,
|
||||
@ -54,7 +73,7 @@ func NewMetricsRegister() *MetricRegistry {
|
||||
// }
|
||||
func (m *MetricRegistry) MustRegister(cs IMetric) {
|
||||
switch v := cs.(type) {
|
||||
case CounterMetric, GaugeMetric, CounterVecMetric, GaugeVecMetric:
|
||||
case CounterMetric, GaugeMetric, CounterVecMetric, GaugeVecMetric, GaugeFuncMetric:
|
||||
if _, exists := m.mName[cs.Get().FQDN]; exists {
|
||||
return
|
||||
} else {
|
||||
@ -70,6 +89,8 @@ func (m *MetricRegistry) MustRegister(cs IMetric) {
|
||||
m.Registerer.MustRegister(metric.Gauge)
|
||||
case CounterVecMetric:
|
||||
m.Registerer.MustRegister(metric.CounterVec)
|
||||
case GaugeFuncMetric:
|
||||
m.Registerer.MustRegister(metric.GaugeFunc)
|
||||
}
|
||||
log.Debugf("Register metric: %s", cs.Get().FQDN)
|
||||
default:
|
||||
|
@ -88,6 +88,7 @@ func (g GaugeVecMetric) SetWithLabels(value float64, lvs ...string) {
|
||||
}
|
||||
|
||||
func NewGaugeWithOpts(opts prometheus.GaugeOpts) GaugeMetric {
|
||||
opts.Namespace = Namespace
|
||||
return GaugeMetric{
|
||||
Metric: Metric{
|
||||
Type: "gauge",
|
||||
@ -104,6 +105,7 @@ func NewGaugeWithOpts(opts prometheus.GaugeOpts) GaugeMetric {
|
||||
// NewGaugedVectorOpts creates a new GaugeVec based on the provided GaugeOpts and
|
||||
// partitioned by the given label names.
|
||||
func NewGaugedVectorOpts(opts prometheus.GaugeOpts, labelNames []string) GaugeVecMetric {
|
||||
opts.Namespace = Namespace
|
||||
return GaugeVecMetric{
|
||||
Metric: Metric{
|
||||
Type: "gauge",
|
||||
@ -118,6 +120,7 @@ func NewGaugedVectorOpts(opts prometheus.GaugeOpts, labelNames []string) GaugeVe
|
||||
}
|
||||
|
||||
func NewCounterWithOpts(opts prometheus.CounterOpts) CounterMetric {
|
||||
opts.Namespace = Namespace
|
||||
return CounterMetric{
|
||||
Metric: Metric{
|
||||
Type: "counter",
|
||||
@ -132,6 +135,7 @@ func NewCounterWithOpts(opts prometheus.CounterOpts) CounterMetric {
|
||||
}
|
||||
|
||||
func NewCounterVecWithOpts(opts prometheus.CounterOpts, labelNames []string) CounterVecMetric {
|
||||
opts.Namespace = Namespace
|
||||
return CounterVecMetric{
|
||||
Metric: Metric{
|
||||
Type: "counter",
|
||||
@ -144,3 +148,31 @@ func NewCounterVecWithOpts(opts prometheus.CounterOpts, labelNames []string) Cou
|
||||
CounterVec: prometheus.NewCounterVec(opts, labelNames),
|
||||
}
|
||||
}
|
||||
|
||||
type GaugeFuncMetric struct {
|
||||
Metric
|
||||
GaugeFunc prometheus.GaugeFunc
|
||||
}
|
||||
|
||||
func (g GaugeFuncMetric) Get() *Metric {
|
||||
return &g.Metric
|
||||
}
|
||||
|
||||
func NewGaugeFuncMetric(opts prometheus.GaugeOpts) GaugeFuncMetric {
|
||||
return GaugeFuncMetric{
|
||||
Metric: Metric{
|
||||
Type: "gauge",
|
||||
Name: opts.Name,
|
||||
FQDN: func() string {
|
||||
if opts.Subsystem != "" {
|
||||
return fmt.Sprintf("%s_%s", opts.Subsystem, opts.Name)
|
||||
}
|
||||
return opts.Name
|
||||
}(),
|
||||
Namespace: opts.Namespace,
|
||||
Subsystem: opts.Subsystem,
|
||||
Help: opts.Help,
|
||||
},
|
||||
GaugeFunc: prometheus.NewGaugeFunc(opts, func() float64 { return 1 }),
|
||||
}
|
||||
}
|
||||
|
@ -17,18 +17,17 @@ limitations under the License.
|
||||
package metrics
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
dto "github.com/prometheus/client_model/go"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
dto "github.com/prometheus/client_model/go"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestNewGaugeWithOpts(t *testing.T) {
|
||||
opts := prometheus.GaugeOpts{
|
||||
Name: "test_gauge",
|
||||
Namespace: "test_namespace",
|
||||
Subsystem: "test_subsystem",
|
||||
Help: "This is a test gauge",
|
||||
}
|
||||
@ -37,7 +36,7 @@ func TestNewGaugeWithOpts(t *testing.T) {
|
||||
|
||||
assert.Equal(t, "gauge", gaugeMetric.Type)
|
||||
assert.Equal(t, "test_gauge", gaugeMetric.Name)
|
||||
assert.Equal(t, "test_namespace", gaugeMetric.Namespace)
|
||||
assert.Equal(t, Namespace, gaugeMetric.Namespace)
|
||||
assert.Equal(t, "test_subsystem", gaugeMetric.Subsystem)
|
||||
assert.Equal(t, "This is a test gauge", gaugeMetric.Help)
|
||||
assert.Equal(t, "test_subsystem_test_gauge", gaugeMetric.FQDN)
|
||||
@ -47,7 +46,6 @@ func TestNewGaugeWithOpts(t *testing.T) {
|
||||
func TestNewCounterWithOpts(t *testing.T) {
|
||||
opts := prometheus.CounterOpts{
|
||||
Name: "test_counter",
|
||||
Namespace: "test_namespace",
|
||||
Subsystem: "test_subsystem",
|
||||
Help: "This is a test counter",
|
||||
}
|
||||
@ -56,7 +54,7 @@ func TestNewCounterWithOpts(t *testing.T) {
|
||||
|
||||
assert.Equal(t, "counter", counterMetric.Type)
|
||||
assert.Equal(t, "test_counter", counterMetric.Name)
|
||||
assert.Equal(t, "test_namespace", counterMetric.Namespace)
|
||||
assert.Equal(t, Namespace, counterMetric.Namespace)
|
||||
assert.Equal(t, "test_subsystem", counterMetric.Subsystem)
|
||||
assert.Equal(t, "This is a test counter", counterMetric.Help)
|
||||
assert.Equal(t, "test_subsystem_test_counter", counterMetric.FQDN)
|
||||
@ -77,7 +75,7 @@ func TestNewCounterVecWithOpts(t *testing.T) {
|
||||
|
||||
assert.Equal(t, "counter", counterVecMetric.Type)
|
||||
assert.Equal(t, "test_counter_vec", counterVecMetric.Name)
|
||||
assert.Equal(t, "test_namespace", counterVecMetric.Namespace)
|
||||
assert.Equal(t, Namespace, counterVecMetric.Namespace)
|
||||
assert.Equal(t, "test_subsystem", counterVecMetric.Subsystem)
|
||||
assert.Equal(t, "This is a test counter vector", counterVecMetric.Help)
|
||||
assert.Equal(t, "test_subsystem_test_counter_vec", counterVecMetric.FQDN)
|
||||
@ -113,3 +111,20 @@ func TestGaugeV_SetWithLabels(t *testing.T) {
|
||||
|
||||
assert.Len(t, m.Label, 2)
|
||||
}
|
||||
|
||||
func TestNewBuildInfoCollector(t *testing.T) {
|
||||
metric := NewGaugeFuncMetric(prometheus.GaugeOpts{
|
||||
Namespace: Namespace,
|
||||
Name: "build_info",
|
||||
ConstLabels: prometheus.Labels{
|
||||
"version": "0.0.1",
|
||||
"goversion": "1.24",
|
||||
"arch": "arm64",
|
||||
},
|
||||
})
|
||||
|
||||
desc := metric.GaugeFunc.Desc()
|
||||
|
||||
assert.Equal(t, "external_dns_build_info", reflect.ValueOf(desc).Elem().FieldByName("fqName").String())
|
||||
assert.Contains(t, desc.String(), "version=\"0.0.1\"")
|
||||
}
|
||||
|
@ -31,7 +31,6 @@ import (
|
||||
var (
|
||||
cachedRecordsCallsTotal = metrics.NewCounterVecWithOpts(
|
||||
prometheus.CounterOpts{
|
||||
Namespace: "external_dns",
|
||||
Subsystem: "provider",
|
||||
Name: "cache_records_calls",
|
||||
Help: "Number of calls to the provider cache Records list.",
|
||||
@ -42,7 +41,6 @@ var (
|
||||
)
|
||||
cachedApplyChangesCallsTotal = metrics.NewCounterWithOpts(
|
||||
prometheus.CounterOpts{
|
||||
Namespace: "external_dns",
|
||||
Subsystem: "provider",
|
||||
Name: "cache_apply_changes_calls",
|
||||
Help: "Number of calls to the provider cache ApplyChanges.",
|
||||
|
@ -43,7 +43,6 @@ const (
|
||||
var (
|
||||
recordsErrorsGauge = metrics.NewGaugeWithOpts(
|
||||
prometheus.GaugeOpts{
|
||||
Namespace: "external_dns",
|
||||
Subsystem: "webhook_provider",
|
||||
Name: "records_errors_total",
|
||||
Help: "Errors with Records method",
|
||||
@ -51,7 +50,6 @@ var (
|
||||
)
|
||||
recordsRequestsGauge = metrics.NewGaugeWithOpts(
|
||||
prometheus.GaugeOpts{
|
||||
Namespace: "external_dns",
|
||||
Subsystem: "webhook_provider",
|
||||
Name: "records_requests_total",
|
||||
Help: "Requests with Records method",
|
||||
@ -59,7 +57,6 @@ var (
|
||||
)
|
||||
applyChangesErrorsGauge = metrics.NewGaugeWithOpts(
|
||||
prometheus.GaugeOpts{
|
||||
Namespace: "external_dns",
|
||||
Subsystem: "webhook_provider",
|
||||
Name: "applychanges_errors_total",
|
||||
Help: "Errors with ApplyChanges method",
|
||||
@ -67,7 +64,6 @@ var (
|
||||
)
|
||||
applyChangesRequestsGauge = metrics.NewGaugeWithOpts(
|
||||
prometheus.GaugeOpts{
|
||||
Namespace: "external_dns",
|
||||
Subsystem: "webhook_provider",
|
||||
Name: "applychanges_requests_total",
|
||||
Help: "Requests with ApplyChanges method",
|
||||
@ -75,7 +71,6 @@ var (
|
||||
)
|
||||
adjustEndpointsErrorsGauge = metrics.NewGaugeWithOpts(
|
||||
prometheus.GaugeOpts{
|
||||
Namespace: "external_dns",
|
||||
Subsystem: "webhook_provider",
|
||||
Name: "adjustendpoints_errors_total",
|
||||
Help: "Errors with AdjustEndpoints method",
|
||||
@ -83,7 +78,6 @@ var (
|
||||
)
|
||||
adjustEndpointsRequestsGauge = metrics.NewGaugeWithOpts(
|
||||
prometheus.GaugeOpts{
|
||||
Namespace: "external_dns",
|
||||
Subsystem: "webhook_provider",
|
||||
Name: "adjustendpoints_requests_total",
|
||||
Help: "Requests with AdjustEndpoints method",
|
||||
|
Loading…
Reference in New Issue
Block a user