logs-analyzer/signoz/pkg/query-service/postprocess/having.go
2024-09-02 22:47:30 +03:00

105 lines
2.6 KiB
Go

package postprocess
import (
"strings"
v3 "go.signoz.io/signoz/pkg/query-service/model/v3"
)
// ApplyHavingClause applies the having clause to the result
// each query has its own having clause
// there can be multiple having clauses for each query
func ApplyHavingClause(result []*v3.Result, queryRangeParams *v3.QueryRangeParamsV3) {
for _, result := range result {
builderQueries := queryRangeParams.CompositeQuery.BuilderQueries
// apply having clause for metrics and formula
if builderQueries != nil &&
(builderQueries[result.QueryName].DataSource == v3.DataSourceMetrics ||
builderQueries[result.QueryName].QueryName != builderQueries[result.QueryName].Expression) {
havingClause := builderQueries[result.QueryName].Having
for i := 0; i < len(result.Series); i++ {
for j := 0; j < len(result.Series[i].Points); j++ {
if !evaluateHavingClause(havingClause, result.Series[i].Points[j].Value) {
result.Series[i].Points = append(result.Series[i].Points[:j], result.Series[i].Points[j+1:]...)
j--
}
}
if len(result.Series[i].Points) == 0 {
result.Series = append(result.Series[:i], result.Series[i+1:]...)
i--
}
}
}
}
}
func evaluateHavingClause(having []v3.Having, value float64) bool {
if len(having) == 0 {
return true
}
satisfied := true
for _, h := range having {
switch h.Operator {
case v3.HavingOperatorEqual:
if value != h.Value.(float64) {
satisfied = false
}
case v3.HavingOperatorNotEqual:
if value == h.Value.(float64) {
satisfied = false
}
case v3.HavingOperatorGreaterThan:
if value <= h.Value.(float64) {
satisfied = false
}
case v3.HavingOperatorGreaterThanOrEq:
if value < h.Value.(float64) {
satisfied = false
}
case v3.HavingOperatorLessThan:
if value >= h.Value.(float64) {
satisfied = false
}
case v3.HavingOperatorLessThanOrEq:
if value > h.Value.(float64) {
satisfied = false
}
case v3.HavingOperatorIn, v3.HavingOperator(strings.ToLower(string(v3.HavingOperatorIn))):
values, ok := h.Value.([]interface{})
if !ok {
satisfied = false
}
found := false
for _, v := range values {
if value == v.(float64) {
found = true
break
}
}
if !found {
satisfied = false
}
case v3.HavingOperatorNotIn, v3.HavingOperator(strings.ToLower(string(v3.HavingOperatorNotIn))):
values, ok := h.Value.([]interface{})
if !ok {
satisfied = false
}
found := false
for _, v := range values {
if value == v.(float64) {
found = true
break
}
}
if found {
satisfied = false
}
}
}
return satisfied
}