Skip to content

Commit 0f04b64

Browse files
committed
metrics: simplify WithLabelValues
With a map instead of a slice stored in the extended manager, the logic when recording a metric becomes simpler.
1 parent d9275a5 commit 0f04b64

File tree

2 files changed

+29
-29
lines changed

2 files changed

+29
-29
lines changed

metrics/metrics.go

Lines changed: 28 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -229,26 +229,18 @@ func (cmm *csiMetricsManager) RecordMetrics(
229229
operationName string,
230230
operationErr error,
231231
operationDuration time.Duration) {
232-
cmm.recordMetricsWithLabels(operationName, operationErr, operationDuration)
232+
cmm.recordMetricsWithLabels(operationName, operationErr, operationDuration, nil)
233233
}
234234

235235
// recordMetricsWithLabels is the internal implementation of RecordMetrics.
236236
func (cmm *csiMetricsManager) recordMetricsWithLabels(
237237
operationName string,
238238
operationErr error,
239239
operationDuration time.Duration,
240-
labelValues ...string) {
240+
labelValues map[string]string) {
241241
values := []string{cmm.driverName, operationName, getErrorCode(operationErr)}
242-
toAdd := len(labelValues)
243-
if toAdd > len(cmm.additionalLabelNames) {
244-
// To many labels?! Truncate. Shouldn't happen because of
245-
// error checking in WithLabelValues.
246-
toAdd = len(cmm.additionalLabelNames)
247-
}
248-
values = append(values, labelValues[0:toAdd]...)
249-
for i := toAdd; i < len(cmm.additionalLabelNames); i++ {
250-
// Backfill missing values with empty string.
251-
values = append(values, "")
242+
for _, name := range cmm.additionalLabelNames {
243+
values = append(values, labelValues[name])
252244
}
253245
for _, label := range cmm.additionalLabels {
254246
values = append(values, label.value)
@@ -260,34 +252,42 @@ type csiMetricsManagerWithValues struct {
260252
*csiMetricsManager
261253

262254
// additionalValues holds the values passed via WithLabelValues.
263-
additionalValues []string
255+
additionalValues map[string]string
264256
}
265257

266258
// WithLabelValues in the base metrics manager creates a fresh wrapper with no labels and let's
267259
// that deal with adding the label values.
268260
func (cmm *csiMetricsManager) WithLabelValues(labels map[string]string) (CSIMetricsManager, error) {
269-
cmmv := &csiMetricsManagerWithValues{csiMetricsManager: cmm}
261+
cmmv := &csiMetricsManagerWithValues{
262+
csiMetricsManager: cmm,
263+
additionalValues: map[string]string{},
264+
}
270265
return cmmv.WithLabelValues(labels)
271266
}
272267

273268
// WithLabelValues in the wrapper creates a wrapper which has all existing labels and
274-
// adds the new ones, with error checking.
269+
// adds the new ones, with error checking. Can be called multiple times. Each call then
270+
// can add some new value(s). It is an error to overwrite an already set value.
271+
// If RecordMetrics is called before setting all additional values, the missing ones will
272+
// be empty.
275273
func (cmmv *csiMetricsManagerWithValues) WithLabelValues(labels map[string]string) (CSIMetricsManager, error) {
276-
extended := &csiMetricsManagerWithValues{cmmv.csiMetricsManager, append([]string{}, cmmv.additionalValues...)}
277-
278-
for name := range labels {
279-
if !cmmv.haveAdditionalLabel(name) {
274+
extended := &csiMetricsManagerWithValues{
275+
csiMetricsManager: cmmv.csiMetricsManager,
276+
additionalValues: map[string]string{},
277+
}
278+
// We need to copy the old values to avoid modifying the map in cmmv.
279+
for name, value := range cmmv.additionalValues {
280+
extended.additionalValues[name] = value
281+
}
282+
// Now add all new values.
283+
for name, value := range labels {
284+
if !extended.haveAdditionalLabel(name) {
280285
return nil, fmt.Errorf("label %q was not defined via WithLabelNames", name)
281286
}
282-
}
283-
// Add in same order as in the label definition.
284-
for _, name := range cmmv.additionalLabelNames {
285-
if value, ok := labels[name]; ok {
286-
if len(cmmv.additionalValues) >= len(extended.additionalLabelNames) {
287-
return nil, fmt.Errorf("label %q = %q cannot be added, all labels already have values %v", name, value, cmmv.additionalValues)
288-
}
289-
extended.additionalValues = append(extended.additionalValues, value)
287+
if v, ok := extended.additionalValues[name]; ok {
288+
return nil, fmt.Errorf("label %q already has value %q", name, v)
290289
}
290+
extended.additionalValues[name] = value
291291
}
292292
return extended, nil
293293
}
@@ -306,7 +306,7 @@ func (cmmv *csiMetricsManagerWithValues) RecordMetrics(
306306
operationName string,
307307
operationErr error,
308308
operationDuration time.Duration) {
309-
cmmv.recordMetricsWithLabels(operationName, operationErr, operationDuration, cmmv.additionalValues...)
309+
cmmv.recordMetricsWithLabels(operationName, operationErr, operationDuration, cmmv.additionalValues)
310310
}
311311

312312
// SetDriverName is called to update the CSI driver name. This should be done

metrics/metrics_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -335,7 +335,7 @@ func TestVaryingLabels_NameError(t *testing.T) {
335335
}
336336
}
337337

338-
func TestVaryingLabels_NumberError(t *testing.T) {
338+
func TestVaryingLabels_OverwriteError(t *testing.T) {
339339
cmm := NewCSIMetricsManagerWithOptions(
340340
"", /* driverName */
341341
WithLabelNames("a", "b"),

0 commit comments

Comments
 (0)