logs-analyzer/signoz/pkg/query-service/pqlEngine/engine.go

126 lines
2.9 KiB
Go
Raw Permalink Normal View History

2024-09-02 22:47:30 +03:00
package promql
import (
"context"
"fmt"
"time"
"github.com/go-kit/log"
pmodel "github.com/prometheus/common/model"
"github.com/prometheus/common/promlog"
pconfig "github.com/prometheus/prometheus/config"
pql "github.com/prometheus/prometheus/promql"
pstorage "github.com/prometheus/prometheus/storage"
premote "github.com/prometheus/prometheus/storage/remote"
"go.signoz.io/signoz/pkg/query-service/interfaces"
)
type PqlEngine struct {
engine *pql.Engine
fanoutStorage pstorage.Storage
}
func FromConfigPath(promConfigPath string) (*PqlEngine, error) {
// load storage path
c, err := pconfig.LoadFile(promConfigPath, false, false, nil)
if err != nil {
return nil, fmt.Errorf("couldn't load configuration (--config.file=%q): %v", promConfigPath, err)
}
return NewPqlEngine(c)
}
func FromReader(ch interfaces.Reader) (*PqlEngine, error) {
return &PqlEngine{
engine: ch.GetQueryEngine(),
fanoutStorage: *ch.GetFanoutStorage(),
}, nil
}
func NewPqlEngine(config *pconfig.Config) (*PqlEngine, error) {
logLevel := promlog.AllowedLevel{}
logLevel.Set("debug")
allowedFormat := promlog.AllowedFormat{}
allowedFormat.Set("logfmt")
promlogConfig := promlog.Config{
Level: &logLevel,
Format: &allowedFormat,
}
logger := promlog.New(&promlogConfig)
opts := pql.EngineOpts{
Logger: log.With(logger, "component", "promql evaluator"),
Reg: nil,
MaxSamples: 50000000,
Timeout: time.Duration(2 * time.Minute),
ActiveQueryTracker: pql.NewActiveQueryTracker(
"",
20,
logger,
),
}
e := pql.NewEngine(opts)
startTime := func() (int64, error) {
return int64(pmodel.Latest), nil
}
remoteStorage := premote.NewStorage(
log.With(logger, "component", "remote"),
nil,
startTime,
"",
time.Duration(1*time.Minute),
nil,
)
fanoutStorage := pstorage.NewFanout(logger, remoteStorage)
remoteStorage.ApplyConfig(config)
return &PqlEngine{
engine: e,
fanoutStorage: fanoutStorage,
}, nil
}
func (p *PqlEngine) RunAlertQuery(ctx context.Context, qs string, start, end time.Time, interval time.Duration) (pql.Matrix, error) {
q, err := p.engine.NewRangeQuery(ctx, p.fanoutStorage, nil, qs, start, end, interval)
if err != nil {
return nil, err
}
res := q.Exec(ctx)
if res.Err != nil {
return nil, res.Err
}
switch typ := res.Value.(type) {
case pql.Vector:
series := make([]pql.Series, 0, len(typ))
value := res.Value.(pql.Vector)
for _, smpl := range value {
series = append(series, pql.Series{
Metric: smpl.Metric,
Floats: []pql.FPoint{{T: smpl.T, F: smpl.F}},
})
}
return series, nil
case pql.Scalar:
value := res.Value.(pql.Scalar)
series := make([]pql.Series, 0, 1)
series = append(series, pql.Series{
Floats: []pql.FPoint{{T: value.T, F: value.V}},
})
return series, nil
case pql.Matrix:
return res.Value.(pql.Matrix), nil
default:
return nil, fmt.Errorf("rule result is not a vector or scalar")
}
}