@@ -21,11 +21,9 @@ func rejectQueryOrSetPriority(r *http.Request, now time.Time, lookbackDelta time
21
21
if limits == nil || ! (limits .QueryPriority (userStr ).Enabled || limits .QueryRejection (userStr ).Enabled ) {
22
22
return nil
23
23
}
24
+ op := getOperation (r )
24
25
25
- isExpressionQuery := strings .HasSuffix (r .URL .Path , "/query" ) || strings .HasSuffix (r .URL .Path , "/query_range" )
26
- isMetadataQuery := strings .HasSuffix (r .URL .Path , "/series" ) || strings .HasSuffix (r .URL .Path , "/labels" ) || strings .HasSuffix (r .URL .Path , "/values" )
27
-
28
- if isExpressionQuery {
26
+ if op == "query" || op == "query_range" {
29
27
query := r .FormValue ("query" )
30
28
expr , err := parser .ParseExpr (query )
31
29
if err != nil {
@@ -36,7 +34,7 @@ func rejectQueryOrSetPriority(r *http.Request, now time.Time, lookbackDelta time
36
34
if queryReject := limits .QueryRejection (userStr ); queryReject .Enabled && query != "" {
37
35
for _ , attribute := range queryReject .QueryAttributes {
38
36
if matchAttributeForExpressionQuery (attribute , r , query , expr , now , minTime , maxTime ) {
39
- rejectedQueriesPerTenant .WithLabelValues (userStr ).Inc ()
37
+ rejectedQueriesPerTenant .WithLabelValues (op , userStr ).Inc ()
40
38
return httpgrpc .Errorf (http .StatusUnprocessableEntity , queryRejectErrorMessage )
41
39
}
42
40
}
@@ -59,11 +57,10 @@ func rejectQueryOrSetPriority(r *http.Request, now time.Time, lookbackDelta time
59
57
}
60
58
}
61
59
62
- if queryReject := limits .QueryRejection (userStr ); queryReject .Enabled && isMetadataQuery {
60
+ if queryReject := limits .QueryRejection (userStr ); queryReject .Enabled && ( op == "series" || op == "labels" || op == "label_values" ) {
63
61
for _ , attribute := range queryReject .QueryAttributes {
64
-
65
62
if matchAttributeForMetadataQuery (attribute , r , now ) {
66
- rejectedQueriesPerTenant .WithLabelValues (userStr ).Inc ()
63
+ rejectedQueriesPerTenant .WithLabelValues (op , userStr ).Inc ()
67
64
return httpgrpc .Errorf (http .StatusUnprocessableEntity , queryRejectErrorMessage )
68
65
}
69
66
}
@@ -72,6 +69,23 @@ func rejectQueryOrSetPriority(r *http.Request, now time.Time, lookbackDelta time
72
69
return nil
73
70
}
74
71
72
+ func getOperation (r * http.Request ) string {
73
+ switch {
74
+ case strings .HasSuffix (r .URL .Path , "/query" ):
75
+ return "query"
76
+ case strings .HasSuffix (r .URL .Path , "/query_range" ):
77
+ return "query_range"
78
+ case strings .HasSuffix (r .URL .Path , "/series" ):
79
+ return "series"
80
+ case strings .HasSuffix (r .URL .Path , "/labels" ):
81
+ return "labels"
82
+ case strings .HasSuffix (r .URL .Path , "/values" ):
83
+ return "label_values"
84
+ default :
85
+ return "other"
86
+ }
87
+ }
88
+
75
89
func matchAttributeForExpressionQuery (attribute validation.QueryAttribute , r * http.Request , query string , expr parser.Expr , now time.Time , minTime , maxTime int64 ) bool {
76
90
if attribute .Regex != "" && attribute .Regex != ".*" && attribute .Regex != ".+" {
77
91
if attribute .CompiledRegex != nil && ! attribute .CompiledRegex .MatchString (query ) {
@@ -83,16 +97,18 @@ func matchAttributeForExpressionQuery(attribute validation.QueryAttribute, r *ht
83
97
return false
84
98
}
85
99
86
- if ! isWithinTimeRangeAttribute (attribute .TimeRangeLimit , maxTime - minTime ) {
100
+ if ! isWithinTimeRangeAttribute (attribute .TimeRangeLimit , minTime , maxTime ) {
87
101
return false
88
102
}
89
103
90
104
if ! isWithinQueryStepLimit (attribute .QueryStepLimit , r , expr ) {
91
105
return false
92
106
}
93
107
94
- if attribute .UserAgent != "" && attribute .UserAgent != r .Header .Get ("User-Agent" ) {
95
- return false
108
+ if attribute .UserAgentRegex != "" && attribute .UserAgentRegex != ".*" && attribute .CompiledUserAgentRegex != nil {
109
+ if ! attribute .CompiledUserAgentRegex .MatchString (r .Header .Get ("User-Agent" )) {
110
+ return false
111
+ }
96
112
}
97
113
98
114
if attribute .DashboardUID != "" && attribute .DashboardUID != r .Header .Get ("X-Dashboard-Uid" ) {
@@ -107,13 +123,13 @@ func matchAttributeForExpressionQuery(attribute validation.QueryAttribute, r *ht
107
123
}
108
124
109
125
func matchAttributeForMetadataQuery (attribute validation.QueryAttribute , r * http.Request , now time.Time ) bool {
110
- if attribute .Regex != "" && attribute .Regex != ".*" && attribute .Regex != ".+" && attribute . CompiledRegex != nil {
126
+ if attribute .Regex != "" && attribute .Regex != ".*" && attribute .CompiledRegex != nil {
111
127
for _ , matcher := range r .Form ["match[]" ] {
112
128
if attribute .CompiledRegex .MatchString (matcher ) {
113
- continue
129
+ break
114
130
}
115
- return false
116
131
}
132
+ return false
117
133
}
118
134
119
135
startTime , _ := util .ParseTime (r .FormValue ("start" ))
@@ -123,20 +139,14 @@ func matchAttributeForMetadataQuery(attribute validation.QueryAttribute, r *http
123
139
return false
124
140
}
125
141
126
- if startTime != 0 && endTime != 0 && ! isWithinTimeRangeAttribute (attribute .TimeRangeLimit , endTime - startTime ) {
127
- return false
128
- }
129
-
130
- if attribute .UserAgent != "" && attribute .UserAgent != r .Header .Get ("User-Agent" ) {
142
+ if ! isWithinTimeRangeAttribute (attribute .TimeRangeLimit , startTime , endTime ) {
131
143
return false
132
144
}
133
145
134
- if attribute .DashboardUID != "" && attribute .DashboardUID != r .Header .Get ("X-Dashboard-Uid" ) {
135
- return false
136
- }
137
-
138
- if attribute .PanelID != "" && attribute .PanelID != r .Header .Get ("X-Panel-Id" ) {
139
- return false
146
+ if attribute .UserAgentRegex != "" && attribute .UserAgentRegex != ".*" && attribute .CompiledUserAgentRegex != nil {
147
+ if ! attribute .CompiledUserAgentRegex .MatchString (r .Header .Get ("User-Agent" )) {
148
+ return false
149
+ }
140
150
}
141
151
142
152
return true
@@ -164,11 +174,17 @@ func isWithinTimeAttributes(timeWindow validation.TimeWindow, now time.Time, sta
164
174
return true
165
175
}
166
176
167
- func isWithinTimeRangeAttribute (limit validation.TimeRangeLimit , timeRangeInMillis int64 ) bool {
177
+ func isWithinTimeRangeAttribute (limit validation.TimeRangeLimit , startTime , endTime int64 ) bool {
168
178
if limit .Min == 0 && limit .Max == 0 {
169
179
return true
170
180
}
171
181
182
+ if startTime == 0 || endTime == 0 {
183
+ return false
184
+ }
185
+
186
+ timeRangeInMillis := endTime - startTime
187
+
172
188
if limit .Min != 0 && time .Duration (limit .Min ).Milliseconds () > timeRangeInMillis {
173
189
return false
174
190
}
0 commit comments