...
1
2
3
4
5
6
7
8
9
10
11
12
13
14 package dispatch
15
16 import (
17 "encoding/json"
18 "fmt"
19 "sort"
20 "strings"
21 "time"
22
23 "github.com/prometheus/common/model"
24
25 "github.com/prometheus/alertmanager/config"
26 "github.com/prometheus/alertmanager/pkg/labels"
27 )
28
29
30
31 var DefaultRouteOpts = RouteOpts{
32 GroupWait: 30 * time.Second,
33 GroupInterval: 5 * time.Minute,
34 RepeatInterval: 4 * time.Hour,
35 GroupBy: map[model.LabelName]struct{}{},
36 GroupByAll: false,
37 MuteTimeIntervals: []string{},
38 }
39
40
41 type Route struct {
42 parent *Route
43
44
45 RouteOpts RouteOpts
46
47
48
49 Matchers labels.Matchers
50
51
52 Continue bool
53
54
55 Routes []*Route
56 }
57
58
59 func NewRoute(cr *config.Route, parent *Route) *Route {
60
61 opts := DefaultRouteOpts
62 if parent != nil {
63 opts = parent.RouteOpts
64 }
65
66 if cr.Receiver != "" {
67 opts.Receiver = cr.Receiver
68 }
69
70 if cr.GroupBy != nil {
71 opts.GroupBy = map[model.LabelName]struct{}{}
72 for _, ln := range cr.GroupBy {
73 opts.GroupBy[ln] = struct{}{}
74 }
75 opts.GroupByAll = false
76 } else {
77 if cr.GroupByAll {
78 opts.GroupByAll = cr.GroupByAll
79 }
80 }
81
82 if cr.GroupWait != nil {
83 opts.GroupWait = time.Duration(*cr.GroupWait)
84 }
85 if cr.GroupInterval != nil {
86 opts.GroupInterval = time.Duration(*cr.GroupInterval)
87 }
88 if cr.RepeatInterval != nil {
89 opts.RepeatInterval = time.Duration(*cr.RepeatInterval)
90 }
91
92
93 var matchers labels.Matchers
94
95
96 for ln, lv := range cr.Match {
97 matcher, err := labels.NewMatcher(labels.MatchEqual, ln, lv)
98 if err != nil {
99
100 panic(err)
101 }
102 matchers = append(matchers, matcher)
103 }
104
105
106 for ln, lv := range cr.MatchRE {
107 matcher, err := labels.NewMatcher(labels.MatchRegexp, ln, lv.String())
108 if err != nil {
109
110 panic(err)
111 }
112 matchers = append(matchers, matcher)
113 }
114
115
116 matchers = append(matchers, cr.Matchers...)
117
118 sort.Sort(matchers)
119
120 opts.MuteTimeIntervals = cr.MuteTimeIntervals
121 opts.ActiveTimeIntervals = cr.ActiveTimeIntervals
122
123 route := &Route{
124 parent: parent,
125 RouteOpts: opts,
126 Matchers: matchers,
127 Continue: cr.Continue,
128 }
129
130 route.Routes = NewRoutes(cr.Routes, route)
131
132 return route
133 }
134
135
136 func NewRoutes(croutes []*config.Route, parent *Route) []*Route {
137 res := []*Route{}
138 for _, cr := range croutes {
139 res = append(res, NewRoute(cr, parent))
140 }
141 return res
142 }
143
144
145
146 func (r *Route) Match(lset model.LabelSet) []*Route {
147 if !r.Matchers.Matches(lset) {
148 return nil
149 }
150
151 var all []*Route
152
153 for _, cr := range r.Routes {
154 matches := cr.Match(lset)
155
156 all = append(all, matches...)
157
158 if matches != nil && !cr.Continue {
159 break
160 }
161 }
162
163
164 if len(all) == 0 {
165 all = append(all, r)
166 }
167
168 return all
169 }
170
171
172 func (r *Route) Key() string {
173 b := strings.Builder{}
174
175 if r.parent != nil {
176 b.WriteString(r.parent.Key())
177 b.WriteRune('/')
178 }
179 b.WriteString(r.Matchers.String())
180 return b.String()
181 }
182
183
184 func (r *Route) Walk(visit func(*Route)) {
185 visit(r)
186 for i := range r.Routes {
187 r.Routes[i].Walk(visit)
188 }
189 }
190
191
192
193 type RouteOpts struct {
194
195 Receiver string
196
197
198 GroupBy map[model.LabelName]struct{}
199
200
201 GroupByAll bool
202
203
204
205 GroupWait time.Duration
206 GroupInterval time.Duration
207 RepeatInterval time.Duration
208
209
210 MuteTimeIntervals []string
211
212
213 ActiveTimeIntervals []string
214 }
215
216 func (ro *RouteOpts) String() string {
217 var labels []model.LabelName
218 for ln := range ro.GroupBy {
219 labels = append(labels, ln)
220 }
221 return fmt.Sprintf("<RouteOpts send_to:%q group_by:%q group_by_all:%t timers:%q|%q>",
222 ro.Receiver, labels, ro.GroupByAll, ro.GroupWait, ro.GroupInterval)
223 }
224
225
226 func (ro *RouteOpts) MarshalJSON() ([]byte, error) {
227 v := struct {
228 Receiver string `json:"receiver"`
229 GroupBy model.LabelNames `json:"groupBy"`
230 GroupByAll bool `json:"groupByAll"`
231 GroupWait time.Duration `json:"groupWait"`
232 GroupInterval time.Duration `json:"groupInterval"`
233 RepeatInterval time.Duration `json:"repeatInterval"`
234 }{
235 Receiver: ro.Receiver,
236 GroupByAll: ro.GroupByAll,
237 GroupWait: ro.GroupWait,
238 GroupInterval: ro.GroupInterval,
239 RepeatInterval: ro.RepeatInterval,
240 }
241 for ln := range ro.GroupBy {
242 v.GroupBy = append(v.GroupBy, ln)
243 }
244
245 return json.Marshal(&v)
246 }
247
View as plain text