Fix top_metrics when metric is missing (backport of #59471) (#59881)

This fixes a null pointer exception when the metric is missing for the
latest document returned by `top_metrics`.

Closes #58926
This commit is contained in:
Nik Everett 2020-07-20 10:42:58 -04:00 committed by GitHub
parent fe10141108
commit fcd8b5fe6e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 108 additions and 1 deletions

View File

@ -92,7 +92,11 @@ public class InternalTopMetrics extends InternalNumericMetricsAggregation.MultiV
return null;
}
assert topMetrics.size() == 1 : "property paths should only resolve against top metrics with size == 1.";
return topMetrics.get(0).metricValues.get(index).numberValue();
MetricValue metric = topMetrics.get(0).metricValues.get(index);
if (metric == null) {
return Double.NaN;
}
return metric.numberValue();
}
@Override

View File

@ -21,6 +21,7 @@ import org.elasticsearch.search.sort.SortOrder;
import org.elasticsearch.search.sort.SortValue;
import org.elasticsearch.test.InternalAggregationTestCase;
import org.elasticsearch.xpack.analytics.AnalyticsPlugin;
import org.elasticsearch.xpack.analytics.topmetrics.InternalTopMetrics.MetricValue;
import java.io.IOException;
import java.time.ZoneId;
@ -42,6 +43,7 @@ import static java.util.stream.Collectors.toList;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasKey;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.notANumber;
public class InternalTopMetricsTests extends InternalAggregationTestCase<InternalTopMetrics> {
/**
@ -213,6 +215,30 @@ public class InternalTopMetricsTests extends InternalAggregationTestCase<Interna
"}"));
}
public void testGetProperty() {
InternalTopMetrics metrics = new InternalTopMetrics(
"test",
SortOrder.ASC,
Arrays.asList("foo", "bar", "baz"),
1,
Arrays.asList(
new InternalTopMetrics.TopMetric(
DocValueFormat.RAW,
SortValue.from(1),
Arrays.asList(
new MetricValue(DocValueFormat.RAW, SortValue.from(1)), // foo
new MetricValue(DocValueFormat.RAW, SortValue.from(5.0)), // bar
null // baz
)
)
),
null
);
assertThat(metrics.getProperty("foo"), equalTo(1L));
assertThat(metrics.getProperty("bar"), equalTo(5.0));
assertThat((Double) metrics.getProperty("baz"), notANumber());
}
@Override
protected List<NamedXContentRegistry.Entry> getNamedXContents() {
List<NamedXContentRegistry.Entry> result = new ArrayList<>(super.getNamedXContents());

View File

@ -449,6 +449,83 @@
- match: { aggregations.ip.buckets.1.tm.top.0.metrics.v: 2 }
- match: { aggregations.ip.buckets.1.tm.top.0.sort: ['2020-01-01T02:01:01.000Z'] }
---
"with sum_buckets":
- do:
indices.create:
index: test
body:
mappings:
properties:
ip:
type: ip
date:
type: date
- do:
bulk:
index: test
refresh: true
body:
- '{"index": {}}'
- '{"ip": "192.168.0.1", "date": "2020-01-01T01:01:01", "v": 1}'
- '{"index": {}}'
- '{"ip": "192.168.0.1", "date": "2020-01-01T02:01:01", "v": 2}'
- '{"index": {}}'
- '{"ip": "192.168.0.2", "date": "2020-01-01T02:01:01", "v": 3}'
- do:
search:
size: 0
body:
aggs:
ip:
terms:
field: ip
aggs:
tm:
top_metrics:
metrics:
field: v
sort:
date: desc
sum:
sum_bucket:
buckets_path: ip>tm[v]
- length: { aggregations.ip.buckets: 2 }
- match: { aggregations.ip.buckets.0.key: 192.168.0.1 }
- match: { aggregations.sum.value: 5 }
# Now add a doc without the metric. Its value should count as 0 because the gap_policy should skip it.
- do:
bulk:
index: test
refresh: true
body:
- '{"index": {}}'
- '{"ip": "192.168.0.2", "date": "2020-01-01T03:01:01"}'
- do:
search:
size: 0
body:
aggs:
ip:
terms:
field: ip
aggs:
tm:
top_metrics:
metrics:
field: v
sort:
date: desc
sum:
sum_bucket:
buckets_path: ip>tm[v]
- length: { aggregations.ip.buckets: 2 }
- match: { aggregations.ip.buckets.0.key: 192.168.0.1 }
- match: { aggregations.sum.value: 2 }
---
"size is index setting":
- skip: