func WithCartesianProductLabelReset()

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)
		}
	}
}