cloudflare/pint

Public

mirrored from https://github.com/cloudflare/pintAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
v0.33.0

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

internal/promapi/failover.go

175lines · modecode

1package promapi
2
3import (
4 "context"
5 "time"
6
7 "github.com/prometheus/client_golang/prometheus"
8)
9
10type FailoverGroupError struct {
11 err error
12 uri string
13 isStrict bool
14}
15
16func (e *FailoverGroupError) Unwrap() error {
17 return e.err
18}
19
20func (e *FailoverGroupError) Error() string {
21 return e.err.Error()
22}
23
24func (e *FailoverGroupError) URI() string {
25 return e.uri
26}
27
28func (e *FailoverGroupError) IsStrict() bool {
29 return e.isStrict
30}
31
32func cacheCleaner(cache *queryCache, interval time.Duration, quit chan bool) {
33 ticker := time.NewTicker(interval)
34 for {
35 select {
36 case <-quit:
37 return
38 case <-ticker.C:
39 cache.gc()
40 }
41 }
42}
43
44type FailoverGroup struct {
45 name string
46 servers []*Prometheus
47 cacheSize int
48 strictErrors bool
49 uptimeMetric string
50 cacheCollector *cacheCollector
51 quitChan chan bool
52}
53
54func NewFailoverGroup(name string, servers []*Prometheus, cacheSize int, strictErrors bool, uptimeMetric string) *FailoverGroup {
55 return &FailoverGroup{
56 name: name,
57 servers: servers,
58 cacheSize: cacheSize,
59 strictErrors: strictErrors,
60 uptimeMetric: uptimeMetric,
61 }
62}
63
64func (fg *FailoverGroup) Name() string {
65 return fg.name
66}
67
68func (fg *FailoverGroup) UptimeMetric() string {
69 return fg.uptimeMetric
70}
71
72func (fg *FailoverGroup) StartWorkers() {
73 queryCache := newQueryCache(fg.cacheSize, time.Hour, 0.333)
74 fg.quitChan = make(chan bool)
75 go cacheCleaner(queryCache, time.Minute*2, fg.quitChan)
76
77 fg.cacheCollector = newCacheCollector(queryCache, fg.name)
78 prometheus.MustRegister(fg.cacheCollector)
79 for _, prom := range fg.servers {
80 prom.cache = queryCache
81 prom.StartWorkers()
82 }
83}
84
85func (fg *FailoverGroup) Close() {
86 for _, prom := range fg.servers {
87 prom.Close()
88 }
89 prometheus.Unregister(fg.cacheCollector)
90 fg.quitChan <- true
91}
92
93func (fg *FailoverGroup) CleanCache() {
94 for _, prom := range fg.servers {
95 if prom.cache != nil {
96 prom.cache.gc()
97 return
98 }
99 }
100}
101
102func (fg *FailoverGroup) Config(ctx context.Context) (cfg *ConfigResult, err error) {
103 var uri string
104 for _, prom := range fg.servers {
105 uri = prom.safeURI
106 cfg, err = prom.Config(ctx)
107 if err == nil {
108 return
109 }
110 if !IsUnavailableError(err) {
111 return nil, &FailoverGroupError{err: err, uri: uri, isStrict: fg.strictErrors}
112 }
113 }
114 return nil, &FailoverGroupError{err: err, uri: uri, isStrict: fg.strictErrors}
115}
116
117func (fg *FailoverGroup) Query(ctx context.Context, expr string) (qr *QueryResult, err error) {
118 var uri string
119 for _, prom := range fg.servers {
120 uri = prom.safeURI
121 qr, err = prom.Query(ctx, expr)
122 if err == nil {
123 return
124 }
125 if !IsUnavailableError(err) {
126 return qr, &FailoverGroupError{err: err, uri: uri, isStrict: fg.strictErrors}
127 }
128 }
129 return nil, &FailoverGroupError{err: err, uri: uri, isStrict: fg.strictErrors}
130}
131
132func (fg *FailoverGroup) RangeQuery(ctx context.Context, expr string, params RangeQueryTimes) (rqr *RangeQueryResult, err error) {
133 var uri string
134 for _, prom := range fg.servers {
135 uri = prom.safeURI
136 rqr, err = prom.RangeQuery(ctx, expr, params)
137 if err == nil {
138 return
139 }
140 if !IsUnavailableError(err) {
141 return rqr, &FailoverGroupError{err: err, uri: uri, isStrict: fg.strictErrors}
142 }
143 }
144 return nil, &FailoverGroupError{err: err, uri: uri, isStrict: fg.strictErrors}
145}
146
147func (fg *FailoverGroup) Metadata(ctx context.Context, metric string) (metadata *MetadataResult, err error) {
148 var uri string
149 for _, prom := range fg.servers {
150 uri = prom.safeURI
151 metadata, err = prom.Metadata(ctx, metric)
152 if err == nil {
153 return
154 }
155 if !IsUnavailableError(err) {
156 return metadata, &FailoverGroupError{err: err, uri: uri, isStrict: fg.strictErrors}
157 }
158 }
159 return nil, &FailoverGroupError{err: err, uri: uri, isStrict: fg.strictErrors}
160}
161
162func (fg *FailoverGroup) Flags(ctx context.Context) (flags *FlagsResult, err error) {
163 var uri string
164 for _, prom := range fg.servers {
165 uri = prom.safeURI
166 flags, err = prom.Flags(ctx)
167 if err == nil {
168 return
169 }
170 if !IsUnavailableError(err) {
171 return nil, &FailoverGroupError{err: err, uri: uri, isStrict: fg.strictErrors}
172 }
173 }
174 return nil, &FailoverGroupError{err: err, uri: uri, isStrict: fg.strictErrors}
175}
176