feat(alerting): moved alerting models back to alerting package, models is more for storage dtos

This commit is contained in:
Torkel Ödegaard
2016-06-06 10:31:21 +02:00
parent 70cb8400c3
commit a191b9b1cf
19 changed files with 578 additions and 313 deletions
+90
View File
@@ -0,0 +1,90 @@
package tsdb
import "errors"
type Batch struct {
DataSourceId int64
Queries QuerySlice
Depends map[string]bool
Done bool
Started bool
}
type BatchSlice []*Batch
func newBatch(dsId int64, queries QuerySlice) *Batch {
return &Batch{
DataSourceId: dsId,
Queries: queries,
Depends: make(map[string]bool),
}
}
func (bg *Batch) process(context *QueryContext) {
executor := getExecutorFor(bg.Queries[0].DataSource)
if executor == nil {
bg.Done = true
result := &BatchResult{
Error: errors.New("Could not find executor for data source type " + bg.Queries[0].DataSource.Type),
QueryResults: make(map[string]*QueryResult),
}
for _, query := range bg.Queries {
result.QueryResults[query.RefId] = &QueryResult{Error: result.Error}
}
context.ResultsChan <- result
return
}
res := executor.Execute(bg.Queries, context)
bg.Done = true
context.ResultsChan <- res
}
func (bg *Batch) addQuery(query *Query) {
bg.Queries = append(bg.Queries, query)
}
func (bg *Batch) allDependenciesAreIn(context *QueryContext) bool {
for key := range bg.Depends {
if _, exists := context.Results[key]; !exists {
return false
}
}
return true
}
func getBatches(req *Request) (BatchSlice, error) {
batches := make(BatchSlice, 0)
for _, query := range req.Queries {
if foundBatch := findMatchingBatchGroup(query, batches); foundBatch != nil {
foundBatch.addQuery(query)
} else {
newBatch := newBatch(query.DataSource.Id, QuerySlice{query})
batches = append(batches, newBatch)
for _, refId := range query.Depends {
for _, batch := range batches {
for _, batchQuery := range batch.Queries {
if batchQuery.RefId == refId {
newBatch.Depends[refId] = true
}
}
}
}
}
}
return batches, nil
}
func findMatchingBatchGroup(query *Query, batches BatchSlice) *Batch {
for _, batch := range batches {
if batch.DataSourceId == query.DataSource.Id {
return batch
}
}
return nil
}
+24
View File
@@ -0,0 +1,24 @@
package tsdb
type Executor interface {
Execute(queries QuerySlice, context *QueryContext) *BatchResult
}
var registry map[string]GetExecutorFn
type GetExecutorFn func(dsInfo *DataSourceInfo) Executor
func init() {
registry = make(map[string]GetExecutorFn)
}
func getExecutorFor(dsInfo *DataSourceInfo) Executor {
if fn, exists := registry[dsInfo.Type]; exists {
return fn(dsInfo)
}
return nil
}
func RegisterExecutor(dsType string, fn GetExecutorFn) {
registry[dsType] = fn
}
+62
View File
@@ -0,0 +1,62 @@
package tsdb
import "time"
type TimeRange struct {
From time.Time
To time.Time
}
type Request struct {
TimeRange TimeRange
MaxDataPoints int
Queries QuerySlice
}
type Response struct {
BatchTimings []*BatchTiming
Results map[string]*QueryResult
}
type DataSourceInfo struct {
Id int64
Name string
Type string
Url string
Password string
User string
Database string
BasicAuth bool
BasicAuthUser string
BasicAuthPassword string
}
type BatchTiming struct {
TimeElapsed int64
}
type BatchResult struct {
Error error
QueryResults map[string]*QueryResult
Timings *BatchTiming
}
type QueryResult struct {
Error error
RefId string
Series TimeSeriesSlice
}
type TimeSeries struct {
Name string
Points [][2]float64
}
type TimeSeriesSlice []*TimeSeries
func NewTimeSeries(name string, points [][2]float64) *TimeSeries {
return &TimeSeries{
Name: name,
Points: points,
}
}
+12
View File
@@ -0,0 +1,12 @@
package tsdb
type Query struct {
RefId string
Query string
Depends []string
DataSource *DataSourceInfo
Results []*TimeSeries
Exclude bool
}
type QuerySlice []*Query
+21
View File
@@ -0,0 +1,21 @@
package tsdb
import "sync"
type QueryContext struct {
TimeRange TimeRange
Queries QuerySlice
Results map[string]*QueryResult
ResultsChan chan *BatchResult
Lock sync.RWMutex
BatchWaits sync.WaitGroup
}
func NewQueryContext(queries QuerySlice, timeRange TimeRange) *QueryContext {
return &QueryContext{
TimeRange: timeRange,
Queries: queries,
ResultsChan: make(chan *BatchResult),
Results: make(map[string]*QueryResult),
}
}
+51
View File
@@ -0,0 +1,51 @@
package tsdb
func HandleRequest(req *Request) (*Response, error) {
context := NewQueryContext(req.Queries, req.TimeRange)
batches, err := getBatches(req)
if err != nil {
return nil, err
}
currentlyExecuting := 0
for _, batch := range batches {
if len(batch.Depends) == 0 {
currentlyExecuting += 1
batch.Started = true
go batch.process(context)
}
}
response := &Response{}
for currentlyExecuting != 0 {
select {
case batchResult := <-context.ResultsChan:
currentlyExecuting -= 1
response.BatchTimings = append(response.BatchTimings, batchResult.Timings)
for refId, result := range batchResult.QueryResults {
context.Results[refId] = result
}
for _, batch := range batches {
// not interested in started batches
if batch.Started {
continue
}
if batch.allDependenciesAreIn(context) {
currentlyExecuting += 1
batch.Started = true
go batch.process(context)
}
}
}
}
response.Results = context.Results
return response, nil
}