Skip to content

Commit de70cc9

Browse files
kibanamachineElenaStoevamattkime
authored
[8.19] [Watcher] Fix watches table (elastic#218853) (elastic#219392)
# Backport This will backport the following commits from `main` to `8.19`: - [[Watcher] Fix watches table (elastic#218853)](elastic#218853) <!--- Backport version: 9.6.6 --> ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sorenlouv/backport) <!--BACKPORT [{"author":{"name":"Elena Stoeva","email":"[email protected]"},"sourceCommit":{"committedDate":"2025-04-28T13:07:42Z","message":"[Watcher] Fix watches table (elastic#218853)\n\nFixes https://github.com/elastic/kibana/issues/218341\n\n## Summary\n\nThis PR fixes the watches table where only up to 10 watches were\npreviously displayed because the Query Watch API returns maximum 10\nwatches by default. To fix this and to avoid performance issues for\nclusters with a large number of watches, we use pagination to only fetch\nthe watches for the current page.\n\n**Limitations:**\n- The Query Watch API only allows sorting by `_id` and `metadata.*`\nfields. However, we cannot allow sorting by ID in the table because this\nrequires enabling the `indices.id_field_data.enabled` cluster setting,\nwhich is disabled by default in the cluster. We can only sort by Name\nbecause the name is part of the `metadata` property. Therefore, we need\nto remove sorting for all columns but the Name.\n- We cannot utilize the native behavior of the Search bar where the\ntable would filter all items by itself, since in this case it would only\nfilter the current page of watches. We need to pass the query to the\nQuery Watches API. However, again only the `_id` and `metadata.*` fields\ncan be searched. Additionally, for `_id` we cannot use a wildcard query\nso the user would need to input the whole id for the requested watch to\nbe displayed. For name, we can use a wildcard query so searching by a\nsubstring of a name should work.\n\n**How to test:**\n1. Create more than 10 watches through the UI or with a Console request:\n\n```\nPUT _watcher/watch/{id}\n{\n \"metadata\": {\n \"name\": \"test-watch-{id}\",\n \"xpack\": {\n \"type\": \"json\"\n }\n },\n \"trigger\": {\n \"schedule\": {\n \"interval\": \"30m\"\n }\n }\n}\n```\n2. Verify that all watches can be viewed in the table and that they can\nbe sorted by Name and search by Name or ID.\n\n\n\n\n\nhttps://github.com/user-attachments/assets/6c812c5d-51e9-472c-a4d9-b1035843b9bb\n\n---------\n\nCo-authored-by: kibanamachine <[email protected]>\nCo-authored-by: Matthew Kime <[email protected]>","sha":"d9c481799f0edb3088595d21e4d7615b1a4e12f6","branchLabelMapping":{"^v9.1.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["Feature:Watcher","Team:Kibana Management","release_note:skip","backport:prev-minor","v9.1.0","v8.19.0","v8.18.1","v9.0.1"],"title":"[Watcher] Fix watches table","number":218853,"url":"https://github.com/elastic/kibana/pull/218853","mergeCommit":{"message":"[Watcher] Fix watches table (elastic#218853)\n\nFixes https://github.com/elastic/kibana/issues/218341\n\n## Summary\n\nThis PR fixes the watches table where only up to 10 watches were\npreviously displayed because the Query Watch API returns maximum 10\nwatches by default. To fix this and to avoid performance issues for\nclusters with a large number of watches, we use pagination to only fetch\nthe watches for the current page.\n\n**Limitations:**\n- The Query Watch API only allows sorting by `_id` and `metadata.*`\nfields. However, we cannot allow sorting by ID in the table because this\nrequires enabling the `indices.id_field_data.enabled` cluster setting,\nwhich is disabled by default in the cluster. We can only sort by Name\nbecause the name is part of the `metadata` property. Therefore, we need\nto remove sorting for all columns but the Name.\n- We cannot utilize the native behavior of the Search bar where the\ntable would filter all items by itself, since in this case it would only\nfilter the current page of watches. We need to pass the query to the\nQuery Watches API. However, again only the `_id` and `metadata.*` fields\ncan be searched. Additionally, for `_id` we cannot use a wildcard query\nso the user would need to input the whole id for the requested watch to\nbe displayed. For name, we can use a wildcard query so searching by a\nsubstring of a name should work.\n\n**How to test:**\n1. Create more than 10 watches through the UI or with a Console request:\n\n```\nPUT _watcher/watch/{id}\n{\n \"metadata\": {\n \"name\": \"test-watch-{id}\",\n \"xpack\": {\n \"type\": \"json\"\n }\n },\n \"trigger\": {\n \"schedule\": {\n \"interval\": \"30m\"\n }\n }\n}\n```\n2. Verify that all watches can be viewed in the table and that they can\nbe sorted by Name and search by Name or ID.\n\n\n\n\n\nhttps://github.com/user-attachments/assets/6c812c5d-51e9-472c-a4d9-b1035843b9bb\n\n---------\n\nCo-authored-by: kibanamachine <[email protected]>\nCo-authored-by: Matthew Kime <[email protected]>","sha":"d9c481799f0edb3088595d21e4d7615b1a4e12f6"}},"sourceBranch":"main","suggestedTargetBranches":["8.19","8.18","9.0"],"targetPullRequestStates":[{"branch":"main","label":"v9.1.0","branchLabelMappingKey":"^v9.1.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/218853","number":218853,"mergeCommit":{"message":"[Watcher] Fix watches table (elastic#218853)\n\nFixes https://github.com/elastic/kibana/issues/218341\n\n## Summary\n\nThis PR fixes the watches table where only up to 10 watches were\npreviously displayed because the Query Watch API returns maximum 10\nwatches by default. To fix this and to avoid performance issues for\nclusters with a large number of watches, we use pagination to only fetch\nthe watches for the current page.\n\n**Limitations:**\n- The Query Watch API only allows sorting by `_id` and `metadata.*`\nfields. However, we cannot allow sorting by ID in the table because this\nrequires enabling the `indices.id_field_data.enabled` cluster setting,\nwhich is disabled by default in the cluster. We can only sort by Name\nbecause the name is part of the `metadata` property. Therefore, we need\nto remove sorting for all columns but the Name.\n- We cannot utilize the native behavior of the Search bar where the\ntable would filter all items by itself, since in this case it would only\nfilter the current page of watches. We need to pass the query to the\nQuery Watches API. However, again only the `_id` and `metadata.*` fields\ncan be searched. Additionally, for `_id` we cannot use a wildcard query\nso the user would need to input the whole id for the requested watch to\nbe displayed. For name, we can use a wildcard query so searching by a\nsubstring of a name should work.\n\n**How to test:**\n1. Create more than 10 watches through the UI or with a Console request:\n\n```\nPUT _watcher/watch/{id}\n{\n \"metadata\": {\n \"name\": \"test-watch-{id}\",\n \"xpack\": {\n \"type\": \"json\"\n }\n },\n \"trigger\": {\n \"schedule\": {\n \"interval\": \"30m\"\n }\n }\n}\n```\n2. Verify that all watches can be viewed in the table and that they can\nbe sorted by Name and search by Name or ID.\n\n\n\n\n\nhttps://github.com/user-attachments/assets/6c812c5d-51e9-472c-a4d9-b1035843b9bb\n\n---------\n\nCo-authored-by: kibanamachine <[email protected]>\nCo-authored-by: Matthew Kime <[email protected]>","sha":"d9c481799f0edb3088595d21e4d7615b1a4e12f6"}},{"branch":"8.19","label":"v8.19.0","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"8.18","label":"v8.18.1","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"9.0","label":"v9.0.1","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"}]}] BACKPORT--> Co-authored-by: Elena Stoeva <[email protected]> Co-authored-by: Matthew Kime <[email protected]>
1 parent 78f1be0 commit de70cc9

File tree

9 files changed

+267
-139
lines changed

9 files changed

+267
-139
lines changed

x-pack/platform/plugins/private/translations/translations/fr-FR.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51653,7 +51653,6 @@
5165351653
"xpack.watcher.sections.watchList.watchTable.commentHeader": "Commentaire",
5165451654
"xpack.watcher.sections.watchList.watchTable.commentHeader.tooltipText": "Si des actions ont été reconnues ou contraintes, ou si leur exécution a échoué.",
5165551655
"xpack.watcher.sections.watchList.watchTable.disabledWatchTooltipText": "Cette alerte est en lecture seule",
51656-
"xpack.watcher.sections.watchList.watchTable.errorOnSearch": "Recherche non valide : {queryError}",
5165751656
"xpack.watcher.sections.watchList.watchTable.idHeader": "ID",
5165851657
"xpack.watcher.sections.watchList.watchTable.lastFiredHeader": "Dernière correspondance de la condition",
5165951658
"xpack.watcher.sections.watchList.watchTable.lastFiredHeader.tooltipText": "Dernière fois où la condition a été remplie et qu'une action a été entreprise.",

x-pack/platform/plugins/private/translations/translations/ja-JP.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51613,7 +51613,6 @@
5161351613
"xpack.watcher.sections.watchList.watchTable.commentHeader": "コメント",
5161451614
"xpack.watcher.sections.watchList.watchTable.commentHeader.tooltipText": "アクションが確認または調整されたか、あるいは実行が失敗したかどうか。",
5161551615
"xpack.watcher.sections.watchList.watchTable.disabledWatchTooltipText": "このウォッチは読み取り専用です",
51616-
"xpack.watcher.sections.watchList.watchTable.errorOnSearch": "無効な検索:{queryError}",
5161751616
"xpack.watcher.sections.watchList.watchTable.idHeader": "ID",
5161851617
"xpack.watcher.sections.watchList.watchTable.lastFiredHeader": "前回条件が満たされた日時",
5161951618
"xpack.watcher.sections.watchList.watchTable.lastFiredHeader.tooltipText": "最後に条件が満たされ、アクションが実行された日付。",

x-pack/platform/plugins/private/translations/translations/zh-CN.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51697,7 +51697,6 @@
5169751697
"xpack.watcher.sections.watchList.watchTable.commentHeader": "注释",
5169851698
"xpack.watcher.sections.watchList.watchTable.commentHeader.tooltipText": "是已确认、已限制还是无法执行任何操作。",
5169951699
"xpack.watcher.sections.watchList.watchTable.disabledWatchTooltipText": "此监视为只读",
51700-
"xpack.watcher.sections.watchList.watchTable.errorOnSearch": "搜索无效:{queryError}",
5170151700
"xpack.watcher.sections.watchList.watchTable.idHeader": "ID",
5170251701
"xpack.watcher.sections.watchList.watchTable.lastFiredHeader": "上次符合条件",
5170351702
"xpack.watcher.sections.watchList.watchTable.lastFiredHeader.tooltipText": "上次符合条件并采取了操作的时间。",

x-pack/platform/plugins/private/watcher/__jest__/client_integration/watch_list_page.test.ts

Lines changed: 6 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -76,48 +76,17 @@ describe('<WatchListPage />', () => {
7676
testBed.component.update();
7777
});
7878

79-
test('should show error callout if search is invalid', async () => {
80-
const { exists, actions } = testBed;
81-
82-
await actions.searchWatches('or');
83-
84-
expect(exists('watcherListSearchError')).toBe(true);
85-
});
86-
8779
test('should retain the search query', async () => {
88-
const { table, actions } = testBed;
89-
90-
await actions.searchWatches(watch1.name);
80+
const { actions, find } = testBed;
9181

92-
const { tableCellsValues } = table.getMetaData('watchesTable');
93-
94-
// Expect "watch1" is only visible in the table
95-
expect(tableCellsValues.length).toEqual(1);
96-
const row = tableCellsValues[0];
97-
const { name, id } = watch1;
98-
99-
const expectedRow = [
100-
'', // checkbox
101-
id,
102-
name,
103-
'', // state
104-
'', // lastMetCondition
105-
'', // lastChecked
106-
'', // comment
107-
'', // row actions
108-
];
109-
110-
expect(row).toEqual(expectedRow);
82+
await actions.searchWatches('query text');
11183

11284
await actions.advanceTimeToTableRefresh();
11385

114-
const { tableCellsValues: updatedTableCellsValues } = table.getMetaData('watchesTable');
115-
116-
// Verify "watch1" is still the only watch visible in the table
117-
expect(updatedTableCellsValues.length).toEqual(1);
118-
const updatedRow = updatedTableCellsValues[0];
119-
120-
expect(updatedRow).toEqual(expectedRow);
86+
const searchInput = find('watchesTableContainer').find('input.euiFieldSearch');
87+
// Verify the query text is still in the search bar
88+
// @ts-ignore
89+
expect(searchInput.instance().value).toEqual('query text');
12190
});
12291

12392
test('should set the correct app title', () => {

x-pack/platform/plugins/private/watcher/common/types/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,5 @@ export type {
1313
ServerWatchStatusModel,
1414
ClientWatchStatusModel,
1515
} from './status_types';
16+
17+
export type { BaseWatch } from './watch_types';

x-pack/platform/plugins/private/watcher/public/application/lib/api.ts

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,16 +29,33 @@ export const getHttpClient = () => {
2929

3030
const basePath = ROUTES.API_ROOT;
3131

32-
const loadWatchesDeserializer = ({ watches = [] }: { watches: any[] }) => {
33-
return watches.map((watch: any) => Watch.fromUpstreamJson(watch));
32+
const loadWatchesDeserializer = ({
33+
watches = [],
34+
watchCount,
35+
}: {
36+
watches: any[];
37+
watchCount: number;
38+
}) => {
39+
return {
40+
watches: watches.map((watch: any) => Watch.fromUpstreamJson(watch)),
41+
watchCount,
42+
};
3443
};
3544

36-
export const useLoadWatches = (pollIntervalMs: number) => {
45+
export const useLoadWatches = (
46+
pollIntervalMs: number,
47+
pageSize: number,
48+
pageIndex: number,
49+
sortField?: string,
50+
sortDirection?: string,
51+
query?: string
52+
) => {
3753
return useRequest({
3854
path: `${basePath}/watches`,
3955
method: 'get',
4056
pollIntervalMs,
4157
deserializer: loadWatchesDeserializer,
58+
query: { pageSize, pageIndex, sortField, sortDirection, query },
4259
});
4360
};
4461

0 commit comments

Comments
 (0)