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

[ResponseOps] Mapped/searchable params #126531

Merged
merged 8 commits into from
Mar 4, 2022

Conversation

JiaweiWu
Copy link
Contributor

Summary

Addresses the issue: #124338

Complete implementation allowing for mapped/Searchable params. The change maps the values from params, which is a flattened field, to a mapped field called mapped_params. This lets us sort/filter/search on these values. To the public, these fields should be hidden, attempts to use mapped_params should not be allowed.

currently we are supporting:

params.risk_score -> mapped_params.risk_score
params.severity -> mapped_params.severity

In the background, mapped_params.severity is stored as 20-low, 40-medium, etc.... This enables us to sort on these fields.

Here's a screenshot that shows sorting by risk score, which is a params property, using mapped_params

Future additions to mapped_params will be done at an ad-hoc basis.

mapped_params

This change contains the following:

  • Create an util function to extract our mapped_params from the params attribute
  • Create an util function to replace our query parameters like sort_fields and search_fields and filter to use mapped_params instead of params field when we can
  • Integrate our util functions to do our migration around mapped params
  • Integrate our util functions around our I/O function like create/update/find
  • Make sure to hide our mapped_params from our public API

@JiaweiWu JiaweiWu added release_note:skip Skip the PR/issue when compiling release notes backport:skip This commit does not require backporting Team:ResponseOps Label for the ResponseOps team (formerly the Cases and Alerting teams) ci:deploy-cloud v8.2.0 labels Feb 28, 2022
@JiaweiWu JiaweiWu requested review from a team as code owners February 28, 2022 21:35
@elasticmachine
Copy link
Contributor

Pinging @elastic/response-ops (Team:ResponseOps)

@JiaweiWu JiaweiWu changed the title Mapped/searchable params [ResponseOps] Mapped/searchable params Feb 28, 2022
@@ -196,15 +196,15 @@ export const useRulesColumns = ({ hasPermissions }: ColumnsProps): TableColumn[]
{value}
</EuiText>
),
sortable: !!isInMemorySorting,
sortable: true,
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This and line 207 are only here for testing/demoing purposes. Will be removed once this PR is approved

Comment on lines +193 to +201
it('should sort by parameters', async () => {
const response = await supertest.get(
`${getUrlPrefix(Spaces.space1.id)}/${
describeType === 'public' ? 'api' : 'internal'
}/alerting/rules/_find?sort_field=params.severity&sort_order=asc`
);
expect(response.body.data[0].params.severity).to.equal('low');
expect(response.body.data[1].params.severity).to.equal('medium');
expect(response.body.data[2].params.severity).to.equal('high');
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'm not sure why but this test fails in CI, but I can't seem to get it to fail locally (always passes)

Copy link
Contributor

Choose a reason for hiding this comment

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

How are you running it locally? Using --grep?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

correct, using the functional test runner and --grep="find".

Copy link
Contributor

Choose a reason for hiding this comment

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

Try running it a level up until you find the error, so instead of --grep="find", try --grep="Alerting"

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah got it, makes sense, yea I'll try that

@chrisronline
Copy link
Contributor

What do you think about adding a test in our migrations file? https://github.com/elastic/kibana/blob/main/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/migrations.ts

You'll need to add a new alert, or just modify an existing one in the archive, to contain the legacy data and ensure the migration occurred smoothly

@JiaweiWu
Copy link
Contributor Author

JiaweiWu commented Mar 1, 2022

Yep I can

Copy link
Contributor

@chrisronline chrisronline left a comment

Choose a reason for hiding this comment

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

This looks really really good! I had a couple of notes/comments so far

}, []);
};

export const getModifiedValue = (key: string, value: string) => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we add a comment here explaining why we need to do this? It looks like we want to remap these values but I don't know why

Copy link
Contributor

Choose a reason for hiding this comment

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

I can explain, it is because in the params, we are saving the severity like critical, hight ... but in the mapped params, we are saving it like 80-critical, 60-high .... Therefore we can sort the severity field the right way.

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah okay so to avoid needing to store the label and the value, we're going to put the value in the label so we can do the right sort. We should add a clarifying comment for future folks though

}

