mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
SSE/Alerting: Support prom instant vector responses (#44865)
* SSE/Alerting: (Draft) Support prom instant vector responses fixes #35663 * reduce\classic expressions to handle mathexp.Number * use Notice for warning Co-authored-by: Yuriy Tseretyan <yuriy.tseretyan@grafana.com>
This commit is contained in:
@@ -8,6 +8,7 @@ import (
|
||||
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||
"github.com/grafana/grafana-plugin-sdk-go/data"
|
||||
|
||||
"github.com/grafana/grafana/pkg/expr/classic"
|
||||
"github.com/grafana/grafana/pkg/expr/mathexp"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
@@ -236,6 +237,15 @@ func (dn *DSNode) Execute(ctx context.Context, vars mathexp.Vars, s *Service) (m
|
||||
return mathexp.Results{}, QueryError{RefID: refID, Err: qr.Error}
|
||||
}
|
||||
|
||||
dataSource := dn.datasource.Type
|
||||
if isAllFrameVectors(dataSource, qr.Frames) {
|
||||
vals, err = framesToNumbers(qr.Frames)
|
||||
if err != nil {
|
||||
return mathexp.Results{}, fmt.Errorf("failed to read frames as numbers: %w", err)
|
||||
}
|
||||
return mathexp.Results{Values: vals}, nil
|
||||
}
|
||||
|
||||
if len(qr.Frames) == 1 {
|
||||
frame := qr.Frames[0]
|
||||
if frame.TimeSeriesSchema().Type == data.TimeSeriesTypeNot && isNumberTable(frame) {
|
||||
@@ -254,7 +264,6 @@ func (dn *DSNode) Execute(ctx context.Context, vars mathexp.Vars, s *Service) (m
|
||||
}
|
||||
}
|
||||
|
||||
dataSource := dn.datasource.Type
|
||||
for _, frame := range qr.Frames {
|
||||
logger.Debug("expression datasource query (seriesSet)", "query", refID)
|
||||
// Check for TimeSeriesTypeNot in InfluxDB queries. A data frame of this type will cause
|
||||
@@ -278,6 +287,51 @@ func (dn *DSNode) Execute(ctx context.Context, vars mathexp.Vars, s *Service) (m
|
||||
}, nil
|
||||
}
|
||||
|
||||
func isAllFrameVectors(datasourceType string, frames data.Frames) bool {
|
||||
if datasourceType != "prometheus" {
|
||||
return false
|
||||
}
|
||||
allVector := false
|
||||
for i, frame := range frames {
|
||||
if frame.Meta != nil && frame.Meta.Custom != nil {
|
||||
if sMap, ok := frame.Meta.Custom.(map[string]string); ok {
|
||||
if sMap != nil {
|
||||
if sMap["resultType"] == "vector" {
|
||||
if i != 0 && !allVector {
|
||||
break
|
||||
}
|
||||
allVector = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return allVector
|
||||
}
|
||||
|
||||
func framesToNumbers(frames data.Frames) ([]mathexp.Value, error) {
|
||||
vals := make([]mathexp.Value, 0, len(frames))
|
||||
for _, frame := range frames {
|
||||
if frame == nil {
|
||||
continue
|
||||
}
|
||||
if len(frame.Fields) == 2 && frame.Fields[0].Len() == 1 {
|
||||
// Can there be zero Len Field results that are being skipped?
|
||||
valueField := frame.Fields[1]
|
||||
if valueField.Type().Numeric() { // should be []float64
|
||||
val, err := valueField.FloatAt(0) // FloatAt should not err if numeric
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to read value of frame [%v] (RefID %v) of type [%v] as float: %w", frame.Name, frame.RefID, valueField.Type(), err)
|
||||
}
|
||||
n := mathexp.NewNumber(frame.Name, valueField.Labels)
|
||||
n.SetValue(&val)
|
||||
vals = append(vals, n)
|
||||
}
|
||||
}
|
||||
}
|
||||
return vals, nil
|
||||
}
|
||||
|
||||
func isNumberTable(frame *data.Frame) bool {
|
||||
if frame == nil || frame.Fields == nil {
|
||||
return false
|
||||
|
||||
Reference in New Issue
Block a user