-
Notifications
You must be signed in to change notification settings - Fork 24.9k
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
TSDB: Add time series information to field caps #78790
Conversation
Exposes information about dimensions and metrics via field caps. This information will be needed for PromQL support. Relates to elastic#74660
Pinging @elastic/es-analytics-geo (Team:Analytics) |
Pinging @elastic/es-search (Team:Search) |
"indices": [ "index3", "index4" ], | ||
"non_searchable_indices": [ "index4" ] | ||
}, | ||
"unmapped": { <1> | ||
"metadata_field": false, | ||
"indices": [ "index5" ], | ||
"searchable": false, | ||
"aggregatable": false | ||
"aggregatable": false, | ||
"time_series_dimension": false |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we want these to appear if the field isn't a dimension? I know lots of folks have thousands of fields and these responses can get quick large. Maybe we should leave it out if it is false.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a good idea.
PARSER.declareStringArray(ConstructingObjectParser.optionalConstructorArg(), INDICES_FIELD); // 6 | ||
PARSER.declareStringArray(ConstructingObjectParser.optionalConstructorArg(), NON_SEARCHABLE_INDICES_FIELD); // 7 | ||
PARSER.declareStringArray(ConstructingObjectParser.optionalConstructorArg(), NON_AGGREGATABLE_INDICES_FIELD); // 8 | ||
PARSER.declareStringArray(ConstructingObjectParser.optionalConstructorArg(), NON_DIMENSION_INDICES_FIELD); // 9 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe move this to your reflection builder. This is a bit scary.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you mean InstantiatingObjectParser we cannot use it here since the contractor needs context as the first argument. I can take a look at adding this functionality to the InstantiatingObjectParser in a separate PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ah. Makes sense.
server/src/main/java/org/elasticsearch/action/fieldcaps/FieldCapabilities.java
Show resolved
Hide resolved
server/src/main/java/org/elasticsearch/action/fieldcaps/FieldCapabilities.java
Show resolved
Hide resolved
@@ -518,6 +518,6 @@ public Long getCardinality(String field) { | |||
} | |||
|
|||
private static FieldCapabilities createFieldCapabilities(String field, String type) { | |||
return new FieldCapabilities(field, type, false, true, true, null, null, null, Collections.emptyMap()); | |||
return new FieldCapabilities(field, type, false, true, true, false, null, null, null, null, null, Collections.emptyMap()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe it'd be helpful to make a
public static final FieldCapabilities simple(String name, String type, boolean searchable, boolean aggregable) {
return new FieldCapabilities(field, type, false, searchable, aggregable, false, null, null, null, null, null, Collections.emptyMap());
}
on FieldCapabilities
or some test helper. It looks like a super common pattern.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or a second ctor. I'm not usually a big fan of extra ctors for tests, but there are so many args here and most code seems to pass exactly the same arguments.
indices have the same definition for the field. | ||
|
||
`metric_conflicts_indices`:: | ||
The list of indices where this field is present but don't have the same metrics type. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe s/metrics type/time_series_metric
/
`time_series_dimension`:: | ||
Whether this field is used as a time series dimension. | ||
|
||
`time_series_metrics`:: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it time_series_metric
- no trailing s
?
PARSER.declareStringArray(ConstructingObjectParser.optionalConstructorArg(), INDICES_FIELD); // 6 | ||
PARSER.declareStringArray(ConstructingObjectParser.optionalConstructorArg(), NON_SEARCHABLE_INDICES_FIELD); // 7 | ||
PARSER.declareStringArray(ConstructingObjectParser.optionalConstructorArg(), NON_AGGREGATABLE_INDICES_FIELD); // 8 | ||
PARSER.declareStringArray(ConstructingObjectParser.optionalConstructorArg(), NON_DIMENSION_INDICES_FIELD); // 9 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ah. Makes sense.
indiceList.add(indexCaps); | ||
this.isSearchable &= search; | ||
this.isAggregatable &= agg; | ||
this.isMetadataField |= isMetadataField; | ||
this.isDimension &= isDimension; | ||
// If we have discrepancy in metric types - we ignore it |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/ignore it/treat the fields as non-metrics and return metricConflictIndices/`?
if (isDimension == false && indiceList.stream().anyMatch((caps) -> caps.isDimension)) { | ||
// Collect all indices that disagree on the dimension flag | ||
nonDimensionIndices = indiceList.stream() | ||
.filter((caps) -> caps.isDimension == false) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like it collects all indices that agree.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If at least one dimension was "false" the end result will be false. However, if at least one dimension was true, we need to report all indices where it was marked as false (the trouble makers) as a non-dimensional index. I think this is consistent with non aggregatable and non searchable indices? Or did I miss your point?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess maybe just change the comment to // report the trouble makers
or something.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 Thanks. I'm being picky about language. It makes me feel better.
if (indiceList.stream().anyMatch((caps) -> caps.metricType != metricType)) { | ||
// Collect all indices that disagree on the dimension flag | ||
metricConflictsIndices = indiceList.stream() | ||
.map(caps -> caps.name) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is just all indices, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suppose if one is in conflict then they all are, but we do set the metric type to null
so I think maybe this should filter out the indices that don't consider it a field? I dunno.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Either way the comment above it inaccurate
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Copy/paste error
indiceList.add(indexCaps); | ||
this.isSearchable &= search; | ||
this.isAggregatable &= agg; | ||
this.isMetadataField |= isMetadataField; | ||
this.isDimension &= isDimension; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Having a non_dimension_indices
field makes me think maybe this should be |=
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or maybe we should flip the logic in non_dimension_indices
. I guess we want to degrade to non-tsdb mode when we get a combination.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think if a field was introduced as non dimension in early indices and then got converted to a dimension in a new index we are in trouble here. To me, this is a fatal error and the main use for this index list will be to generate an appropriate error message to the user.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍. It feels weird to have non_dimension_indices
when the top level is false
. Maybe I just need to get used to it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. I left a some comments about the docs - I think they still mention null but now the fields are absent instead. Also, I wanted to rewrite the description of non_dimension_indices
because I still haven't grown comfortable describing it. I understand why its the right way to return the data. I just can't describe why properly yet.
Whether this field is used as a time series dimension. | ||
|
||
`time_series_metric`:: | ||
Contains metric type if this fields is used as a time series metrics, null if the field is not used as metric. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is absent if the field is not a metric.
@@ -123,6 +129,14 @@ field types are all described as the `keyword` type family. | |||
The list of indices where this field is not aggregatable, or null if all | |||
indices have the same definition for the field. | |||
|
|||
`non_dimension_indices`:: | |||
The list of indices where this field is not marked as a dimension field, or null if all | |||
indices have the same definition for the field. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe a more obvious way of saying this could be "If this is present in response then some indices have the field marked as a dimension and other indices, the ones in this list, do not."
This is a followup for elastic#78790, which allows us to replace ConstructingObjectParser with InstantiatingObjectParser which makes keeping track of the positional arguments somewhat easier.
To assist the user in configuring the visualizations correctly while leveraging TSDB functionality, information about TSDB configuration should be exposed via the field caps API per field. Especially for metrics fields, it must be clear which fields are metrics and if they belong to only time-series indexes or mixed time-series and non-time-series indexes. To further distinguish metric fields when they belong to any of the following indices: - Standard (non-time-series) indexes - Time series indexes - Downsampled time series indexes This PR modifies the field caps API so that the mapping parameters time_series_dimension and time_series_dimension are presented only when they are set on fields of time-series indexes. Those parameters are completely ignored when they are set on standard (non-time-series) indexes. This PR revisits some of the conventions adopted by elastic#78790
Exposes information about dimensions and metrics via field caps. This
information will be needed for different query languages support.
Relates to #74660