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

Code before:
}

// === predict_linear(node parser.ValueTypeMatrix, k parser.ValueTypeScalar) (Vector, Annotations) ===
func funcPredictLinear(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) {
	samples := vals[0].(Matrix)[0]
	duration := vals[1].(Vector)[0].F
	metricName := samples.Metric.Get(labels.MetricName)

	// No sense in trying to predict anything without at least two float points.
	// Drop this Vector element.
	if len(samples.Floats) < 2 {
		// Annotate mix of float and histogram.
		if len(samples.Floats) == 1 && len(samples.Histograms) > 0 {
			return enh.Out, annotations.New().Add(annotations.NewHistogramIgnoredInMixedRangeInfo(metricName, args[0].PositionRange()))
		}
		return enh.Out, nil
	}

	slope, intercept := linearRegression(samples.Floats, enh.Ts)
	if len(samples.Histograms) > 0 {
		return append(enh.Out, Sample{F: slope*duration + intercept}), annotations.New().Add(annotations.NewHistogramIgnoredInMixedRangeInfo(metricName, args[0].PositionRange()))
	}
	return append(enh.Out, Sample{F: slope*duration + intercept}), nil
}

func simpleHistFunc(vals []parser.Value, enh *EvalNodeHelper, f func(h *histogram.FloatHistogram) float64) Vector {
	for _, el := range vals[0].(Vector) {
		if el.H != nil { // Process only histogram samples.
			if !enh.enableDelayedNameRemoval {
				el.Metric = el.Metric.DropMetricName()
			}
			enh.Out = append(enh.Out, Sample{
				Metric:   el.Metric,
				F:        f(el.H),
				DropName: true,
			})
		}
	}
	return enh.Out
}

// === histogram_count(Vector parser.ValueTypeVector) (Vector, Annotations) ===
func funcHistogramCount(vals []parser.Value, _ parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) {
	return simpleHistFunc(vals, enh, func(h *histogram.FloatHistogram) float64 {
		return h.Count
	}), nil
}

// === histogram_sum(Vector parser.ValueTypeVector) (Vector, Annotations) ===
func funcHistogramSum(vals []parser.Value, _ parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) {
	return simpleHistFunc(vals, enh, func(h *histogram.FloatHistogram) float64 {

Review comment (suggestion):
I'm not a great fan of abbreviations that do not abbreviate much but still create ambiguity (has this to do with historic values?).

Let's call this `simpleHistogramFunc` or if we want to be short, do `simpleHFunc`.

Maybe we should also rename the existing `simpleFunc` to `simpleFloatFunc` or `simpleFFunc`.

My personal preference would be `simpleHistogramFunc` and `simpleFloatFunc`.

Code after:
	return append(enh.Out, Sample{F: slope}), nil
}

// === predict_linear(node parser.ValueTypeMatrix, k parser.ValueTypeScalar) (Vector, Annotations) ===
func funcPredictLinear(vals []parser.Value, args parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) {
	samples := vals[0].(Matrix)[0]
	duration := vals[1].(Vector)[0].F
	metricName := samples.Metric.Get(labels.MetricName)

	// No sense in trying to predict anything without at least two float points.
	// Drop this Vector element.
	if len(samples.Floats) < 2 {
		// Annotate mix of float and histogram.
		if len(samples.Floats) == 1 && len(samples.Histograms) > 0 {
			return enh.Out, annotations.New().Add(annotations.NewHistogramIgnoredInMixedRangeInfo(metricName, args[0].PositionRange()))
		}
		return enh.Out, nil
	}

	slope, intercept := linearRegression(samples.Floats, enh.Ts)
	if len(samples.Histograms) > 0 {
		return append(enh.Out, Sample{F: slope*duration + intercept}), annotations.New().Add(annotations.NewHistogramIgnoredInMixedRangeInfo(metricName, args[0].PositionRange()))
	}
	return append(enh.Out, Sample{F: slope*duration + intercept}), nil
}

func simpleHistogramFunc(vals []parser.Value, enh *EvalNodeHelper, f func(h *histogram.FloatHistogram) float64) Vector {
	for _, el := range vals[0].(Vector) {
		if el.H != nil { // Process only histogram samples.
			if !enh.enableDelayedNameRemoval {
				el.Metric = el.Metric.DropMetricName()
			}
			enh.Out = append(enh.Out, Sample{
				Metric:   el.Metric,
				F:        f(el.H),
				DropName: true,
			})
		}
	}
	return enh.Out
}

// === histogram_count(Vector parser.ValueTypeVector) (Vector, Annotations) ===
func funcHistogramCount(vals []parser.Value, _ parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) {
	return simpleHistogramFunc(vals, enh, func(h *histogram.FloatHistogram) float64 {
		return h.Count
	}), nil
}

// === histogram_sum(Vector parser.ValueTypeVector) (Vector, Annotations) ===
func funcHistogramSum(vals []parser.Value, _ parser.Expressions, enh *EvalNodeHelper) (Vector, annotations.Annotations) {