Repository: prometheus/prometheus
File: promql/functions.go (Go)

Code before:
	vec := vals[0].(Vector)
	for _, sample := range vec {
		// Skip non-histogram samples.
		if sample.H == nil {
			continue
		}
		mean := sample.H.Sum / sample.H.Count
		var variance, cVariance float64
		it := sample.H.AllBucketIterator()
		for it.Next() {
			bucket := it.At()
			if bucket.Count == 0 {
				continue
			}
			var val float64
			if sample.H.UsesCustomBuckets() {
				// use arithmetic mean in case of NHCB.
				val = (bucket.Upper * bucket.Lower) / 2.0
			} else {
				if bucket.Lower <= 0 && bucket.Upper >= 0 {
					val = 0
				} else {
					val = math.Sqrt(bucket.Upper * bucket.Lower)
					if bucket.Upper < 0 {
						val = -val
					}
				}
			}
			delta := val - mean
			variance, cVariance = kahanSumInc(bucket.Count*delta*delta, variance, cVariance)
		}
		variance += cVariance
		variance /= sample.H.Count
		if !enh.enableDelayedNameRemoval {
			sample.Metric = sample.Metric.DropMetricName()
		}
		if varianceToResult != nil {
			variance = varianceToResult(variance)
		}
		enh.Out = append(enh.Out, Sample{
			Metric:   sample.Metric,
			F:        variance,
			DropName: true,
		})
	}
	return enh.Out, nil
}

// === histogram_stddev(Vector parser.ValueTypeVector) (Vector, Annotations)  ===
func funcHistogramStdDev(vals []parser.Value, _ parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) {
	return histogramVariance(vals, enh, math.Sqrt)

Review comment (suggestion):
Instead of using an if/else cascade, this should just be a switch statement. It could also deserve a comment for each branch like "Use arithmetic mean in the zero bucket." and "Use geometric mean in standard exponential buckets."

Code after:
	for _, sample := range vec {
		// Skip non-histogram samples.
		if sample.H == nil {
			continue
		}
		mean := sample.H.Sum / sample.H.Count
		var variance, cVariance float64
		it := sample.H.AllBucketIterator()
		for it.Next() {
			bucket := it.At()
			if bucket.Count == 0 {
				continue
			}
			var val float64
			switch {
			case sample.H.UsesCustomBuckets():
				// Use arithmetic mean in case of custom buckets.
				val = (bucket.Upper + bucket.Lower) / 2.0
			case bucket.Lower <= 0 && bucket.Upper >= 0:
				// Use zero (effectively the arithmetic mean) in the zero bucket of a standard exponential histogram.
				val = 0
			default:
				// Use geometric mean in case of standard exponential buckets.
				val = math.Sqrt(bucket.Upper * bucket.Lower)
				if bucket.Upper < 0 {
					val = -val
				}
			}
			delta := val - mean
			variance, cVariance = kahanSumInc(bucket.Count*delta*delta, variance, cVariance)
		}
		variance += cVariance
		variance /= sample.H.Count
		if !enh.enableDelayedNameRemoval {
			sample.Metric = sample.Metric.DropMetricName()
		}
		if varianceToResult != nil {
			variance = varianceToResult(variance)
		}
		enh.Out = append(enh.Out, Sample{
			Metric:   sample.Metric,
			F:        variance,
			DropName: true,
		})
	}
	return enh.Out, nil
}

// === histogram_stddev(Vector parser.ValueTypeVector) (Vector, Annotations)  ===
func funcHistogramStdDev(vals []parser.Value, _ parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) {
	return histogramVariance(vals, enh, math.Sqrt)