if (filterKueryNode) {
modifyFilterKueryNode({ astFilter: filterKueryNode });
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you explain why this is necessary? Does the esKuery.fromKueryExpression not handle everything we need?

Copy link
Contributor

Choose a reason for hiding this comment

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

the reason is if your query has field which belong in the mapped_fields, we will convert this field to use the mapped_params like if you want to filter on risk_score the query will be something like alert.attributes.params.risk_score > 50 then we will convert it to alert.attributes.mapped_params.risk_score > 50

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah okay so the filter kuery node functionality has no understanding of this mapped_params duality state situation so we need to explicitly modify the results to handle that - okay makes sense - lets add a clarifying comment for future folks

const response = await supertest.get(
`${getUrlPrefix(Spaces.space1.id)}/${
describeType === 'public' ? 'api' : 'internal'
}/alerting/rules/_find?search_fields=params.severity&search=40-medium`
Copy link
Contributor

Choose a reason for hiding this comment

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

I think the test should be like that and behind the scene we are doing the change

Suggested change
}/alerting/rules/_find?search_fields=params.severity&search=40-medium`
}/alerting/rules/_find?search_fields=params.severity&search=medium`

expect(response.body.total).to.equal(1);
expect(response.body.data[0].params.risk_score).to.eql(40);

if (describeType === 'public') {
Copy link
Contributor

Choose a reason for hiding this comment

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

😍

Copy link
Contributor

Choose a reason for hiding this comment

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

Looks great in practice! (The separate of public and internal)

@mdefazio
Copy link
Contributor

mdefazio commented Mar 3, 2022

@JiaweiWu Is it possible to add in additional screenshots to the description of the PR? I thought I remember seeing this demoed outside of the security table with a specific search box. It'll help me provide some UI feedback if I can see it in all scenarios. Otherwise, if / when you're ready we can just do a quick zoom to go through it together.

@JiaweiWu
Copy link
Contributor Author

JiaweiWu commented Mar 3, 2022

@elasticmachine merge upstream

@JiaweiWu
Copy link
Contributor Author

JiaweiWu commented Mar 3, 2022

@mdefazio
Hey! Yea I created those search boxes pretty ad-hoc just to demo the searching and filtering since these are new searchable fields, so we currently don't have UI that performs this search. This PR is mostly the backend change to enable this, but yea, feel free to throw something in my calendar and I can give you more information.

@XavierM
Copy link
Contributor

XavierM commented Mar 3, 2022

@elasticmachine merge upstream

@JiaweiWu JiaweiWu requested review from chrisronline and XavierM March 3, 2022 19:25
if (options.searchFields) {
options.searchFields = getModifiedSearchFields(options.searchFields);
}
// Generate new modified search and search fields, translating certain params properties
Copy link
Contributor

Choose a reason for hiding this comment

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

❤️

@XavierM
Copy link
Contributor

XavierM commented Mar 4, 2022

@elasticmachine merge upstream

Copy link
Contributor

@XavierM XavierM left a comment

Choose a reason for hiding this comment

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

Well done!, exactly what we wanted. You are going to make some people happy!

Copy link
Contributor

@chrisronline chrisronline left a comment

Choose a reason for hiding this comment

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

LGTM!

@kibana-ci
Copy link
Collaborator

💚 Build Succeeded

Metrics [docs]

Public APIs missing comments

Total count of every public API that lacks a comment. Target amount is 0. Run node scripts/build_api_docs --plugin [yourplugin] --stats comments for more detailed information.

id before after diff
alerting 293 298 +5

Async chunks

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

id before after diff
securitySolution 4.7MB 4.7MB -2.0B

Saved Objects .kibana field count

Every field in each saved object type adds overhead to Elasticsearch. Kibana needs to keep the total field count below Elasticsearch's default limit of 1000 fields. Only specify field mappings for the fields you wish to search on or query. See https://www.elastic.co/guide/en/kibana/master/development-plugin-saved-objects.html#_mappings

id before after diff
alert 48 51 +3
Unknown metric groups

API count

id before after diff
alerting 301 306 +5

History

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

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 ci:cloud-deploy Create or update a Cloud deployment release_note:skip Skip the PR/issue when compiling release notes Team:ResponseOps Label for the ResponseOps team (formerly the Cases and Alerting teams) v8.2.0
Projects
None yet
8 participants