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

TSDB: Add time series information to field caps #78790

Merged
merged 10 commits into from
Oct 13, 2021

Conversation

imotov
Copy link
Contributor

@imotov imotov commented Oct 6, 2021

Exposes information about dimensions and metrics via field caps. This
information will be needed for different query languages support.

Relates to #74660

Exposes information about dimensions and metrics via field caps. This
information will be needed for PromQL support.

Relates to elastic#74660
@imotov imotov requested a review from csoulios October 6, 2021 23:23
@imotov imotov marked this pull request as ready for review October 6, 2021 23:23
@elasticmachine elasticmachine added the Team:Analytics Meta label for analytical engine team (ESQL/Aggs/Geo) label Oct 6, 2021
@elasticmachine
Copy link
Collaborator

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

@imotov imotov added :Search Foundations/Mapping Index mappings, including merging and defining field types and removed Team:Analytics Meta label for analytical engine team (ESQL/Aggs/Geo) labels Oct 6, 2021
@elasticmachine elasticmachine added the Team:Search Meta label for search team label Oct 6, 2021
@elasticmachine
Copy link
Collaborator

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
Copy link
Member

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.

Copy link
Contributor Author

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
Copy link
Member

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.

Copy link
Contributor Author

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.

Copy link
Member

Choose a reason for hiding this comment

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

ah. Makes sense.

@@ -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());
Copy link
Member

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.

Copy link
Member

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.

@imotov imotov requested a review from nik9000 October 11, 2021 23:12
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.
Copy link
Member

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`::
Copy link
Member

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
Copy link
Member

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
Copy link
Member

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)
Copy link
Member

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.

Copy link
Contributor Author

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?

Copy link
Member

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Copy link
Member

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)
Copy link
Member

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?

Copy link
Member

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.

Copy link
Member

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

Copy link
Contributor Author

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;
Copy link
Member

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 |=.

Copy link
Member

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.

Copy link
Contributor Author

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.

Copy link
Member

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.

Copy link
Member

@nik9000 nik9000 left a 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.
Copy link
Member

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.
Copy link
Member

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."

@imotov imotov merged commit f6034e6 into elastic:master Oct 13, 2021
imotov added a commit to imotov/elasticsearch that referenced this pull request Oct 14, 2021
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.
@imotov imotov deleted the tsdb-add-field-caps-support branch October 15, 2021 20:56
imotov added a commit that referenced this pull request Oct 18, 2021
…79206)

This is a followup for #78790, which allows us to replace
ConstructingObjectParser with InstantiatingObjectParser which makes keeping
track of the positional arguments somewhat easier.
@wchaparro wchaparro assigned imotov and unassigned imotov Dec 16, 2021
pull bot pushed a commit to NOUIY/elasticsearch that referenced this pull request Aug 4, 2022
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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
>enhancement :Search Foundations/Mapping Index mappings, including merging and defining field types :StorageEngine/TSDB You know, for Metrics Team:Search Meta label for search team v8.0.0-beta1
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants