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

Support multiple metrics in top_metrics agg #52965

Merged
merged 5 commits into from
Mar 5, 2020

Conversation

nik9000
Copy link
Member

@nik9000 nik9000 commented Feb 28, 2020

This adds support for returning multiple metrics to the top_metrics
agg. It looks like:

POST /test/_search?filter_path=aggregations
{
  "aggs": {
    "tm": {
      "top_metrics": {
        "metrics": [
          {"field": "v"},
          {"field": "m"}
        ],
        "sort": {"s": "desc"}
      }
    }
  }
}

Relates to #51813.

This adds support for returning multiple metrics to the `top_metrics`
agg. It looks like:
```
POST /test/_search?filter_path=aggregations
{
  "aggs": {
    "tm": {
      "top_metrics": {
        "metrics": [
          {"field": "v"},
          {"field": "m"}
        ],
        "sort": {"s": "desc"}
      }
    }
  }
}
```
@elasticmachine
Copy link
Collaborator

Pinging @elastic/es-analytics-geo (:Analytics/Aggregations)

@nik9000
Copy link
Member Author

nik9000 commented Feb 28, 2020

Adding a second metric to fetch is pretty cheap! Some benchmarks that I'm playing with have the 90% latency for one metric at 923ms and two metrics at 931ms. I'm kind of surprised it is in the neighborhood of 1% cost.

Copy link
Member

@not-napoleon not-napoleon left a comment

Choose a reason for hiding this comment

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

The ValuesSource usage here seems weird to me, and I'd like to understand it before I approve this.

return topMetrics.get(0).metricValue;
int index = metricNames.indexOf(name);
if (index < 0) {
throw new IllegalArgumentException("known metric [" + name + "]");
Copy link
Member

Choose a reason for hiding this comment

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

I don't understand what this error message means. Should it read "Unknown metric..."?

Copy link
Member Author

Choose a reason for hiding this comment

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

+1 - it should be unknown metric. I don't believe we'll ever throw it because of the interplay with hasValue. Which bothers me, but is a problem for another PR.

private final int size;
private final MultiValuesSourceFieldConfig metricField;
private final List<MultiValuesSourceFieldConfig> metricFields;
// TODO MultiValuesSourceFieldConfig has more things than we support and less things than we want to support
Copy link
Member

Choose a reason for hiding this comment

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

Can you expand on this a bit, and/or open a ticket for it? Feel free to ignore this comment if you're planing to resolve this TODO soon, but I'm worried that if we find this again in a few months we won't remember what it is we intended to do here.
Also, it looks like later on, we just turn this into a list of ValuesSourceConfig. Why not just start with ValuesSourceConfig at this point?

Copy link
Member Author

Choose a reason for hiding this comment

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

I inherited this from @polyfractal's original implementation. I can look into changing to directly to ValuesSourceConfig.

Copy link
Member

Choose a reason for hiding this comment

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

ha, that's exactly the kind of problem I want to prevent ;)

We could leave this as a TODO for now, since we're hoping to merge the new Values Source work soon-ish, and that dramatically reduces the complexity of ValuesSourceConfig, making it more like an actual config object and less like a magic box.

Copy link
Member

Choose a reason for hiding this comment

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

(but if we do leave it as a todo, we should still clarify what we want to do and when)

for (MultiValuesSourceFieldConfig config : fieldsConfig) {
ValuesSourceConfig<ValuesSource.Numeric> resolved = ValuesSourceConfig.resolve(ctx, ValueType.NUMERIC,
config.getFieldName(), config.getScript(), config.getMissing(), config.getTimeZone(), null);
if (resolved == null) {
Copy link
Member

Choose a reason for hiding this comment

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

Does ValuesSourceConfig#resolve actually return null in some cases? I didn't see a path that would cause that. Or is this just being defensive?

Copy link
Member Author

Choose a reason for hiding this comment

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

I thought it did. Looks like I was confused. I'll dig.

values[i++] = new MissingMetricValues();
continue;
}
ValuesSource.Numeric valuesSource = resolved.toValuesSource(ctx);
Copy link
Member

Choose a reason for hiding this comment

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

Be aware that this can throw on invalid configs (i.e. configs containing neither a script nor a field)

int i = 0;
for (MultiValuesSourceFieldConfig config : fieldsConfig) {
ValuesSourceConfig<ValuesSource.Numeric> resolved = ValuesSourceConfig.resolve(ctx, ValueType.NUMERIC,
config.getFieldName(), config.getScript(), config.getMissing(), config.getTimeZone(), null);
Copy link
Member

Choose a reason for hiding this comment

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

This seems late in the game to be resolving values sources. Usually we do that at the border between the builder and the factory, and pass the values source(s) into the aggregator. If it has to be this way, let's at least leave a comment as to why that's the case, please.

Copy link
Member Author

Choose a reason for hiding this comment

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

I believe this is right at aggregator construction time - so it is on the boarder, just on the Aggregator side of it. I can see if I can move it if it'd make things nicer.

@nik9000
Copy link
Member Author

nik9000 commented Mar 4, 2020

@not-napoleon I've updated this based on our conversation and believe it should be ready for another round.

Copy link
Member

@not-napoleon not-napoleon 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, thanks for making those changes.

@nik9000
Copy link
Member Author

nik9000 commented Mar 4, 2020

Looks good, thanks for making those changes.

❤️

@elasticsearchmachine run elasticsearch-ci/2

@nik9000 nik9000 merged commit 56058ab into elastic:master Mar 5, 2020
nik9000 added a commit to nik9000/elasticsearch that referenced this pull request Mar 5, 2020
)

This adds support for returning multiple metrics to the `top_metrics`
agg. It looks like:
```
POST /test/_search?filter_path=aggregations
{
  "aggs": {
    "tm": {
      "top_metrics": {
        "metrics": [
          {"field": "v"},
          {"field": "m"}
        ],
        "sort": {"s": "desc"}
      }
    }
  }
}
```
nik9000 added a commit that referenced this pull request Mar 5, 2020
…53163)

This adds support for returning multiple metrics to the `top_metrics`
agg. It looks like:
```
POST /test/_search?filter_path=aggregations
{
  "aggs": {
    "tm": {
      "top_metrics": {
        "metrics": [
          {"field": "v"},
          {"field": "m"}
        ],
        "sort": {"s": "desc"}
      }
    }
  }
}
```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants