2023-07-21 18:38:29 +08:00
package expr
import (
"errors"
2023-09-14 01:58:16 +08:00
"fmt"
2025-04-04 22:00:30 +08:00
"sort"
"strings"
2023-07-21 18:38:29 +08:00
2024-06-13 12:11:35 +08:00
"github.com/grafana/grafana/pkg/apimachinery/errutil"
2023-07-21 18:38:29 +08:00
)
2024-05-08 00:31:07 +08:00
var ErrSeriesMustBeWide = errors . New ( "input data must be a wide series" )
2023-08-22 18:52:24 +08:00
var ConversionError = errutil . BadRequest ( "sse.readDataError" ) . MustTemplate (
2023-07-21 18:38:29 +08:00
"[{{ .Public.refId }}] got error: {{ .Error }}" ,
errutil . WithPublic (
"failed to read data from from query {{ .Public.refId }}: {{ .Public.error }}" ,
) ,
)
2023-09-14 01:58:16 +08:00
func makeConversionError ( refID string , err error ) error {
2023-07-21 18:38:29 +08:00
data := errutil . TemplateData {
// Conversion errors should only have meta information in errors
2023-08-30 23:46:47 +08:00
Public : map [ string ] any {
2023-07-21 18:38:29 +08:00
"refId" : refID ,
"error" : err . Error ( ) ,
} ,
Error : err ,
}
return ConversionError . Build ( data )
}
2023-08-22 18:52:24 +08:00
var QueryError = errutil . BadRequest ( "sse.dataQueryError" ) . MustTemplate (
2023-07-21 18:38:29 +08:00
"failed to execute query [{{ .Public.refId }}]: {{ .Error }}" ,
errutil . WithPublic (
"failed to execute query [{{ .Public.refId }}]: {{ .Public.error }}" ,
) )
func MakeQueryError ( refID , datasourceUID string , err error ) error {
var pErr error
var utilErr errutil . Error
// See if this is grafana error, if so, grab public message
if errors . As ( err , & utilErr ) {
pErr = utilErr . Public ( )
} else {
pErr = err
}
data := errutil . TemplateData {
2023-08-30 23:46:47 +08:00
Public : map [ string ] any {
2023-07-21 18:38:29 +08:00
"refId" : refID ,
"datasourceUID" : datasourceUID ,
"error" : pErr . Error ( ) ,
} ,
Error : err ,
}
return QueryError . Build ( data )
}
2023-09-14 01:58:16 +08:00
var depErrStr = "did not execute expression [{{ .Public.refId }}] due to a failure to of the dependent expression or query [{{.Public.depRefId}}]"
var DependencyError = errutil . NewBase (
errutil . StatusBadRequest , "sse.dependencyError" ) . MustTemplate (
depErrStr ,
errutil . WithPublic ( depErrStr ) )
2024-06-11 23:37:10 +08:00
func MakeDependencyError ( refID , depRefID string ) error {
2023-09-14 01:58:16 +08:00
data := errutil . TemplateData {
Public : map [ string ] interface { } {
"refId" : refID ,
"depRefId" : depRefID ,
} ,
Error : fmt . Errorf ( "did not execute expression %v due to a failure to of the dependent expression or query %v" , refID , depRefID ) ,
}
return DependencyError . Build ( data )
}
var unexpectedNodeTypeErrString = "expected executable node type but got node type [{{ .Public.nodeType }} for refid [{{ .Public.refId}}]"
var UnexpectedNodeTypeError = errutil . NewBase (
errutil . StatusBadRequest , "sse.unexpectedNodeType" ) . MustTemplate (
unexpectedNodeTypeErrString ,
errutil . WithPublic ( unexpectedNodeTypeErrString ) )
func makeUnexpectedNodeTypeError ( refID , nodeType string ) error {
data := errutil . TemplateData {
Public : map [ string ] interface { } {
"refId" : refID ,
"nodeType" : nodeType ,
} ,
Error : fmt . Errorf ( "expected executable node type but got node type %v for refId %v" , nodeType , refID ) ,
}
return UnexpectedNodeTypeError . Build ( data )
}
2025-04-04 22:00:30 +08:00
var DuplicateStringColumnError = errutil . NewBase (
errutil . StatusBadRequest , "sse.duplicateStringColumns" ) . MustTemplate (
"your SQL query returned {{ .Public.count }} rows with duplicate values across the string columns, which is not allowed for alerting. Examples: ({{ .Public.examples }}). Hint: use GROUP BY or aggregation (e.g. MAX(), AVG()) to return one row per unique combination." ,
errutil . WithPublic ( "SQL query returned duplicate combinations of string column values. Use GROUP BY or aggregation to return one row per combination." ) ,
)
func makeDuplicateStringColumnError ( examples [ ] string ) error {
const limit = 5
sort . Strings ( examples )
exampleStr := strings . Join ( truncateExamples ( examples , limit ) , ", " )
return DuplicateStringColumnError . Build ( errutil . TemplateData {
Public : map [ string ] any {
"examples" : exampleStr ,
"count" : len ( examples ) ,
} ,
} )
}
func truncateExamples ( examples [ ] string , limit int ) [ ] string {
if len ( examples ) <= limit {
return examples
}
truncated := examples [ : limit ]
truncated = append ( truncated , fmt . Sprintf ( "... and %d more" , len ( examples ) - limit ) )
return truncated
}