Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Timelion percentiles aggregation support (#8953) #15154

Merged

Conversation

wkruse
Copy link
Contributor

@wkruse wkruse commented Nov 24, 2017

fixes #8953

Elasticsearch already supports percentiles aggregation. In order to support it in Timelion we add percentiles aggregation function and optionally a list of comma separated percents to the request.

{
    "aggs" : {
        "load_time_outlier" : {
            "percentiles" : {
                "field" : "load_time",
                "percents" : [95, 99.99] 
            }
        }
    }
}

The response contains a list of buckets, each of them is a single series.

{
    ...

   "aggregations": {
      "load_time_outlier": {
         "values" : { 
            "95.0": 60,
            "99.99": 150
         }
      }
   }
}

Usage in Timelion:

.es(*,metric='percentiles:load_time:95,99.99')

Thanks to @nisxiya!

Elasticsearch: Percentiles Aggregation

Elasticsearch already supports percentiles aggregation. In order to
support it in Timelion we add `percentiles` aggregation function and
optionally a list of comma separated `percents` to the request. The
response contains a list of buckets, each of them is a single series.
@elasticmachine
Copy link
Contributor

Can one of the admins verify this patch?

@wkruse
Copy link
Contributor Author

wkruse commented Nov 24, 2017

.es(*,metric="percentiles:bytes:50,95,99.99")

timelion-percentiles

@nreese nreese added Feature:Visualizations Generic visualization features (in case no more specific feature label is available) Feature:Timelion Timelion app and visualization v6.2.0 v7.0.0 release_note:enhancement labels Nov 27, 2017
Copy link
Contributor

@nreese nreese left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR. This is really nice.

There are just a few additional files that need to be updated

  • arg_value_suggestions Need to add percentiles as an argument suggestion.
  • We should add another test case to es.js to verify that multi-value metric aggregataion results are flattened as expected.

@@ -34,6 +34,11 @@ export default function createDateAgg(config, tlConfig, scriptedFields) {
const metricName = metric[0] + '(' + metric[1] + ')';
dateAgg.time_buckets.aggs[metricName] = {};
dateAgg.time_buckets.aggs[metricName][metric[0]] = buildAggBody(metric[1], scriptedFields);
if (metric[0] === 'percentiles' && metric[2]) {
let percentList = metric[2].split(',');
percentList = percentList.map(x => parseFloat(x));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

percents is an optional parameter of the percentiles aggregation. I think it should be optional in timelion as well. So percentiles:load_time and percentiles:load_time:95,99.99 are both valid.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is optional. In case there are no percents, metric[2] is false and percentList is not added to the request. ES returns the default list[ 1, 5, 25, 50, 75, 95, 99 ] then.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you are right. disregard

if (metric[0] === 'percentiles' && metric[2]) {
let percentList = metric[2].split(',');
percentList = percentList.map(x => parseFloat(x));
dateAgg.time_buckets.aggs[metricName][metric[0]].percents = percentList;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs to use the buildAggBody method so scripted fields can be supported.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Scripted fields are already supported.

36: dateAgg.time_buckets.aggs[metricName][metric[0]] = buildAggBody(metric[1], scriptedFields);

buildAggBody sets dateAgg.time_buckets.aggs[metricName][metric[0]] to either field or script, percents is added to the corresponding object afterwards.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you are right. disregard

@wkruse
Copy link
Contributor Author

wkruse commented Nov 29, 2017

Done. Should we also mention percentiles aggregation function on the function reference page?

@nreese
Copy link
Contributor

nreese commented Nov 29, 2017

@wkruse yes, that text should also be updated. Maybe something like
An elasticsearch metric agg: avg, sum, min, max, percentiles or cardinality, followed by a field. Eg "sum:bytes", "percentiles:bytes:95,99,99.9" or just "count"

@thomasneirynck what are your thoughts on the updated metric description?

@wkruse
Copy link
Contributor Author

wkruse commented Nov 30, 2017

@nreese Done.

Copy link
Contributor

@nreese nreese left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good to me (lgtm)

Copy link
Contributor

@thomasneirynck thomasneirynck left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a nice addition @wkruse, thanks a lot!

I think there's a small bug when dealing with time-ranges with empty data. Could you double check?

thx,

series[key] = series[key] || [];
series[key].push(val.value);
if (val.values) {
_.forOwn(val.values, function (bucketValue, bucketKey) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should filter here on NaN values. These arise when there is no data in the time-range of the bucket. They get propagated to the client, and the code breaks on the front-end (https://github.com/thomasneirynck/kibana/blob/e274f118f720386c551d3941668387f686e3d52c/src/core_plugins/timelion/public/panels/timechart/schema.js#L168-L168).

TypeError: y.toFixed is not a function
    at setLegendNumbers

@wkruse
Copy link
Contributor Author

wkruse commented Dec 5, 2017

Nice catch, thanks for looking into it @thomasneirynck!

First I tried to remove NaN values from the buckets, but it shifted the charts on the time axis.
Replacing NaN with 0 adds "gravitation".
Replacing 'NaN' string with the real NaN fixes the issue without affecting the visualization.
That is what I call scientific trial and error.
I sprinkled some NaN's into the test case.

@wkruse
Copy link
Contributor Author

wkruse commented Dec 5, 2017

Input data are in JSON. NaN is encoded as 'NaN' as there are no support for NaN in JSON. That is why I had to decode it back to NaN. Now it makes sense! 👍

@thomasneirynck
Copy link
Contributor

thanks for the quick update @wkruse, I'll try and take a look later today

Copy link
Contributor

@thomasneirynck thomasneirynck left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks @wkruse 🙇‍♂️ !

@nreese description for metric is good by me.

@nreese nreese merged commit 61ee81f into elastic:master Dec 11, 2017
@nreese
Copy link
Contributor

nreese commented Dec 11, 2017

Merged!

thanks @wkruse

nreese pushed a commit to nreese/kibana that referenced this pull request Dec 11, 2017
…15154)

* Add Timelion percentiles aggregation support (elastic#8953)

Elasticsearch already supports percentiles aggregation. In order to
support it in Timelion we add `percentiles` aggregation function and
optionally a list of comma separated `percents` to the request. The
response contains a list of buckets, each of them is a single series.

* Add percentiles as an argument suggestion

* Add test case for percentiles multi-value metric aggregation flattening

* Add percentiles to the function reference help page

* Fix broken frontend on NaN values
nreese added a commit that referenced this pull request Dec 12, 2017
* Add Timelion percentiles aggregation support (#8953)

Elasticsearch already supports percentiles aggregation. In order to
support it in Timelion we add `percentiles` aggregation function and
optionally a list of comma separated `percents` to the request. The
response contains a list of buckets, each of them is a single series.

* Add percentiles as an argument suggestion

* Add test case for percentiles multi-value metric aggregation flattening

* Add percentiles to the function reference help page

* Fix broken frontend on NaN values
@wkruse wkruse deleted the feature/timelion-percentiles-aggregation-support branch December 12, 2017 08:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Feature:Timelion Timelion app and visualization Feature:Visualizations Generic visualization features (in case no more specific feature label is available) release_note:enhancement v6.2.0 v7.0.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Timelion percentiles aggregation support
4 participants