in metrics/internal/metrics/metadata.go [60:133]
func WithCartesianProductLabelReset() MetricOption {
return func(desc *descriptionOpts) {
if len(desc.labels) == 0 {
return
}
// index is a slice containing the current permutation of label values indexes.
// index[i] will be the current index for desc.labelValues[i],
// on each step of the loop we will produce something like this:
// given n = len(desc.labelValues)-1
// { labelValues[0][index[0]], ... labelValues[i][index[i]], .... labelValues[n][index[n]] }
index := make([]int, len(desc.labels))
labelValues := make([][]string, len(desc.labels))
for i, label := range desc.labels {
labelValues[i] = label.Values()
}
// nextIndex sets index to the next permutation of labels, the index is built incrementing
// elements from the end of the slice.
// Each element goes from the first to the last label value index.
// This function will increment index values such that for each i>0, 0 <= index[i] < lens(i).
//
// Example:
// - assuming we have 3 labels with 2, 2, and 3 values respectivery,
// - and index = { 0, 0, 0 }
//
// nextIndex will update index with the following values on each invocation:
// - { 0, 0, 1 }
// - { 0, 0, 2 }
// - { 0, 1, 0 }
// - { 0, 1, 1 }
// - { 0, 1, 2 }
// - { 1, 0, 0 }
// - { 1, 0, 1 }
// - { 1, 0, 2 }
// - { 1, 1, 0 }
// - { 1, 1, 1 }
// - { 1, 1, 2 }
// - { 2, 0, 0 } <-- this is not a valid index, we will use this as the exit condition for our initializer
nextIndex := func() {
// we loop over the labels from the last one to the first one, increasing each index (and returning)
// until we reach the last valid index for that label.
// We the last index is found, we reset to 0 and move to the next label.
for labelIdx := len(index) - 1; labelIdx >= 0; labelIdx-- {
index[labelIdx]++
// we don't want to go to the next label until we processed all the possible label values for the current labelIdx.
// here is where we identify if the current values in index are a valid next index and return
if index[labelIdx] < len(labelValues[labelIdx]) || // the current index[labelIdx] is valid
labelIdx == 0 { // or we are handling the last index (we loop in backward)
// here index contains a new permutation
return
}
// here we have already built all the permutations for labelIdx
// it's time to set it back to 0 and let the loop move to the next label
index[labelIdx] = 0
}
}
// we loop on every permutation from nextIndex until we reach an invalid index
for firsLabelSize := len(labelValues[0]); index[0] < firsLabelSize; nextIndex() {
var labels []string
for labelIdx, labelValueIdx := range index {
labels = append(labels, labelValues[labelIdx][labelValueIdx])
}
WithLabelReset(labels...)(desc)
}
}
}