moira

Форк
0
/
timeseries.go 
149 строк · 4.6 Кб
1
package checker
2

3
import (
4
	"fmt"
5
	"math"
6

7
	"go.avito.ru/DO/moira/expression"
8
	"go.avito.ru/DO/moira/target"
9
)
10

11
type triggerTimeSeries struct {
12
	Main       []*target.TimeSeries `json:"main,omitempty"`
13
	Additional []*target.TimeSeries `json:"additional,omitempty"`
14
}
15

16
// ErrWrongTriggerTarget represents inconsistent number of timeseries
17
type ErrWrongTriggerTarget int
18

19
// ErrWrongTriggerTarget implementation for given number of found timeseries
20
func (err ErrWrongTriggerTarget) Error() string {
21
	return fmt.Sprintf("Target t%v has more than one timeseries", int(err))
22
}
23

24
func (triggerChecker *TriggerChecker) getTimeSeries(from, until int64) (*triggerTimeSeries, []string, error) {
25
	triggerTimeSeries := &triggerTimeSeries{
26
		Main:       make([]*target.TimeSeries, 0),
27
		Additional: make([]*target.TimeSeries, 0),
28
	}
29
	metricsArr := make([]string, 0)
30

31
	isSimpleTrigger := triggerChecker.trigger.IsSimple()
32
	for targetIndex, tar := range triggerChecker.trigger.Targets {
33
		result, err := target.EvaluateTarget(triggerChecker.Database, tar, from, until, isSimpleTrigger)
34
		if err != nil {
35
			return nil, nil, err
36
		}
37

38
		if targetIndex == 0 {
39
			triggerTimeSeries.Main = result.TimeSeries
40
		} else {
41
			timeSeriesCount := len(result.TimeSeries)
42
			switch {
43
			case timeSeriesCount == 0:
44
				if len(result.Metrics) == 0 {
45
					triggerTimeSeries.Additional = append(triggerTimeSeries.Additional, nil)
46
				} else {
47
					return nil, nil, fmt.Errorf("Target t%v has no timeseries", targetIndex+1)
48
				}
49
			case timeSeriesCount > 1:
50
				return nil, nil, ErrWrongTriggerTarget(targetIndex + 1)
51
			default:
52
				triggerTimeSeries.Additional = append(triggerTimeSeries.Additional, result.TimeSeries[0])
53
			}
54
		}
55

56
		metricsArr = append(metricsArr, result.Metrics...)
57
	}
58

59
	triggerChecker.cleanupMetrics(metricsArr, triggerChecker.Until)
60
	return triggerTimeSeries, metricsArr, nil
61
}
62

63
func (triggerChecker *TriggerChecker) getRemoteTimeSeries(from, until int64) (*triggerTimeSeries, error) {
64
	triggerTimeSeries := &triggerTimeSeries{
65
		Main:       make([]*target.TimeSeries, 0),
66
		Additional: make([]*target.TimeSeries, 0),
67
	}
68

69
	pullURL := triggerChecker.Config.PullURL
70
	for i, tar := range triggerChecker.trigger.Targets {
71
		timeseries, err := triggerChecker.PullRemote(pullURL, from, until, []string{tar}) // TODO pull all with one query
72
		if err != nil {
73
			return nil, err
74
		}
75
		// t1
76
		if i == 0 {
77
			triggerTimeSeries.Main = timeseries
78
		} else {
79
			switch len(timeseries) {
80
			case 0:
81
				triggerTimeSeries.Additional = append(triggerTimeSeries.Additional, nil)
82
				// TODO check
83
				//if len(timeseries.Metrics) == 0 {
84
				//	triggerTimeSeries.Additional = append(triggerTimeSeries.Additional, nil)
85
				//} else {
86
				//	return nil, fmt.Errorf("target t%v has no timeseries", i+1)
87
				//}
88
			case 1:
89
				triggerTimeSeries.Additional = append(triggerTimeSeries.Additional, timeseries[0])
90
			default:
91
				return nil, ErrWrongTriggerTarget(i + 1)
92
			}
93
		}
94
	}
95
	return triggerTimeSeries, nil
96
}
97

98
func (*triggerTimeSeries) getMainTargetName() string {
99
	return "t1"
100
}
101

102
func (*triggerTimeSeries) getAdditionalTargetName(targetIndex int) string {
103
	return fmt.Sprintf("t%v", targetIndex+2)
104
}
105

106
func (triggerTimeSeries *triggerTimeSeries) getExpressionValues(firstTargetTimeSeries *target.TimeSeries, valueTimestamp int64) (*expression.TriggerExpression, bool) {
107
	expressionValues := &expression.TriggerExpression{
108
		AdditionalTargetsValues: make(map[string]float64, len(triggerTimeSeries.Additional)),
109
	}
110
	firstTargetValue := firstTargetTimeSeries.GetTimestampValue(valueTimestamp)
111
	if IsInvalidValue(firstTargetValue) {
112
		return expressionValues, false
113
	}
114
	expressionValues.MainTargetValue = firstTargetValue
115

116
	for targetNumber := 0; targetNumber < len(triggerTimeSeries.Additional); targetNumber++ {
117
		additionalTimeSeries := triggerTimeSeries.Additional[targetNumber]
118
		if additionalTimeSeries == nil {
119
			return expressionValues, false
120
		}
121
		tnValue := additionalTimeSeries.GetTimestampValue(valueTimestamp)
122
		if IsInvalidValue(tnValue) {
123
			return expressionValues, false
124
		}
125
		expressionValues.AdditionalTargetsValues[triggerTimeSeries.getAdditionalTargetName(targetNumber)] = tnValue
126
	}
127
	return expressionValues, true
128
}
129

130
// IsInvalidValue checks trigger for Inf and NaN. If it is then trigger is not valid
131
func IsInvalidValue(val float64) bool {
132
	if math.IsNaN(val) {
133
		return true
134
	}
135
	if math.IsInf(val, 0) {
136
		return true
137
	}
138
	return false
139
}
140

141
// hasOnlyWildcards checks given targetTimeSeries for only wildcards
142
func (triggerTimeSeries *triggerTimeSeries) hasOnlyWildcards() bool {
143
	for _, timeSeries := range triggerTimeSeries.Main {
144
		if !timeSeries.Wildcard {
145
			return false
146
		}
147
	}
148
	return len(triggerTimeSeries.Main) > 0
149
}
150

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.