mirror of
https://github.com/SigNoz/signoz.git
synced 2025-12-24 19:07:47 +00:00
126 lines
3.6 KiB
Go
126 lines
3.6 KiB
Go
package querier
|
|
|
|
import (
|
|
qbtypes "github.com/SigNoz/signoz/pkg/types/querybuildertypes/querybuildertypesv5"
|
|
)
|
|
|
|
// applyFormulas processes formula queries in the composite query
|
|
func (q *querier) applyFormulas(results map[string]*qbtypes.Result, req *qbtypes.QueryRangeRequest) map[string]*qbtypes.Result {
|
|
// Collect formula queries
|
|
formulaQueries := make(map[string]qbtypes.QueryBuilderFormula)
|
|
|
|
for _, query := range req.CompositeQuery.Queries {
|
|
if query.Type == qbtypes.QueryTypeFormula {
|
|
if formula, ok := query.Spec.(qbtypes.QueryBuilderFormula); ok {
|
|
formulaQueries[formula.Name] = formula
|
|
}
|
|
}
|
|
}
|
|
|
|
// Process each formula
|
|
for name, formula := range formulaQueries {
|
|
// Prepare time series data for formula evaluation
|
|
timeSeriesData := make(map[string]*qbtypes.TimeSeriesData)
|
|
|
|
// Extract time series data from results
|
|
for queryName, result := range results {
|
|
if tsData, ok := result.Value.(*qbtypes.TimeSeriesData); ok {
|
|
timeSeriesData[queryName] = tsData
|
|
}
|
|
}
|
|
|
|
// Create formula evaluator
|
|
canDefaultZero := make(map[string]bool)
|
|
for _, query := range req.CompositeQuery.Queries {
|
|
switch spec := query.Spec.(type) {
|
|
case qbtypes.QueryBuilderQuery[qbtypes.MetricAggregation]:
|
|
// Metrics can default to zero for rate/increase operations
|
|
canDefaultZero[spec.Name] = true
|
|
case qbtypes.QueryBuilderQuery[qbtypes.TraceAggregation]:
|
|
canDefaultZero[spec.Name] = false
|
|
case qbtypes.QueryBuilderQuery[qbtypes.LogAggregation]:
|
|
canDefaultZero[spec.Name] = false
|
|
}
|
|
}
|
|
|
|
evaluator, err := qbtypes.NewFormulaEvaluator(formula.Expression, canDefaultZero)
|
|
if err != nil {
|
|
q.logger.Error("failed to create formula evaluator", "error", err, "formula", name)
|
|
continue
|
|
}
|
|
|
|
// Evaluate the formula
|
|
formulaSeries, err := evaluator.EvaluateFormula(timeSeriesData)
|
|
if err != nil {
|
|
q.logger.Error("failed to evaluate formula", "error", err, "formula", name)
|
|
continue
|
|
}
|
|
|
|
// Create result for formula
|
|
formulaResult := &qbtypes.TimeSeriesData{
|
|
QueryName: name,
|
|
Aggregations: []*qbtypes.AggregationBucket{
|
|
{
|
|
Index: 0,
|
|
Series: formulaSeries,
|
|
},
|
|
},
|
|
}
|
|
|
|
// Apply functions if any
|
|
if len(formula.Functions) > 0 {
|
|
for _, agg := range formulaResult.Aggregations {
|
|
for i, series := range agg.Series {
|
|
agg.Series[i] = qbtypes.ApplyFunctions(formula.Functions, series)
|
|
}
|
|
}
|
|
}
|
|
|
|
results[name] = &qbtypes.Result{
|
|
Value: formulaResult,
|
|
}
|
|
}
|
|
|
|
return results
|
|
}
|
|
|
|
// filterDisabledQueries removes results for disabled queries
|
|
func (q *querier) filterDisabledQueries(results map[string]*qbtypes.Result, req *qbtypes.QueryRangeRequest) map[string]*qbtypes.Result {
|
|
filtered := make(map[string]*qbtypes.Result)
|
|
|
|
for _, query := range req.CompositeQuery.Queries {
|
|
var queryName string
|
|
var disabled bool
|
|
|
|
switch spec := query.Spec.(type) {
|
|
case qbtypes.QueryBuilderQuery[qbtypes.TraceAggregation]:
|
|
queryName = spec.Name
|
|
disabled = spec.Disabled
|
|
case qbtypes.QueryBuilderQuery[qbtypes.LogAggregation]:
|
|
queryName = spec.Name
|
|
disabled = spec.Disabled
|
|
case qbtypes.QueryBuilderQuery[qbtypes.MetricAggregation]:
|
|
queryName = spec.Name
|
|
disabled = spec.Disabled
|
|
case qbtypes.QueryBuilderFormula:
|
|
queryName = spec.Name
|
|
// Formulas don't have a disabled flag, include them
|
|
disabled = false
|
|
case qbtypes.PromQuery:
|
|
queryName = spec.Name
|
|
disabled = spec.Disabled
|
|
case qbtypes.ClickHouseQuery:
|
|
queryName = spec.Name
|
|
disabled = spec.Disabled
|
|
}
|
|
|
|
if !disabled {
|
|
if result, ok := results[queryName]; ok {
|
|
filtered[queryName] = result
|
|
}
|
|
}
|
|
}
|
|
|
|
return filtered
|
|
}
|