@@ -2,7 +2,10 @@ package validation
2
2
3
3
import (
4
4
"flag"
5
+ "os"
5
6
"time"
7
+
8
+ "gopkg.in/yaml.v2"
6
9
)
7
10
8
11
// Limits describe all the limits for users; can be used to describe global default
@@ -73,7 +76,184 @@ func (l *Limits) UnmarshalYAML(unmarshal func(interface{}) error) error {
73
76
// We want to set c to the defaults and then overwrite it with the input.
74
77
// To make unmarshal fill the plain data struct rather than calling UnmarshalYAML
75
78
// again, we have to hide it using a type indirection. See prometheus/config.
76
- * l = defaultLimits
79
+
80
+ // During startup we wont have a default value so we don't want to overwrite them
81
+ if defaultLimits != nil {
82
+ * l = * defaultLimits
83
+ }
77
84
type plain Limits
78
85
return unmarshal ((* plain )(l ))
79
86
}
87
+
88
+ // When we load YAML from disk, we want the various per-customer limits
89
+ // to default to any values specified on the command line, not default
90
+ // command line values. This global contains those values. I (Tom) cannot
91
+ // find a nicer way I'm afraid.
92
+ var defaultLimits * Limits
93
+
94
+ // Overrides periodically fetch a set of per-user overrides, and provides convenience
95
+ // functions for fetching the correct value.
96
+ type Overrides struct {
97
+ overridesManager * OverridesManager
98
+ }
99
+
100
+ // NewOverrides makes a new Overrides.
101
+ // We store the supplied limits in a global variable to ensure per-tenant limits
102
+ // are defaulted to those values. As such, the last call to NewOverrides will
103
+ // become the new global defaults.
104
+ func NewOverrides (defaults Limits ) (* Overrides , error ) {
105
+ defaultLimits = & defaults
106
+ overridesManagerConfig := OverridesManagerConfig {
107
+ OverridesReloadPeriod : defaults .PerTenantOverridePeriod ,
108
+ OverridesLoadPath : defaults .PerTenantOverrideConfig ,
109
+ OverridesLoader : loadOverrides ,
110
+ Defaults : & defaults ,
111
+ }
112
+
113
+ overridesManager , err := NewOverridesManager (overridesManagerConfig )
114
+ if err != nil {
115
+ return nil , err
116
+ }
117
+
118
+ return & Overrides {
119
+ overridesManager : overridesManager ,
120
+ }, nil
121
+ }
122
+
123
+ // Stop background reloading of overrides.
124
+ func (o * Overrides ) Stop () {
125
+ o .overridesManager .Stop ()
126
+ }
127
+
128
+ // IngestionRate returns the limit on ingester rate (samples per second).
129
+ func (o * Overrides ) IngestionRate (userID string ) float64 {
130
+ return o .overridesManager .GetLimits (userID ).(* Limits ).IngestionRate
131
+ }
132
+
133
+ // IngestionBurstSize returns the burst size for ingestion rate.
134
+ func (o * Overrides ) IngestionBurstSize (userID string ) int {
135
+ return o .overridesManager .GetLimits (userID ).(* Limits ).IngestionBurstSize
136
+ }
137
+
138
+ // AcceptHASamples returns whether the distributor should track and accept samples from HA replicas for this user.
139
+ func (o * Overrides ) AcceptHASamples (userID string ) bool {
140
+ return o .overridesManager .GetLimits (userID ).(* Limits ).AcceptHASamples
141
+ }
142
+
143
+ // HAReplicaLabel returns the replica label to look for when deciding whether to accept a sample from a Prometheus HA replica.
144
+ func (o * Overrides ) HAReplicaLabel (userID string ) string {
145
+ return o .overridesManager .GetLimits (userID ).(* Limits ).HAReplicaLabel
146
+ }
147
+
148
+ // HAClusterLabel returns the cluster label to look for when deciding whether to accept a sample from a Prometheus HA replica.
149
+ func (o * Overrides ) HAClusterLabel (userID string ) string {
150
+ return o .overridesManager .GetLimits (userID ).(* Limits ).HAClusterLabel
151
+ }
152
+
153
+ // MaxLabelNameLength returns maximum length a label name can be.
154
+ func (o * Overrides ) MaxLabelNameLength (userID string ) int {
155
+ return o .overridesManager .GetLimits (userID ).(* Limits ).MaxLabelNameLength
156
+ }
157
+
158
+ // MaxLabelValueLength returns maximum length a label value can be. This also is
159
+ // the maximum length of a metric name.
160
+ func (o * Overrides ) MaxLabelValueLength (userID string ) int {
161
+ return o .overridesManager .GetLimits (userID ).(* Limits ).MaxLabelValueLength
162
+ }
163
+
164
+ // MaxLabelNamesPerSeries returns maximum number of label/value pairs timeseries.
165
+ func (o * Overrides ) MaxLabelNamesPerSeries (userID string ) int {
166
+ return o .overridesManager .GetLimits (userID ).(* Limits ).MaxLabelNamesPerSeries
167
+ }
168
+
169
+ // RejectOldSamples returns true when we should reject samples older than certain
170
+ // age.
171
+ func (o * Overrides ) RejectOldSamples (userID string ) bool {
172
+ return o .overridesManager .GetLimits (userID ).(* Limits ).RejectOldSamples
173
+ }
174
+
175
+ // RejectOldSamplesMaxAge returns the age at which samples should be rejected.
176
+ func (o * Overrides ) RejectOldSamplesMaxAge (userID string ) time.Duration {
177
+ return o .overridesManager .GetLimits (userID ).(* Limits ).RejectOldSamplesMaxAge
178
+ }
179
+
180
+ // CreationGracePeriod is misnamed, and actually returns how far into the future
181
+ // we should accept samples.
182
+ func (o * Overrides ) CreationGracePeriod (userID string ) time.Duration {
183
+ return o .overridesManager .GetLimits (userID ).(* Limits ).CreationGracePeriod
184
+ }
185
+
186
+ // MaxSeriesPerQuery returns the maximum number of series a query is allowed to hit.
187
+ func (o * Overrides ) MaxSeriesPerQuery (userID string ) int {
188
+ return o .overridesManager .GetLimits (userID ).(* Limits ).MaxSeriesPerQuery
189
+ }
190
+
191
+ // MaxSamplesPerQuery returns the maximum number of samples in a query (from the ingester).
192
+ func (o * Overrides ) MaxSamplesPerQuery (userID string ) int {
193
+ return o .overridesManager .GetLimits (userID ).(* Limits ).MaxSamplesPerQuery
194
+ }
195
+
196
+ // MaxSeriesPerUser returns the maximum number of series a user is allowed to store.
197
+ func (o * Overrides ) MaxSeriesPerUser (userID string ) int {
198
+ return o .overridesManager .GetLimits (userID ).(* Limits ).MaxSeriesPerUser
199
+ }
200
+
201
+ // MaxSeriesPerMetric returns the maximum number of series allowed per metric.
202
+ func (o * Overrides ) MaxSeriesPerMetric (userID string ) int {
203
+ return o .overridesManager .GetLimits (userID ).(* Limits ).MaxSeriesPerMetric
204
+ }
205
+
206
+ // MaxChunksPerQuery returns the maximum number of chunks allowed per query.
207
+ func (o * Overrides ) MaxChunksPerQuery (userID string ) int {
208
+ return o .overridesManager .GetLimits (userID ).(* Limits ).MaxChunksPerQuery
209
+ }
210
+
211
+ // MaxQueryLength returns the limit of the length (in time) of a query.
212
+ func (o * Overrides ) MaxQueryLength (userID string ) time.Duration {
213
+ return o .overridesManager .GetLimits (userID ).(* Limits ).MaxQueryLength
214
+ }
215
+
216
+ // MaxQueryParallelism returns the limit to the number of sub-queries the
217
+ // frontend will process in parallel.
218
+ func (o * Overrides ) MaxQueryParallelism (userID string ) int {
219
+ return o .overridesManager .GetLimits (userID ).(* Limits ).MaxQueryParallelism
220
+ }
221
+
222
+ // EnforceMetricName whether to enforce the presence of a metric name.
223
+ func (o * Overrides ) EnforceMetricName (userID string ) bool {
224
+ return o .overridesManager .GetLimits (userID ).(* Limits ).EnforceMetricName
225
+ }
226
+
227
+ // CardinalityLimit whether to enforce the presence of a metric name.
228
+ func (o * Overrides ) CardinalityLimit (userID string ) int {
229
+ return o .overridesManager .GetLimits (userID ).(* Limits ).CardinalityLimit
230
+ }
231
+
232
+ // Loads overrides and returns the limits as an interface to store them in OverridesManager.
233
+ // We need to implement it here since OverridesManager must store type Limits in an interface but
234
+ // it doesn't know its definition to initialize it.
235
+ // We could have used yamlv3.Node for this but there is no way to enforce strict decoding due to a bug in it
236
+ // TODO: Use yamlv3.Node to move this to OverridesManager after https://github.com/go-yaml/yaml/issues/460 is fixed
237
+ func loadOverrides (filename string ) (map [string ]interface {}, error ) {
238
+ f , err := os .Open (filename )
239
+ if err != nil {
240
+ return nil , err
241
+ }
242
+
243
+ var overrides struct {
244
+ Overrides map [string ]* Limits `yaml:"overrides"`
245
+ }
246
+
247
+ decoder := yaml .NewDecoder (f )
248
+ decoder .SetStrict (true )
249
+ if err := decoder .Decode (& overrides ); err != nil {
250
+ return nil , err
251
+ }
252
+
253
+ overridesAsInterface := map [string ]interface {}{}
254
+ for userID := range overrides .Overrides {
255
+ overridesAsInterface [userID ] = overrides .Overrides [userID ]
256
+ }
257
+
258
+ return overridesAsInterface , nil
259
+ }
0 commit comments