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

[data.search][data.indexPatterns] Expose esaggs + indexPatternLoad on the server. #84590

Merged
merged 10 commits into from
Dec 3, 2020

Conversation

lukeelmers
Copy link
Member

@lukeelmers lukeelmers commented Nov 30, 2020

Part of #65067

Summary

This PR exposes the data plugin's esaggs and indexPatternLoad expression functions on the server as a part of the effort to make esaggs available on the server. (The indexPatternLoad function was moved here because it will be needed for the final step of improving the semantics of the esaggs function).

One complication that arose was that some of the services that esaggs relies on -- such as aggs, index patterns, and search source -- have slightly different contracts on the server in that they must be scoped to a specific user first. To address this, I've added an optional kibanaRequest handler to the expressions execution context. When executing an expression on the server, downstream consumers will need to provide this request object when making calls to run or execute so that the object is made available to the expression functions that need it. Assuming it is provided, the expression should return the same value that it would on the client.

Changes

  1. Splits implementation of esaggs on both client & server
  2. Moves some shared esaggs code to common
  3. Splits implementation of indexPatternLoad on both client & server
  4. Moves some shared indexPatternLoad code to common
  5. Updates agg types to make expressionName required, and ensure each type has an assigned name
    • Each of the agg type functions is already registered on the server, but we need expressionName so you can call aggConfig.toExpressionAst(), the output of which will be used when we refactor the esaggs arguments.

Reviewers

It's recommended to ignore whitespace changes and review this commit-by-commit, as github seems to have trouble displaying the diffs correctly. It looks like a ton of changes, but in reality a lot of them are from updating each of the agg types, which involved touching a bunch of files but was otherwise pretty repetitive.

Testing

This is a refactor that should introduce no functional changes. Areas touched include the querying infrastructure that's shared among all visualizations, including TSVB and lens.

