Skip to content

Commit b93d1e9

Browse files
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>
1 parent faeee12 commit b93d1e9

File tree

8 files changed

+84
-34
lines changed

8 files changed

+84
-34
lines changed

controller/controller.go

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -37,55 +37,48 @@ import (
3737
var (
3838
registryErrorsTotal = metrics.NewCounterWithOpts(
3939
prometheus.CounterOpts{
40-
Namespace: "external_dns",
4140
Subsystem: "registry",
4241
Name: "errors_total",
4342
Help: "Number of Registry errors.",
4443
},
4544
)
4645
sourceErrorsTotal = metrics.NewCounterWithOpts(
4746
prometheus.CounterOpts{
48-
Namespace: "external_dns",
4947
Subsystem: "source",
5048
Name: "errors_total",
5149
Help: "Number of Source errors.",
5250
},
5351
)
5452
sourceEndpointsTotal = metrics.NewGaugeWithOpts(
5553
prometheus.GaugeOpts{
56-
Namespace: "external_dns",
5754
Subsystem: "source",
5855
Name: "endpoints_total",
5956
Help: "Number of Endpoints in all sources",
6057
},
6158
)
6259
registryEndpointsTotal = metrics.NewGaugeWithOpts(
6360
prometheus.GaugeOpts{
64-
Namespace: "external_dns",
6561
Subsystem: "registry",
6662
Name: "endpoints_total",
6763
Help: "Number of Endpoints in the registry",
6864
},
6965
)
7066
lastSyncTimestamp = metrics.NewGaugeWithOpts(
7167
prometheus.GaugeOpts{
72-
Namespace: "external_dns",
7368
Subsystem: "controller",
7469
Name: "last_sync_timestamp_seconds",
7570
Help: "Timestamp of last successful sync with the DNS provider",
7671
},
7772
)
7873
lastReconcileTimestamp = metrics.NewGaugeWithOpts(
7974
prometheus.GaugeOpts{
80-
Namespace: "external_dns",
8175
Subsystem: "controller",
8276
Name: "last_reconcile_timestamp_seconds",
8377
Help: "Timestamp of last attempted sync with the DNS provider",
8478
},
8579
)
8680
controllerNoChangesTotal = metrics.NewCounterWithOpts(
8781
prometheus.CounterOpts{
88-
Namespace: "external_dns",
8982
Subsystem: "controller",
9083
Name: "no_op_runs_total",
9184
Help: "Number of reconcile loops ending up with no changes on the DNS provider side.",
@@ -108,7 +101,6 @@ var (
108101

109102
registryRecords = metrics.NewGaugedVectorOpts(
110103
prometheus.GaugeOpts{
111-
Namespace: "external_dns",
112104
Subsystem: "registry",
113105
Name: "records",
114106
Help: "Number of registry records partitioned by label name (vector).",
@@ -118,7 +110,6 @@ var (
118110

119111
sourceRecords = metrics.NewGaugedVectorOpts(
120112
prometheus.GaugeOpts{
121-
Namespace: "external_dns",
122113
Subsystem: "source",
123114
Name: "records",
124115
Help: "Number of source records partitioned by label name (vector).",
@@ -128,7 +119,6 @@ var (
128119

129120
verifiedRecords = metrics.NewGaugedVectorOpts(
130121
prometheus.GaugeOpts{
131-
Namespace: "external_dns",
132122
Subsystem: "controller",
133123
Name: "verified_records",
134124
Help: "Number of DNS records that exists both in source and registry (vector).",
@@ -138,7 +128,6 @@ var (
138128

139129
consecutiveSoftErrors = metrics.NewGaugeWithOpts(
140130
prometheus.GaugeOpts{
141-
Namespace: "external_dns",
142131
Subsystem: "controller",
143132
Name: "consecutive_soft_errors",
144133
Help: "Number of consecutive soft errors in reconciliation loop.",

docs/monitoring/metrics.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ curl https://localhost:7979/metrics
2020
2121
| Name | Metric Type | Subsystem | Help |
2222
|:---------------------------------|:------------|:------------|:------------------------------------------------------|
23+
| 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. |
2324
| consecutive_soft_errors | Gauge | controller | Number of consecutive soft errors in reconciliation loop. |
2425
| last_reconcile_timestamp_seconds | Gauge | controller | Timestamp of last attempted sync with the DNS provider |
2526
| last_sync_timestamp_seconds | Gauge | controller | Timestamp of last successful sync with the DNS provider |

internal/gen/docs/metrics/main_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ func TestComputeMetrics(t *testing.T) {
3737
t.Errorf("Expected not empty metrics registry, got %d", len(reg.Metrics))
3838
}
3939

40-
assert.Len(t, reg.Metrics, 19)
40+
assert.Len(t, reg.Metrics, 20)
4141
}
4242

4343
func TestGenerateMarkdownTableRenderer(t *testing.T) {

pkg/metrics/metrics.go

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,25 +17,44 @@ limitations under the License.
1717
package metrics
1818

1919
import (
20-
"runtime"
20+
"fmt"
2121

2222
"github.com/prometheus/client_golang/prometheus"
23+
"github.com/prometheus/common/version"
2324
log "github.com/sirupsen/logrus"
2425

2526
cfg "sigs.k8s.io/external-dns/pkg/apis/externaldns"
2627
)
2728

29+
const (
30+
Namespace = "external_dns"
31+
)
32+
2833
var (
2934
RegisterMetric = NewMetricsRegister()
3035
)
3136

32-
func NewMetricsRegister() *MetricRegistry {
33-
reg := prometheus.WrapRegistererWith(
34-
prometheus.Labels{
37+
func init() {
38+
RegisterMetric.MustRegister(NewGaugeFuncMetric(prometheus.GaugeOpts{
39+
Namespace: Namespace,
40+
Name: "build_info",
41+
Help: fmt.Sprintf(
42+
"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.",
43+
Namespace,
44+
),
45+
ConstLabels: prometheus.Labels{
3546
"version": cfg.Version,
36-
"arch": runtime.GOARCH,
37-
"go_version": runtime.Version(),
47+
"revision": version.GetRevision(),
48+
"go_version": version.GoVersion,
49+
"os": version.GoOS,
50+
"arch": version.GoArch,
3851
},
52+
}))
53+
}
54+
55+
func NewMetricsRegister() *MetricRegistry {
56+
reg := prometheus.WrapRegistererWith(
57+
prometheus.Labels{},
3958
prometheus.DefaultRegisterer)
4059
return &MetricRegistry{
4160
Registerer: reg,
@@ -54,7 +73,7 @@ func NewMetricsRegister() *MetricRegistry {
5473
// }
5574
func (m *MetricRegistry) MustRegister(cs IMetric) {
5675
switch v := cs.(type) {
57-
case CounterMetric, GaugeMetric, CounterVecMetric, GaugeVecMetric:
76+
case CounterMetric, GaugeMetric, CounterVecMetric, GaugeVecMetric, GaugeFuncMetric:
5877
if _, exists := m.mName[cs.Get().FQDN]; exists {
5978
return
6079
} else {
@@ -70,6 +89,8 @@ func (m *MetricRegistry) MustRegister(cs IMetric) {
7089
m.Registerer.MustRegister(metric.Gauge)
7190
case CounterVecMetric:
7291
m.Registerer.MustRegister(metric.CounterVec)
92+
case GaugeFuncMetric:
93+
m.Registerer.MustRegister(metric.GaugeFunc)
7394
}
7495
log.Debugf("Register metric: %s", cs.Get().FQDN)
7596
default:

pkg/metrics/models.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ func (g GaugeVecMetric) SetWithLabels(value float64, lvs ...string) {
8888
}
8989

9090
func NewGaugeWithOpts(opts prometheus.GaugeOpts) GaugeMetric {
91+
opts.Namespace = Namespace
9192
return GaugeMetric{
9293
Metric: Metric{
9394
Type: "gauge",
@@ -104,6 +105,7 @@ func NewGaugeWithOpts(opts prometheus.GaugeOpts) GaugeMetric {
104105
// NewGaugedVectorOpts creates a new GaugeVec based on the provided GaugeOpts and
105106
// partitioned by the given label names.
106107
func NewGaugedVectorOpts(opts prometheus.GaugeOpts, labelNames []string) GaugeVecMetric {
108+
opts.Namespace = Namespace
107109
return GaugeVecMetric{
108110
Metric: Metric{
109111
Type: "gauge",
@@ -118,6 +120,7 @@ func NewGaugedVectorOpts(opts prometheus.GaugeOpts, labelNames []string) GaugeVe
118120
}
119121

120122
func NewCounterWithOpts(opts prometheus.CounterOpts) CounterMetric {
123+
opts.Namespace = Namespace
121124
return CounterMetric{
122125
Metric: Metric{
123126
Type: "counter",
@@ -132,6 +135,7 @@ func NewCounterWithOpts(opts prometheus.CounterOpts) CounterMetric {
132135
}
133136

134137
func NewCounterVecWithOpts(opts prometheus.CounterOpts, labelNames []string) CounterVecMetric {
138+
opts.Namespace = Namespace
135139
return CounterVecMetric{
136140
Metric: Metric{
137141
Type: "counter",
@@ -144,3 +148,31 @@ func NewCounterVecWithOpts(opts prometheus.CounterOpts, labelNames []string) Cou
144148
CounterVec: prometheus.NewCounterVec(opts, labelNames),
145149
}
146150
}
151+
152+
type GaugeFuncMetric struct {
153+
Metric
154+
GaugeFunc prometheus.GaugeFunc
155+
}
156+
157+
func (g GaugeFuncMetric) Get() *Metric {
158+
return &g.Metric
159+
}
160+
161+
func NewGaugeFuncMetric(opts prometheus.GaugeOpts) GaugeFuncMetric {
162+
return GaugeFuncMetric{
163+
Metric: Metric{
164+
Type: "gauge",
165+
Name: opts.Name,
166+
FQDN: func() string {
167+
if opts.Subsystem != "" {
168+
return fmt.Sprintf("%s_%s", opts.Subsystem, opts.Name)
169+
}
170+
return opts.Name
171+
}(),
172+
Namespace: opts.Namespace,
173+
Subsystem: opts.Subsystem,
174+
Help: opts.Help,
175+
},
176+
GaugeFunc: prometheus.NewGaugeFunc(opts, func() float64 { return 1 }),
177+
}
178+
}

pkg/metrics/models_test.go

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,18 +17,17 @@ limitations under the License.
1717
package metrics
1818

1919
import (
20+
"reflect"
2021
"testing"
2122

22-
dto "github.com/prometheus/client_model/go"
23-
2423
"github.com/prometheus/client_golang/prometheus"
24+
dto "github.com/prometheus/client_model/go"
2525
"github.com/stretchr/testify/assert"
2626
)
2727

2828
func TestNewGaugeWithOpts(t *testing.T) {
2929
opts := prometheus.GaugeOpts{
3030
Name: "test_gauge",
31-
Namespace: "test_namespace",
3231
Subsystem: "test_subsystem",
3332
Help: "This is a test gauge",
3433
}
@@ -37,7 +36,7 @@ func TestNewGaugeWithOpts(t *testing.T) {
3736

3837
assert.Equal(t, "gauge", gaugeMetric.Type)
3938
assert.Equal(t, "test_gauge", gaugeMetric.Name)
40-
assert.Equal(t, "test_namespace", gaugeMetric.Namespace)
39+
assert.Equal(t, Namespace, gaugeMetric.Namespace)
4140
assert.Equal(t, "test_subsystem", gaugeMetric.Subsystem)
4241
assert.Equal(t, "This is a test gauge", gaugeMetric.Help)
4342
assert.Equal(t, "test_subsystem_test_gauge", gaugeMetric.FQDN)
@@ -47,7 +46,6 @@ func TestNewGaugeWithOpts(t *testing.T) {
4746
func TestNewCounterWithOpts(t *testing.T) {
4847
opts := prometheus.CounterOpts{
4948
Name: "test_counter",
50-
Namespace: "test_namespace",
5149
Subsystem: "test_subsystem",
5250
Help: "This is a test counter",
5351
}
@@ -56,7 +54,7 @@ func TestNewCounterWithOpts(t *testing.T) {
5654

5755
assert.Equal(t, "counter", counterMetric.Type)
5856
assert.Equal(t, "test_counter", counterMetric.Name)
59-
assert.Equal(t, "test_namespace", counterMetric.Namespace)
57+
assert.Equal(t, Namespace, counterMetric.Namespace)
6058
assert.Equal(t, "test_subsystem", counterMetric.Subsystem)
6159
assert.Equal(t, "This is a test counter", counterMetric.Help)
6260
assert.Equal(t, "test_subsystem_test_counter", counterMetric.FQDN)
@@ -77,7 +75,7 @@ func TestNewCounterVecWithOpts(t *testing.T) {
7775

7876
assert.Equal(t, "counter", counterVecMetric.Type)
7977
assert.Equal(t, "test_counter_vec", counterVecMetric.Name)
80-
assert.Equal(t, "test_namespace", counterVecMetric.Namespace)
78+
assert.Equal(t, Namespace, counterVecMetric.Namespace)
8179
assert.Equal(t, "test_subsystem", counterVecMetric.Subsystem)
8280
assert.Equal(t, "This is a test counter vector", counterVecMetric.Help)
8381
assert.Equal(t, "test_subsystem_test_counter_vec", counterVecMetric.FQDN)
@@ -113,3 +111,20 @@ func TestGaugeV_SetWithLabels(t *testing.T) {
113111

114112
assert.Len(t, m.Label, 2)
115113
}
114+
115+
func TestNewBuildInfoCollector(t *testing.T) {
116+
metric := NewGaugeFuncMetric(prometheus.GaugeOpts{
117+
Namespace: Namespace,
118+
Name: "build_info",
119+
ConstLabels: prometheus.Labels{
120+
"version": "0.0.1",
121+
"goversion": "1.24",
122+
"arch": "arm64",
123+
},
124+
})
125+
126+
desc := metric.GaugeFunc.Desc()
127+
128+
assert.Equal(t, "external_dns_build_info", reflect.ValueOf(desc).Elem().FieldByName("fqName").String())
129+
assert.Contains(t, desc.String(), "version=\"0.0.1\"")
130+
}

provider/cached_provider.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ import (
3131
var (
3232
cachedRecordsCallsTotal = metrics.NewCounterVecWithOpts(
3333
prometheus.CounterOpts{
34-
Namespace: "external_dns",
3534
Subsystem: "provider",
3635
Name: "cache_records_calls",
3736
Help: "Number of calls to the provider cache Records list.",
@@ -42,7 +41,6 @@ var (
4241
)
4342
cachedApplyChangesCallsTotal = metrics.NewCounterWithOpts(
4443
prometheus.CounterOpts{
45-
Namespace: "external_dns",
4644
Subsystem: "provider",
4745
Name: "cache_apply_changes_calls",
4846
Help: "Number of calls to the provider cache ApplyChanges.",

provider/webhook/webhook.go

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -43,47 +43,41 @@ const (
4343
var (
4444
recordsErrorsGauge = metrics.NewGaugeWithOpts(
4545
prometheus.GaugeOpts{
46-
Namespace: "external_dns",
4746
Subsystem: "webhook_provider",
4847
Name: "records_errors_total",
4948
Help: "Errors with Records method",
5049
},
5150
)
5251
recordsRequestsGauge = metrics.NewGaugeWithOpts(
5352
prometheus.GaugeOpts{
54-
Namespace: "external_dns",
5553
Subsystem: "webhook_provider",
5654
Name: "records_requests_total",
5755
Help: "Requests with Records method",
5856
},
5957
)
6058
applyChangesErrorsGauge = metrics.NewGaugeWithOpts(
6159
prometheus.GaugeOpts{
62-
Namespace: "external_dns",
6360
Subsystem: "webhook_provider",
6461
Name: "applychanges_errors_total",
6562
Help: "Errors with ApplyChanges method",
6663
},
6764
)
6865
applyChangesRequestsGauge = metrics.NewGaugeWithOpts(
6966
prometheus.GaugeOpts{
70-
Namespace: "external_dns",
7167
Subsystem: "webhook_provider",
7268
Name: "applychanges_requests_total",
7369
Help: "Requests with ApplyChanges method",
7470
},
7571
)
7672
adjustEndpointsErrorsGauge = metrics.NewGaugeWithOpts(
7773
prometheus.GaugeOpts{
78-
Namespace: "external_dns",
7974
Subsystem: "webhook_provider",
8075
Name: "adjustendpoints_errors_total",
8176
Help: "Errors with AdjustEndpoints method",
8277
},
8378
)
8479
adjustEndpointsRequestsGauge = metrics.NewGaugeWithOpts(
8580
prometheus.GaugeOpts{
86-
Namespace: "external_dns",
8781
Subsystem: "webhook_provider",
8882
Name: "adjustendpoints_requests_total",
8983
Help: "Requests with AdjustEndpoints method",

0 commit comments

Comments
 (0)