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

[Discover] Add support for contextual awareness functional tests #185905

Merged
merged 14 commits into from
Jun 19, 2024

Conversation

davismcphee
Copy link
Contributor

@davismcphee davismcphee commented Jun 10, 2024

Summary

This PR adds functional test support for the Discover contextual awareness framework, and adds tests for the initial getCellRenderers extension point using example profiles.

To support this, this PR introduces a new YAML setting called discover.experimental.enabledProfiles which can be used to selectively enable profiles both for functional testing and demoing WIP profiles that aren't yet ready for GA.

Example usage:

discover.experimental.enabledProfiles: ['example-root-profile', 'example-data-source-profile', 'example-document-profile']

Flaky test runs:

Resolves #184699.

Checklist

For maintainers

@davismcphee davismcphee added release_note:skip Skip the PR/issue when compiling release notes Team:DataDiscovery Discover, search (e.g. data plugin and KQL), data views, saved searches. For ES|QL, use Team:ES|QL. Project:OneDiscover Enrich Discover with contextual awareness labels Jun 10, 2024
@davismcphee davismcphee self-assigned this Jun 10, 2024
@davismcphee
Copy link
Contributor Author

/ci

@davismcphee davismcphee force-pushed the one-discover-functional-tests branch from ec06e14 to 831f324 Compare June 12, 2024 19:14
@davismcphee
Copy link
Contributor Author

/ci

@davismcphee
Copy link
Contributor Author

/ci

@davismcphee
Copy link
Contributor Author

/ci

@kibanamachine
Copy link
Contributor

Flaky Test Runner Stats

🎉 All tests passed! - kibana-flaky-test-suite-runner#6304

[✅] test/functional/apps/discover/context_awareness/config.ts: 50/50 tests passed.

see run history

@kibanamachine
Copy link
Contributor

Flaky Test Runner Stats

🎉 All tests passed! - kibana-flaky-test-suite-runner#6307

[✅] x-pack/test_serverless/functional/test_suites/security/config.context_awareness.ts: 50/50 tests passed.

see run history

@kibanamachine
Copy link
Contributor

Flaky Test Runner Stats

🎉 All tests passed! - kibana-flaky-test-suite-runner#6305

[✅] x-pack/test_serverless/functional/test_suites/observability/config.context_awareness.ts: 50/50 tests passed.

see run history

@kibanamachine
Copy link
Contributor

Flaky Test Runner Stats

🎉 All tests passed! - kibana-flaky-test-suite-runner#6306

[✅] x-pack/test_serverless/functional/test_suites/search/config.context_awareness.ts: 50/50 tests passed.

see run history

@davismcphee
Copy link
Contributor Author

/ci

@davismcphee davismcphee marked this pull request as ready for review June 13, 2024 03:07
@davismcphee davismcphee requested review from a team as code owners June 13, 2024 03:08
@elasticmachine
Copy link
Contributor

Pinging @elastic/kibana-data-discovery (Team:DataDiscovery)

Copy link
Contributor

@jughosta jughosta left a comment

Choose a reason for hiding this comment

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

LGTM 👍

@tonyghiani
Copy link
Contributor

@davismcphee I just finished a first pass on the changes at a high-level, here some thoughts:

  • Working with esArchiver for the FT makes it more difficult to debug and update test data as mock data are gzipped and there is no explicit data to look over while debugging.
    I believe switching to synthtrace will make more manageable the fake data and avoid the configuration of additional esArchives, here you can find a quick example of ad-hoc logs ingested for an FT.
  • The new discover.experimental.enabledProfiles setting requires every developer to know about all the available profile ids and set them manually to develop the contextual awareness architecture. I'm not sure if this is easily maintainable as many devs might stay out of sync if they don't set/update this setting.
    Is there any particular benefit I am missing here for why we need this setting first? If the matter is keeping it disabled while developing, we can just not pass it on the list of registered providers, otherwise, I can't think of a reason why a ready-to-production profile should be disabled.
  • The example profiles are useful to understand the capabilities of each profile type, although I wonder if makes sens to register them on the main system where we also add the real profiles. If it's for testing/documentation purpose only, shall we move them out and register them on a test env only?
  • The profile manager init and profiles registration start having more logic around it (singleton profiles registration step, depends on config, need services injection, dynamic loading, ...) and the plugin entry point has already knowledge of more and more of it (this.profileProvidersRegistered).
    Should we consider extracting these parts into a more encapsulated service, so that a client is instantiated lazily on demand, and all these implementation details don't pertain to the main plugin? I'm not leaving examples but I have some to provide, happy to talk more about this 👌