@lukeelmers lukeelmers added Feature:Search Querying infrastructure in Kibana WIP Work in progress Feature:Aggregations Aggregation infrastructure (AggConfig, esaggs, ...) v8.0.0 v7.11.0 labels Nov 30, 2020
@lukeelmers lukeelmers self-assigned this Nov 30, 2020
@lukeelmers lukeelmers changed the title [data.search] Relocate esaggs to common so it can be exposed on the server. [data.search][data.indexPatterns] Expose esaggs + indexPatternLoad on the server. Dec 2, 2020
@lukeelmers lukeelmers added Feature:Data Views Data Views code and UI - index patterns before 8.0 release_note:skip Skip the PR/issue when compiling release notes and removed WIP Work in progress labels Dec 2, 2020
@@ -42,7 +41,7 @@ export class FieldFormatsRegistry {
protected metaParamsOptions: Record<string, any> = {};
protected getConfig?: FieldFormatsGetConfigFn;
// overriden on the public contract
public deserialize: (mapping: SerializedFieldFormat) => IFieldFormat = () => {
public deserialize: FormatFactory = () => {
Copy link
Member Author

Choose a reason for hiding this comment

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

The public contract uses FormatFactory, so this inconsistency caused some type issues when moving esaggs to the server.

"type": "function",
}
`);
});
Copy link
Member Author

Choose a reason for hiding this comment

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

For the agg types that already had unit tests, I added one to verify the output of toExpressionAst

};

return table;
}
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've split out a few things here that we can share on the client & server:

  1. The meta for the expression function definition
  2. The types for the function's dependencies & definition
  3. The request handler & logic that converts a response to a datatable

Comment on lines 77 to 114
return createEsaggs({
getStartDependencies: async () => {
const [, , self] = await getStartServices();
const { fieldFormats, indexPatterns, query, search } = self;
return {
addFilters: query.filterManager.addFilters.bind(query.filterManager),
aggs: search.aggs,
deserializeFieldFormat: fieldFormats.deserialize.bind(fieldFormats),
indexPatterns,
searchSource: search.searchSource,
};
},
});
Copy link
Member Author

Choose a reason for hiding this comment

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

This is the main difference between the public and server implementations -- basically it's a function that wires up all of the stateful dependencies on various start contracts.

The createEsaggs function above is much simpler: it's just responsible for retrieving the needed pieces of state from those services, and calling the helper that handles the entire request.

The goal here was to isolate differences between client & server code so that we could still share as much as possible from common, and I've used a similar approach with indexPatternLoad. Open to any feedback or other ideas on this.

Copy link
Member Author

Choose a reason for hiding this comment

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

Discussing this further in this thread.

expect(result.type).toEqual('index_pattern');
expect(result.value.title).toEqual('value');
});
});
Copy link
Member Author

Choose a reason for hiding this comment

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

There were already tests for indexPatternLoad but I haven't yet added any for esaggs -- my plan was to wait until the next PR as I'll be refactoring the args at that time anyway

Comment on lines +41 to +65
if (!kibanaRequest) {
throw new Error(
i18n.translate('data.search.esaggs.error.kibanaRequest', {
defaultMessage:
'A KibanaRequest is required to execute this search on the server. ' +
'Please provide a request object to the expression execution params.',
})
);
}
Copy link
Member Author

Choose a reason for hiding this comment

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

On the server we must have a KibanaRequest or we cannot scope the dependencies of esaggs, so any function that relies on a scoped service will need to throw if this handler is not present (since it's optional).

Comment on lines +20 to +21
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import type { KibanaRequest } from 'src/core/server';
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've tested, and so far it seems that as long as we're only importing a type from server, it doesn't create issues in the bundle as the typescript is compiled away.

};
},
})
);
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 moved esaggs function registration to the search service.

Did the same for indexPatternLoad in the index pattern service on the server, however kept it here on the client as there's no separate index pattern "service" that gets called in setup

@lukeelmers lukeelmers marked this pull request as ready for review December 2, 2020 04:34
@lukeelmers lukeelmers requested a review from a team as a code owner December 2, 2020 04:34
@elasticmachine
Copy link
Contributor

Pinging @elastic/kibana-app-services (Team:AppServices)

@botelastic botelastic bot added the Feature:ExpressionLanguage Interpreter expression language (aka canvas pipeline) label Dec 2, 2020
@lukeelmers
Copy link
Member Author

@elasticmachine merge upstream

@kibanamachine
Copy link
Contributor

💚 Build Succeeded

Metrics [docs]

Module Count

Fewer modules leads to a faster build time

id before after diff
data 602 605 +3

Distributable file count

id before after diff
default 43460 43470 +10
oss 22744 22754 +10

Page load bundle

Size of the bundles that are downloaded on every page load. Target size is below 100kb

id before after diff
data 983.3KB 987.2KB +4.0KB
expressions 182.5KB 182.6KB +93.0B
total +4.0KB

History

To update your PR or re-run it, just comment with:
@elasticmachine merge upstream

Copy link
Member

@ppisljar ppisljar left a comment

Choose a reason for hiding this comment

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

code LGTM

@lukeelmers lukeelmers removed the review label Dec 3, 2020
@lukeelmers lukeelmers merged commit d2fc976 into elastic:master Dec 3, 2020
@lukeelmers lukeelmers deleted the feat/esaggs-server-2 branch December 3, 2020 15:28
lukeelmers added a commit to lukeelmers/kibana that referenced this pull request Dec 3, 2020
lukeelmers added a commit that referenced this pull request Dec 3, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Feature:Aggregations Aggregation infrastructure (AggConfig, esaggs, ...) Feature:Data Views Data Views code and UI - index patterns before 8.0 Feature:ExpressionLanguage Interpreter expression language (aka canvas pipeline) Feature:Search Querying infrastructure in Kibana release_note:skip Skip the PR/issue when compiling release notes v7.11.0 v8.0.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants