Skip to content

Commit 2649050

Browse files
[8.9] Enable all remaining metric aggregations on counters (#97974) (#98294)
* Enable all remaining metric aggregations on counters (#97974) Here we enable aggregations previously not allowed on fields of type counter. The decision of enabling such aggregations even if the result is "meaningless" for counters has been taken to favour TSDB adoption. Aggregations now allowed, other than the existing ones, include: * avg * box plot * cardinality * extended stats * median absolute deviation * percentile ranks * percentiles * stats * sum * value count I included tests for the weighted average and matrix stats aggregations too. Resolves #97882 (cherry picked from commit d0b2f65) # Conflicts: # rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/tsdb/120_counter_fields.yml * fix: skip versions up to and including 8.9.0
1 parent 236f55a commit 2649050

File tree

14 files changed

+496
-39
lines changed

14 files changed

+496
-39
lines changed

docs/reference/data-streams/tsds.asciidoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ of aggregations (for example `sum`) compute results that don't make sense for a
155155
+
156156
Only numeric and `aggregate_metric_double` fields support the `counter` metric type.
157157
158-
NOTE: Due to the cumulative nature of counter fields, only the following aggregations are allowed with the `counter` field: `rate`, `histogram`, `range`, `min`, `max`, `top_metrics` and `variable_width_histogram`.
158+
NOTE: Due to the cumulative nature of counter fields, the following aggregations are supported and expected to provide meaningful results with the `counter` field: `rate`, `histogram`, `range`, `min`, `max`, `top_metrics` and `variable_width_histogram`. In order to prevent issues with existing integrations and custom dashboards, we also allow the following aggregations, even if the result might be meaningless on counters: `avg`, `box plot`, `cardinality`, `extended stats`, `median absolute deviation`, `percentile ranks`, `percentiles`, `stats`, `sum` and `value count`.
159159
160160
// tag::time-series-metric-gauge[]
161161
`gauge`:: A metric that represents a single numeric that can arbitrarily increase or decrease. For example, a temperature or
Lines changed: 299 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,324 @@
11
---
2-
"avg aggregation on counter field":
2+
setup:
33
- skip:
4-
version: " - 8.6.99"
5-
reason: "counter field support added in 8.7"
4+
version: " - 8.9.0"
5+
reason: "additional counter field aggregations back-ported from 8.10 to 8.9.1"
6+
features: close_to
67

78
- do:
89
indices.create:
9-
index: myindex1
10-
body:
11-
mappings:
12-
properties:
13-
counter_field:
14-
type : long
15-
time_series_metric: counter
16-
- do:
17-
indices.create:
18-
index: myindex2
10+
index: test_counter
1911
body:
2012
settings:
2113
index:
2214
mode: time_series
23-
routing_path: [ keyword_field ]
15+
routing_path: [ key ]
2416
time_series:
25-
start_time: 2023-01-01T00:00:00Z
26-
end_time: 2024-01-01T00:00:00Z
17+
start_time: 2021-01-01T00:00:00Z
18+
end_time: 2021-01-31T00:00:00Z
19+
number_of_shards: 1
2720
mappings:
2821
properties:
29-
keyword_field:
22+
"@timestamp":
23+
type: date
24+
key:
3025
type: keyword
3126
time_series_dimension: true
32-
counter_field:
33-
type : long
27+
counter:
28+
type: long
3429
time_series_metric: counter
30+
weight:
31+
type: integer
32+
33+
- do:
34+
bulk:
35+
index: test_counter
36+
refresh: true
37+
body:
38+
- '{ "index": {} }'
39+
- '{ "@timestamp": "2021-01-01T00:01:00Z", "key": "bar", "counter": 10, "weight": 2 }'
40+
- '{ "index": {} }'
41+
- '{ "@timestamp": "2021-01-01T00:02:00Z", "key": "bar", "counter": 20, "weight": 1 }'
42+
- '{ "index": {} }'
43+
- '{ "@timestamp": "2021-01-01T00:03:00Z", "key": "bar", "counter": 22, "weight": 2 }'
44+
- '{ "index": {} }'
45+
- '{ "@timestamp": "2021-01-01T00:04:00Z", "key": "bar", "counter": 28, "weight": 1 }'
46+
47+
---
48+
"avg":
3549
- do:
3650
search:
37-
index: myindex1
51+
index: test_counter
3852
body:
3953
aggs:
40-
the_counter_avg:
54+
counter_avg:
4155
avg:
42-
field: counter_field
43-
- match: { aggregations.the_counter_avg.value: null }
56+
field: counter
57+
58+
- match: { hits.total.value: 4 }
59+
- length: { hits.hits: 4 }
60+
- close_to: { aggregations.counter_avg.value: { value: 20.00, error: 0.01 } }
4461

62+
---
63+
"cardinality":
4564
- do:
46-
catch: /Field \[counter_field\] of type \[long\] is not supported for aggregation \[avg\]/
4765
search:
48-
index: myindex2
66+
index: test_counter
4967
body:
5068
aggs:
51-
the_counter_avg:
52-
avg:
53-
field: counter_field
69+
counter_cardinality:
70+
cardinality:
71+
field: counter
72+
73+
- match: { hits.total.value: 4 }
74+
- length: { hits.hits: 4 }
75+
- match: { aggregations.counter_cardinality.value: 4 }
76+
77+
---
78+
"extended stats":
79+
- do:
80+
search:
81+
index: test_counter
82+
body:
83+
aggs:
84+
counter_extended_stats:
85+
extended_stats:
86+
field: counter
87+
88+
- match: { hits.total.value: 4 }
89+
- length: { hits.hits: 4 }
90+
- match: { aggregations.counter_extended_stats.count: 4 }
91+
- close_to: { aggregations.counter_extended_stats.min: { value: 10.00, error: 0.01 } }
92+
- close_to: { aggregations.counter_extended_stats.max: { value: 28.00, error: 0.01 } }
93+
- close_to: { aggregations.counter_extended_stats.avg: { value: 20.00, error: 0.01 } }
94+
- close_to: { aggregations.counter_extended_stats.sum: { value: 80.00, error: 0.01 } }
95+
- close_to: { aggregations.counter_extended_stats.sum_of_squares: { value: 1768.00, error: 0.01 } }
96+
- close_to: { aggregations.counter_extended_stats.std_deviation: { value: 6.48, error: 0.01 } }
97+
- close_to: { aggregations.counter_extended_stats.std_deviation_bounds.upper: { value: 32.96, error: 0.01 } }
98+
- close_to: { aggregations.counter_extended_stats.std_deviation_bounds.lower: { value: 7.03, error: 0.01 } }
99+
100+
---
101+
"median absolute deviation":
102+
- do:
103+
search:
104+
index: test_counter
105+
body:
106+
aggs:
107+
mad_counter:
108+
median_absolute_deviation:
109+
field: counter
110+
111+
- match: { hits.total.value: 4 }
112+
- length: { hits.hits: 4 }
113+
- close_to: { aggregations.mad_counter.value: { value: 4.00, error: 0.01 } }
114+
115+
---
116+
"percentile ranks hdr":
117+
- do:
118+
search:
119+
index: test_counter
120+
body:
121+
aggs:
122+
counter_percentile_ranks:
123+
percentile_ranks:
124+
field: counter
125+
values: [50, 90]
126+
keyed: false
127+
hdr:
128+
number_of_significant_value_digits: 2
129+
130+
- match: { hits.total.value: 4 }
131+
- length: { hits.hits: 4 }
132+
- close_to: { aggregations.counter_percentile_ranks.values.0.value: { value: 100.00, error: 0.01 } }
133+
- close_to: { aggregations.counter_percentile_ranks.values.1.value: { value: 100.00, error: 0.01 } }
134+
135+
---
136+
"percentile ranks tdigest":
137+
- do:
138+
search:
139+
index: test_counter
140+
body:
141+
aggs:
142+
counter_percentiles:
143+
percentiles:
144+
field: counter
145+
keyed: false
146+
147+
- match: { hits.total.value: 4 }
148+
- length: { hits.hits: 4 }
149+
- close_to: { aggregations.counter_percentiles.values.0.value: { value: 10.30, error: 0.01 } }
150+
- close_to: { aggregations.counter_percentiles.values.1.value: { value: 11.50, error: 0.01 } }
151+
- close_to: { aggregations.counter_percentiles.values.2.value: { value: 17.50, error: 0.01 } }
152+
- close_to: { aggregations.counter_percentiles.values.3.value: { value: 21.00, error: 0.01 } }
153+
- close_to: { aggregations.counter_percentiles.values.4.value: { value: 23.50, error: 0.01 } }
154+
- close_to: { aggregations.counter_percentiles.values.5.value: { value: 27.10, error: 0.01 } }
155+
- close_to: { aggregations.counter_percentiles.values.6.value: { value: 27.82, error: 0.01 } }
156+
157+
---
158+
"percentiles hdr":
159+
- do:
160+
search:
161+
index: test_counter
162+
body:
163+
aggs:
164+
counter_percentiles:
165+
percentiles:
166+
field: counter
167+
keyed: false
168+
hdr:
169+
number_of_significant_value_digits: 2
170+
171+
- match: { hits.total.value: 4 }
172+
- length: { hits.hits: 4 }
173+
- close_to: { aggregations.counter_percentiles.values.0.value: { value: 10.00, error: 0.01 } }
174+
- close_to: { aggregations.counter_percentiles.values.1.value: { value: 10.00, error: 0.01 } }
175+
- close_to: { aggregations.counter_percentiles.values.2.value: { value: 10.00, error: 0.01 } }
176+
- close_to: { aggregations.counter_percentiles.values.3.value: { value: 20.06, error: 0.01 } }
177+
- close_to: { aggregations.counter_percentiles.values.4.value: { value: 22.06, error: 0.01 } }
178+
- close_to: { aggregations.counter_percentiles.values.5.value: { value: 28.06, error: 0.01 } }
179+
- close_to: { aggregations.counter_percentiles.values.6.value: { value: 28.06, error: 0.01 } }
180+
181+
---
182+
"percentiles tdigest":
183+
- do:
184+
bulk:
185+
index: test_counter
186+
refresh: true
187+
body:
188+
- '{ "index": {} }'
189+
- '{ "@timestamp": "2021-01-01T00:01:00Z", "key": "bar", "counter": 10 }'
190+
- '{ "index": {} }'
191+
- '{ "@timestamp": "2021-01-01T00:02:00Z", "key": "bar", "counter": 20 }'
192+
- '{ "index": {} }'
193+
- '{ "@timestamp": "2021-01-01T00:03:00Z", "key": "bar", "counter": 22 }'
194+
- '{ "index": {} }'
195+
- '{ "@timestamp": "2021-01-01T00:04:00Z", "key": "bar", "counter": 28 }'
196+
197+
- do:
198+
search:
199+
index: test_counter
200+
body:
201+
aggs:
202+
counter_percentiles:
203+
percentiles:
204+
field: counter
205+
keyed: false
206+
207+
- match: { hits.total.value: 4 }
208+
- length: { hits.hits: 4 }
209+
- close_to: { aggregations.counter_percentiles.values.0.value: { value: 10.30, error: 0.01 } }
210+
- close_to: { aggregations.counter_percentiles.values.1.value: { value: 11.50, error: 0.01 } }
211+
- close_to: { aggregations.counter_percentiles.values.2.value: { value: 17.50, error: 0.01 } }
212+
- close_to: { aggregations.counter_percentiles.values.3.value: { value: 21.00, error: 0.01 } }
213+
- close_to: { aggregations.counter_percentiles.values.4.value: { value: 23.50, error: 0.01 } }
214+
- close_to: { aggregations.counter_percentiles.values.5.value: { value: 27.10, error: 0.01 } }
215+
- close_to: { aggregations.counter_percentiles.values.6.value: { value: 27.82, error: 0.01 } }
216+
217+
---
218+
"stats":
219+
- do:
220+
bulk:
221+
index: test_counter
222+
refresh: true
223+
body:
224+
- '{ "index": {} }'
225+
- '{ "@timestamp": "2021-01-01T00:01:00Z", "key": "bar", "counter": 10 }'
226+
- '{ "index": {} }'
227+
- '{ "@timestamp": "2021-01-01T00:02:00Z", "key": "bar", "counter": 20 }'
228+
- '{ "index": {} }'
229+
- '{ "@timestamp": "2021-01-01T00:03:00Z", "key": "bar", "counter": 22 }'
230+
- '{ "index": {} }'
231+
- '{ "@timestamp": "2021-01-01T00:04:00Z", "key": "bar", "counter": 28 }'
232+
233+
- do:
234+
search:
235+
index: test_counter
236+
body:
237+
aggs:
238+
counter_extended_stats:
239+
stats:
240+
field: counter
241+
242+
- match: { hits.total.value: 4 }
243+
- length: { hits.hits: 4 }
244+
- match: { aggregations.counter_extended_stats.count: 4 }
245+
- close_to: { aggregations.counter_extended_stats.min: { value: 10.00, error: 0.01 } }
246+
- close_to: { aggregations.counter_extended_stats.max: { value: 28.00, error: 0.01 } }
247+
- close_to: { aggregations.counter_extended_stats.avg: { value: 20.00, error: 0.01 } }
248+
- close_to: { aggregations.counter_extended_stats.sum: { value: 80.00, error: 0.01 } }
249+
250+
---
251+
"sum":
252+
- do:
253+
bulk:
254+
index: test_counter
255+
refresh: true
256+
body:
257+
- '{ "index": {} }'
258+
- '{ "@timestamp": "2021-01-01T00:01:00Z", "key": "bar", "counter": 10 }'
259+
- '{ "index": {} }'
260+
- '{ "@timestamp": "2021-01-01T00:02:00Z", "key": "bar", "counter": 20 }'
261+
- '{ "index": {} }'
262+
- '{ "@timestamp": "2021-01-01T00:03:00Z", "key": "bar", "counter": 22 }'
263+
- '{ "index": {} }'
264+
- '{ "@timestamp": "2021-01-01T00:04:00Z", "key": "bar", "counter": 28 }'
265+
266+
- do:
267+
search:
268+
index: test_counter
269+
body:
270+
aggs:
271+
counter_sum:
272+
sum:
273+
field: counter
274+
275+
- match: { hits.total.value: 4 }
276+
- length: { hits.hits: 4 }
277+
- close_to: { aggregations.counter_sum.value: { value: 80.00, error: 0.01 } }
278+
279+
---
280+
"value count":
281+
- do:
282+
bulk:
283+
index: test_counter
284+
refresh: true
285+
body:
286+
- '{ "index": {} }'
287+
- '{ "@timestamp": "2021-01-01T00:01:00Z", "key": "bar", "counter": 10 }'
288+
- '{ "index": {} }'
289+
- '{ "@timestamp": "2021-01-01T00:02:00Z", "key": "bar", "counter": 20 }'
290+
- '{ "index": {} }'
291+
- '{ "@timestamp": "2021-01-01T00:03:00Z", "key": "bar", "counter": 22 }'
292+
- '{ "index": {} }'
293+
- '{ "@timestamp": "2021-01-01T00:04:00Z", "key": "bar", "counter": 28 }'
294+
295+
- do:
296+
search:
297+
index: test_counter
298+
body:
299+
aggs:
300+
counter_value_count:
301+
value_count:
302+
field: counter
303+
304+
- match: { hits.total.value: 4 }
305+
- length: { hits.hits: 4 }
306+
- match: { aggregations.counter_value_count.value: 4 }
307+
308+
---
309+
"weighted avg":
310+
- do:
311+
search:
312+
index: test_counter
313+
body:
314+
aggs:
315+
counter_weighted_avg:
316+
weighted_avg:
317+
value:
318+
field: counter
319+
weight:
320+
field: weight
321+
322+
- match: { hits.total.value: 4 }
323+
- length: { hits.hits: 4 }
324+
- close_to: { aggregations.counter_weighted_avg.value: { value: 18.66, error: 0.01 } }

server/src/main/java/org/elasticsearch/search/aggregations/metrics/AvgAggregatorFactory.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import org.elasticsearch.search.aggregations.CardinalityUpperBound;
1515
import org.elasticsearch.search.aggregations.support.AggregationContext;
1616
import org.elasticsearch.search.aggregations.support.CoreValuesSourceType;
17+
import org.elasticsearch.search.aggregations.support.TimeSeriesValuesSourceType;
1718
import org.elasticsearch.search.aggregations.support.ValuesSourceAggregatorFactory;
1819
import org.elasticsearch.search.aggregations.support.ValuesSourceConfig;
1920
import org.elasticsearch.search.aggregations.support.ValuesSourceRegistry;
@@ -41,7 +42,12 @@ class AvgAggregatorFactory extends ValuesSourceAggregatorFactory {
4142
static void registerAggregators(ValuesSourceRegistry.Builder builder) {
4243
builder.register(
4344
AvgAggregationBuilder.REGISTRY_KEY,
44-
List.of(CoreValuesSourceType.NUMERIC, CoreValuesSourceType.DATE, CoreValuesSourceType.BOOLEAN),
45+
List.of(
46+
CoreValuesSourceType.NUMERIC,
47+
CoreValuesSourceType.DATE,
48+
CoreValuesSourceType.BOOLEAN,
49+
TimeSeriesValuesSourceType.COUNTER
50+
),
4551
AvgAggregator::new,
4652
true
4753
);

0 commit comments

Comments
 (0)