@davismcphee
Copy link
Contributor Author

Thanks for the review @tonyghiani, and some responses to your feedback:

Working with esArchiver for the FT makes it more difficult to debug and update test data as mock data are gzipped and there is no explicit data to look over while debugging.
I believe switching to synthtrace will make more manageable the fake data and avoid the configuration of additional esArchives, here you can find a quick example of ad-hoc logs ingested for an FT.

Neat, I actually didn't realize you could use synthtrace as a service in functional tests since it's not something I've seen used in Platform tests. That said, I'd prefer to keep using the esArchiver approach for now to avoid blocking this PR to refactor how the example data is ingested.

The example data should be very simple and predictable, not reflective of real world data, to make it easy to assert against specific index names, field contents, etc. I'm sure we could do this with synthtrace too, but that would basically just be another way of hardcoding it through a different API. I'd rather use synthtrace for cases where we want realistic data like when testing the actual logs profiles. But if you feel strongly about this, I'd accept a followup PR that migrates the example data to be ingested through synthtrace instead.

The new discover.experimental.enabledProfiles setting requires every developer to know about all the available profile ids and set them manually to develop the contextual awareness architecture. I'm not sure if this is easily maintainable as many devs might stay out of sync if they don't set/update this setting.
Is there any particular benefit I am missing here for why we need this setting first? If the matter is keeping it disabled while developing, we can just not pass it on the list of registered providers, otherwise, I can't think of a reason why a ready-to-production profile should be disabled.

The intent isn't to have all profiles enabled through discover.experimental.enabledProfiles, only ones that we don't want exposed to users by default. Other ones such as the logs profiles will be hardcoded to be enabled, which is what I've done here now that they've been merged: 1aff791.

The reason we want this setting other than for example profiles is so that we can merge incomplete or experimental profiles to main without releasing them to users, allowing product folks to set up demo environments to test different combinations of unreleased profiles, or rolling out experimental profiles in serverless before going GA in a stateful release.

The example profiles are useful to understand the capabilities of each profile type, although I wonder if makes sens to register them on the main system where we also add the real profiles. If it's for testing/documentation purpose only, shall we move them out and register them on a test env only?

We discussed just hardcoding them to be enabled when passing --run-examples like we do with most other example functionality, but decided it against it since we don't want them to interfere with the default Discover behaviour in dev environments where folks often run Kibana with --run-examples, so we went with a YAML setting instead. I don't really see an issue with them being registered through the same mechanism as other profiles since we won't be enabling them unless specified.

The profile manager init and profiles registration start having more logic around it (singleton profiles registration step, depends on config, need services injection, dynamic loading, ...) and the plugin entry point has already knowledge of more and more of it (this.profileProvidersRegistered).
Should we consider extracting these parts into a more encapsulated service, so that a client is instantiated lazily on demand, and all these implementation details don't pertain to the main plugin? I'm not leaving examples but I have some to provide, happy to talk more about this 👌

Personally I think a dedicated service for this would be overkill, but I agree that the handling of profiles was starting to get messy. I revisited this and realized we actually don't need this.profileProvidersRegistered or class fields for the services. In the interest of moving quickly and keeping things simple, I went with a straightforward approach of just memoizing the creation of services and profile registrations here: 07a26a8.

@tonyghiani
Copy link
Contributor

The reason we want this setting other than for example profiles is so that we can merge incomplete or experimental profiles to main without releasing them to users, allowing product folks to set up demo environments to test different combinations of unreleased profiles, or rolling out experimental profiles in serverless before going GA in a stateful release.

@davismcphee I see your point, I guess it would be useful to then have some sort of guidance on how to use this (I think you mentioned you had a follow-up PR for documentation).

I'll continue the PR review and leave the previous points to your judgment, I feel synthtrace should be the way to go for new tests as it makes it much easier to iterate the tests and update the mock data, but it's not necessarily a must-have here if you want to unblock this PR 👌

Copy link
Contributor

@tonyghiani tonyghiani left a comment

Choose a reason for hiding this comment

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

LGTM 👌

Copy link
Contributor

@logeekal logeekal left a comment

Choose a reason for hiding this comment

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

small questions/comments

