Skip to content

Commit 5ca47dd

Browse files
authored
Adding a LastUpdated metric so that we can see when images were lookedup and if we have stale data (#346)
1 parent 355e219 commit 5ca47dd

File tree

2 files changed

+61
-12
lines changed

2 files changed

+61
-12
lines changed

pkg/metrics/metrics.go

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ type Metrics struct {
2525

2626
registry *prometheus.Registry
2727
containerImageVersion *prometheus.GaugeVec
28+
containerImageChecked *prometheus.GaugeVec
2829
containerImageDuration *prometheus.GaugeVec
2930
containerImageErrors *prometheus.CounterVec
3031

@@ -60,6 +61,16 @@ func NewServer(log *logrus.Entry) *Metrics {
6061
"namespace", "pod", "container", "container_type", "image", "current_version", "latest_version",
6162
},
6263
)
64+
containerImageChecked := promauto.With(reg).NewGaugeVec(
65+
prometheus.GaugeOpts{
66+
Namespace: "version_checker",
67+
Name: "last_checked",
68+
Help: "Timestamp when the image was checked",
69+
},
70+
[]string{
71+
"namespace", "pod", "container", "container_type", "image",
72+
},
73+
)
6374
containerImageDuration := promauto.With(reg).NewGaugeVec(
6475
prometheus.GaugeOpts{
6576
Namespace: "version_checker",
@@ -84,6 +95,7 @@ func NewServer(log *logrus.Entry) *Metrics {
8495
registry: reg,
8596
containerImageVersion: containerImageVersion,
8697
containerImageDuration: containerImageDuration,
98+
containerImageChecked: containerImageChecked,
8799
containerImageErrors: containerImageErrors,
88100
containerCache: make(map[string]cacheItem),
89101
roundTripper: NewRoundTripper(reg),
@@ -135,9 +147,14 @@ func (m *Metrics) AddImage(namespace, pod, container, containerType, imageURL st
135147
}
136148

137149
m.containerImageVersion.With(
138-
m.buildLabels(namespace, pod, container, containerType, imageURL, currentVersion, latestVersion),
150+
m.buildFullLabels(namespace, pod, container, containerType, imageURL, currentVersion, latestVersion),
139151
).Set(isLatestF)
140152

153+
// Bump last updated timestamp
154+
m.containerImageChecked.With(
155+
m.buildLastUpdatedLabels(namespace, pod, container, containerType, imageURL),
156+
).Set(float64(time.Now().Unix()))
157+
141158
index := m.latestImageIndex(namespace, pod, container, containerType)
142159
m.containerCache[index] = cacheItem{
143160
image: imageURL,
@@ -162,6 +179,9 @@ func (m *Metrics) RemoveImage(namespace, pod, container, containerType string) {
162179
m.containerImageDuration.DeletePartialMatch(
163180
m.buildPartialLabels(namespace, pod),
164181
)
182+
m.containerImageChecked.DeletePartialMatch(
183+
m.buildPartialLabels(namespace, pod),
184+
)
165185
delete(m.containerCache, index)
166186
}
167187

@@ -178,11 +198,10 @@ func (m *Metrics) latestImageIndex(namespace, pod, container, containerType stri
178198
}
179199

180200
func (m *Metrics) ErrorsReporting(namespace, pod, container, imageURL string) {
181-
182201
m.containerImageErrors.WithLabelValues(namespace, pod, container, imageURL).Inc()
183202
}
184203

185-
func (m *Metrics) buildLabels(namespace, pod, container, containerType, imageURL, currentVersion, latestVersion string) prometheus.Labels {
204+
func (m *Metrics) buildFullLabels(namespace, pod, container, containerType, imageURL, currentVersion, latestVersion string) prometheus.Labels {
186205
return prometheus.Labels{
187206
"namespace": namespace,
188207
"pod": pod,
@@ -194,6 +213,16 @@ func (m *Metrics) buildLabels(namespace, pod, container, containerType, imageURL
194213
}
195214
}
196215

216+
func (m *Metrics) buildLastUpdatedLabels(namespace, pod, container, containerType, imageURL string) prometheus.Labels {
217+
return prometheus.Labels{
218+
"namespace": namespace,
219+
"pod": pod,
220+
"container_type": containerType,
221+
"container": container,
222+
"image": imageURL,
223+
}
224+
}
225+
197226
func (m *Metrics) buildPartialLabels(namespace, pod string) prometheus.Labels {
198227
return prometheus.Labels{
199228
"namespace": namespace,

pkg/metrics/metrics_test.go

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,40 +3,60 @@ package metrics
33
import (
44
"fmt"
55
"testing"
6+
"time"
67

78
"github.com/prometheus/client_golang/prometheus"
89
"github.com/prometheus/client_golang/prometheus/testutil"
910
"github.com/sirupsen/logrus"
11+
1012
"github.com/stretchr/testify/assert"
13+
"github.com/stretchr/testify/require"
1114
)
1215

1316
func TestCache(t *testing.T) {
1417
m := NewServer(logrus.NewEntry(logrus.New()))
1518

19+
// Lets add some Images/Metrics...
1620
for i, typ := range []string{"init", "container"} {
1721
version := fmt.Sprintf("0.1.%d", i)
1822
m.AddImage("namespace", "pod", "container", typ, "url", true, version, version)
1923
}
2024

25+
// Check and ensure that the metrics are available...
2126
for i, typ := range []string{"init", "container"} {
2227
version := fmt.Sprintf("0.1.%d", i)
23-
mt, _ := m.containerImageVersion.GetMetricWith(m.buildLabels("namespace", "pod", "container", typ, "url", version, version))
28+
mt, err := m.containerImageVersion.GetMetricWith(m.buildFullLabels("namespace", "pod", "container", typ, "url", version, version))
29+
require.NoError(t, err)
30+
count := testutil.ToFloat64(mt)
31+
assert.Equal(t, count, float64(1))
32+
}
33+
34+
// as well as the lastUpdated...
35+
for _, typ := range []string{"init", "container"} {
36+
mt, err := m.containerImageChecked.GetMetricWith(m.buildLastUpdatedLabels("namespace", "pod", "container", typ, "url"))
37+
require.NoError(t, err)
2438
count := testutil.ToFloat64(mt)
25-
if count != 1 {
26-
t.Error("Should have added metric")
27-
}
39+
assert.GreaterOrEqual(t, count, float64(time.Now().Unix()))
2840
}
2941

42+
// Remove said metrics...
3043
for _, typ := range []string{"init", "container"} {
3144
m.RemoveImage("namespace", "pod", "container", typ)
3245
}
46+
// Ensure metrics and values return 0
3347
for i, typ := range []string{"init", "container"} {
3448
version := fmt.Sprintf("0.1.%d", i)
35-
mt, _ := m.containerImageVersion.GetMetricWith(m.buildLabels("namespace", "pod", "container", typ, "url", version, version))
49+
mt, err := m.containerImageVersion.GetMetricWith(m.buildFullLabels("namespace", "pod", "container", typ, "url", version, version))
50+
require.NoError(t, err)
51+
count := testutil.ToFloat64(mt)
52+
assert.Equal(t, count, float64(0))
53+
}
54+
// And the Last Updated is removed too
55+
for _, typ := range []string{"init", "container"} {
56+
mt, err := m.containerImageChecked.GetMetricWith(m.buildLastUpdatedLabels("namespace", "pod", "container", typ, "url"))
57+
require.NoError(t, err)
3658
count := testutil.ToFloat64(mt)
37-
if count != 0 {
38-
t.Error("Should have removed metric")
39-
}
59+
assert.Equal(t, count, float64(0))
4060
}
4161
}
4262

@@ -71,7 +91,7 @@ func TestErrorsReporting(t *testing.T) {
7191
"container": tc.container,
7292
"image": tc.image,
7393
})
74-
assert.NoError(t, err, "Failed to get metric with labels")
94+
require.NoError(t, err, "Failed to get metric with labels")
7595

7696
// Validate metric count
7797
fetchErrorCount := testutil.ToFloat64(metric)

0 commit comments

Comments
 (0)