it('should render custom @timestamp but not custom log.level', async () => {
const state = kbnRison.encode({
dataSource: { type: 'esql' },
query: { esql: 'from my-example-* | sort @timestamp desc' },
Copy link
Contributor

Choose a reason for hiding this comment

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

I have question for my clarity. Even though my-example-* includes my-example-logs as an index, why log.level is not customized here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good question, it's just due to the way the resolution logic for the example profile that customizes log.level is implemented here:

if (indexPattern !== 'my-example-logs') {
return { isMatch: false };
}

We're only matching on this profile if the index pattern exactly equals my-example-logs, although it could have been implemented to match on any index pattern covered by my-example-* if I had decided to implement it that way. Real resolution implementations like the logs one are more sophisticated, this one is pretty dumb just for example purposes.

Copy link
Contributor

Choose a reason for hiding this comment

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

Ahh... I went though these example profile multiple time but missed this line. Sorry for that and thank you very much for pointing it out.

Real resolution implementations like the logs one are more sophisticated, this one is pretty dumb just for example purposes.

Makes sense to me now. This demonstrates the profile resolutions well enough. Thanks.

const level = getFieldValue(props.row, 'log.level');

if (!level) {
return <span css={{ color: euiThemeVars.euiTextSubduedColor }}>(None)</span>;
Copy link
Contributor

Choose a reason for hiding this comment

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

I suggest to add data-test-subj here as well, since this is also a customized renderer and not the original one.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Makes sense to me, added here: de21734

Copy link
Contributor Author

@davismcphee davismcphee left a comment

Choose a reason for hiding this comment

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

@davismcphee I see your point, I guess it would be useful to then have some sort of guidance on how to use this (I think you mentioned you had a follow-up PR for documentation).

Definitely it would be, and I do intend to add documentation and will make sure to cover this since I understand it's currently confusing for others. Just a matter of finding some time between trying to get things ready for next week's demo 😅 It's ON Week for us next week and I'm on PTO the following week, but I will aim to address this ASAP.

I feel synthtrace should be the way to go for new tests as it makes it much easier to iterate the tests and update the mock data

Fully agree, it's a better way for sure, and I appreciate the understanding. Now that I know how to use it for FTs, we should absolutely use it at least for testing real profile implementations, and I will see if I can find some time to come back and update these example tests to use it too.

const level = getFieldValue(props.row, 'log.level');

if (!level) {
return <span css={{ color: euiThemeVars.euiTextSubduedColor }}>(None)</span>;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Makes sense to me, added here: de21734

it('should render custom @timestamp but not custom log.level', async () => {
const state = kbnRison.encode({
dataSource: { type: 'esql' },
query: { esql: 'from my-example-* | sort @timestamp desc' },
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good question, it's just due to the way the resolution logic for the example profile that customizes log.level is implemented here:

if (indexPattern !== 'my-example-logs') {
return { isMatch: false };
}

We're only matching on this profile if the index pattern exactly equals my-example-logs, although it could have been implemented to match on any index pattern covered by my-example-* if I had decided to implement it that way. Real resolution implementations like the logs one are more sophisticated, this one is pretty dumb just for example purposes.

@kibana-ci
Copy link
Collaborator

💛 Build succeeded, but was flaky

Failed CI Steps

Test Failures

  • [job] [logs] Jest Tests #17 / Fleet integration policy endpoint security event filters card should show the card when no permissions but results

Metrics [docs]

Module Count

Fewer modules leads to a faster build time

id before after diff
discover 930 938 +8

Async chunks

Total size of all lazy-loaded chunks that will be downloaded as the user navigates the app

id before after diff
discover 804.2KB 808.7KB +4.5KB

Page load bundle

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

id before after diff
discover 44.0KB 42.6KB -1.4KB
Unknown metric groups

async chunk count

id before after diff
discover 24 25 +1

History

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

cc @davismcphee

@davismcphee davismcphee merged commit 57891ff into elastic:main Jun 19, 2024
22 checks passed
@davismcphee davismcphee deleted the one-discover-functional-tests branch June 19, 2024 17:17
@kibanamachine kibanamachine added v8.15.0 backport:skip This commit does not require backporting labels Jun 19, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backport:skip This commit does not require backporting Project:OneDiscover Enrich Discover with contextual awareness release_note:skip Skip the PR/issue when compiling release notes Team:DataDiscovery Discover, search (e.g. data plugin and KQL), data views, saved searches. For ES|QL, use Team:ES|QL. v8.15.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Discover] Add functional tests for Discover contextual awareness framework
10 participants