Skip to content

Commit d37cb19

Browse files
kibanamachineflash1293klacabane
authored
[9.2] 🌊 Streams: Retention pages fixes (#238683) (#239180)
# Backport This will backport the following commits from `main` to `9.2`: - [🌊 Streams: Retention pages fixes (#238683)](#238683) <!--- Backport version: 9.6.6 --> ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sorenlouv/backport) <!--BACKPORT [{"author":{"name":"Joe Reuter","email":"[email protected]"},"sourceCommit":{"committedDate":"2025-10-15T15:49:45Z","message":"🌊 Streams: Retention pages fixes (#238683)\n\nFixes https://github.com/elastic/kibana/issues/238277\nFixes https://github.com/elastic/kibana/issues/238643\n\n* Subtract failure store size from storage size when possible\n* Do not hide the chart data while it's loading after a refresh - no\njumpy chart\n* Only sample if there more than 10k docs in total:\n* On page load, start fetching with a sampling of 0.1 and fetch the data\nstream stats in parallel (this already happened)\n* If data stream stats arrive and there are less than 10k docs, refetch\nthe chart data without sampling\n\nThis has the following effect:\n* If there isn't much data, we fetch twice, but it doesn't matter much\nbecause there is very little data (e.g. for failure store) and the chart\nis meaningful because it has the actual counts\n* If there is a lot of data, nothing changes compared to todays version\n\n\nThis also does another improvement - for estimating the ingest rate, we\ncurrently take the current time range as the basis to extrapolate. But\nwe also know the creation date of the data stream, which we can take\ninto account. E.g. if the user picks a time range of \"last 10 years\",\nthen we can be smart and only take 4 days of that range if we know the\ndata stream only existed since 4 days.\n\n### Testing `(storage size - failure store)` change\n\n**Full permissions**\n- ingest documents in a stream and in its failure store\n- verify the \"Storage size\" corresponds to the sum of the regular\n(`.ds-..`) indices' of the stream\n- verify the \"Failure storage size\" corresponds to the failure store\n(`.fs-..`) size of the stream\n\n**No failure store permissions**\n- create user with no permissions to manage failure store\n```\n// 1. create role\nPOST _security/role/streams_no_failure_store\n{\n \"cluster\": [\n \"manage_index_templates\",\n \"manage_ingest_pipelines\"\n ],\n \"indices\": [\n {\n \"names\": [\n \"logs*\"\n ],\n \"privileges\": [\n \"view_index_metadata\",\n \"read\",\n \"write\",\n \"monitor\"\n ],\n \"field_security\": {\n \"grant\": [\n \"*\"\n ],\n \"except\": []\n },\n \"allow_restricted_indices\": false\n }\n ],\n \"applications\": [\n {\n \"application\": \"kibana-.kibana\",\n \"privileges\": [\n \"feature_streams.all\"\n ],\n \"resources\": [\n \"*\"\n ]\n }\n ],\n \"run_as\": [],\n \"metadata\": {},\n \"transient_metadata\": {\n \"enabled\": true\n }\n}\n\n// 2. create user\nPOST _security/user/streams_user_no_fs\n{\n \"password\" : \"changeme\",\n \"roles\" : [ \"streams_no_failure_store\" ]\n}\n```\n\n2. log in as user and visit the stream that contains regular and failure\nstore data\n3. verify that \"Storage size\" is the sum of regular (`.ds-..`) and\n(`.fs-..`) indices\n4. verify that Storage size has a tooltip and Ingestion rate's tooltip\nmentions that metrics may be inaccurate\n\n---------\n\nCo-authored-by: klacabane <[email protected]>\nCo-authored-by: kibanamachine <[email protected]>","sha":"389ef265945a0a9a5247bbb1ea993800917d61dc","branchLabelMapping":{"^v9.3.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:skip","Team:obs-ux-logs","backport:version","Feature:Streams","v9.2.0","Team:streams-program","v9.3.0"],"title":"🌊 Streams: Retention pages fixes","number":238683,"url":"https://github.com/elastic/kibana/pull/238683","mergeCommit":{"message":"🌊 Streams: Retention pages fixes (#238683)\n\nFixes https://github.com/elastic/kibana/issues/238277\nFixes https://github.com/elastic/kibana/issues/238643\n\n* Subtract failure store size from storage size when possible\n* Do not hide the chart data while it's loading after a refresh - no\njumpy chart\n* Only sample if there more than 10k docs in total:\n* On page load, start fetching with a sampling of 0.1 and fetch the data\nstream stats in parallel (this already happened)\n* If data stream stats arrive and there are less than 10k docs, refetch\nthe chart data without sampling\n\nThis has the following effect:\n* If there isn't much data, we fetch twice, but it doesn't matter much\nbecause there is very little data (e.g. for failure store) and the chart\nis meaningful because it has the actual counts\n* If there is a lot of data, nothing changes compared to todays version\n\n\nThis also does another improvement - for estimating the ingest rate, we\ncurrently take the current time range as the basis to extrapolate. But\nwe also know the creation date of the data stream, which we can take\ninto account. E.g. if the user picks a time range of \"last 10 years\",\nthen we can be smart and only take 4 days of that range if we know the\ndata stream only existed since 4 days.\n\n### Testing `(storage size - failure store)` change\n\n**Full permissions**\n- ingest documents in a stream and in its failure store\n- verify the \"Storage size\" corresponds to the sum of the regular\n(`.ds-..`) indices' of the stream\n- verify the \"Failure storage size\" corresponds to the failure store\n(`.fs-..`) size of the stream\n\n**No failure store permissions**\n- create user with no permissions to manage failure store\n```\n// 1. create role\nPOST _security/role/streams_no_failure_store\n{\n \"cluster\": [\n \"manage_index_templates\",\n \"manage_ingest_pipelines\"\n ],\n \"indices\": [\n {\n \"names\": [\n \"logs*\"\n ],\n \"privileges\": [\n \"view_index_metadata\",\n \"read\",\n \"write\",\n \"monitor\"\n ],\n \"field_security\": {\n \"grant\": [\n \"*\"\n ],\n \"except\": []\n },\n \"allow_restricted_indices\": false\n }\n ],\n \"applications\": [\n {\n \"application\": \"kibana-.kibana\",\n \"privileges\": [\n \"feature_streams.all\"\n ],\n \"resources\": [\n \"*\"\n ]\n }\n ],\n \"run_as\": [],\n \"metadata\": {},\n \"transient_metadata\": {\n \"enabled\": true\n }\n}\n\n// 2. create user\nPOST _security/user/streams_user_no_fs\n{\n \"password\" : \"changeme\",\n \"roles\" : [ \"streams_no_failure_store\" ]\n}\n```\n\n2. log in as user and visit the stream that contains regular and failure\nstore data\n3. verify that \"Storage size\" is the sum of regular (`.ds-..`) and\n(`.fs-..`) indices\n4. verify that Storage size has a tooltip and Ingestion rate's tooltip\nmentions that metrics may be inaccurate\n\n---------\n\nCo-authored-by: klacabane <[email protected]>\nCo-authored-by: kibanamachine <[email protected]>","sha":"389ef265945a0a9a5247bbb1ea993800917d61dc"}},"sourceBranch":"main","suggestedTargetBranches":["9.2"],"targetPullRequestStates":[{"branch":"9.2","label":"v9.2.0","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"main","label":"v9.3.0","branchLabelMappingKey":"^v9.3.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/238683","number":238683,"mergeCommit":{"message":"🌊 Streams: Retention pages fixes (#238683)\n\nFixes https://github.com/elastic/kibana/issues/238277\nFixes https://github.com/elastic/kibana/issues/238643\n\n* Subtract failure store size from storage size when possible\n* Do not hide the chart data while it's loading after a refresh - no\njumpy chart\n* Only sample if there more than 10k docs in total:\n* On page load, start fetching with a sampling of 0.1 and fetch the data\nstream stats in parallel (this already happened)\n* If data stream stats arrive and there are less than 10k docs, refetch\nthe chart data without sampling\n\nThis has the following effect:\n* If there isn't much data, we fetch twice, but it doesn't matter much\nbecause there is very little data (e.g. for failure store) and the chart\nis meaningful because it has the actual counts\n* If there is a lot of data, nothing changes compared to todays version\n\n\nThis also does another improvement - for estimating the ingest rate, we\ncurrently take the current time range as the basis to extrapolate. But\nwe also know the creation date of the data stream, which we can take\ninto account. E.g. if the user picks a time range of \"last 10 years\",\nthen we can be smart and only take 4 days of that range if we know the\ndata stream only existed since 4 days.\n\n### Testing `(storage size - failure store)` change\n\n**Full permissions**\n- ingest documents in a stream and in its failure store\n- verify the \"Storage size\" corresponds to the sum of the regular\n(`.ds-..`) indices' of the stream\n- verify the \"Failure storage size\" corresponds to the failure store\n(`.fs-..`) size of the stream\n\n**No failure store permissions**\n- create user with no permissions to manage failure store\n```\n// 1. create role\nPOST _security/role/streams_no_failure_store\n{\n \"cluster\": [\n \"manage_index_templates\",\n \"manage_ingest_pipelines\"\n ],\n \"indices\": [\n {\n \"names\": [\n \"logs*\"\n ],\n \"privileges\": [\n \"view_index_metadata\",\n \"read\",\n \"write\",\n \"monitor\"\n ],\n \"field_security\": {\n \"grant\": [\n \"*\"\n ],\n \"except\": []\n },\n \"allow_restricted_indices\": false\n }\n ],\n \"applications\": [\n {\n \"application\": \"kibana-.kibana\",\n \"privileges\": [\n \"feature_streams.all\"\n ],\n \"resources\": [\n \"*\"\n ]\n }\n ],\n \"run_as\": [],\n \"metadata\": {},\n \"transient_metadata\": {\n \"enabled\": true\n }\n}\n\n// 2. create user\nPOST _security/user/streams_user_no_fs\n{\n \"password\" : \"changeme\",\n \"roles\" : [ \"streams_no_failure_store\" ]\n}\n```\n\n2. log in as user and visit the stream that contains regular and failure\nstore data\n3. verify that \"Storage size\" is the sum of regular (`.ds-..`) and\n(`.fs-..`) indices\n4. verify that Storage size has a tooltip and Ingestion rate's tooltip\nmentions that metrics may be inaccurate\n\n---------\n\nCo-authored-by: klacabane <[email protected]>\nCo-authored-by: kibanamachine <[email protected]>","sha":"389ef265945a0a9a5247bbb1ea993800917d61dc"}}]}] BACKPORT--> Co-authored-by: Joe Reuter <[email protected]> Co-authored-by: klacabane <[email protected]>
1 parent fedea09 commit d37cb19

File tree

19 files changed

+583
-684
lines changed

19 files changed

+583
-684
lines changed

β€Žx-pack/platform/plugins/shared/streams_app/public/components/data_management/stream_detail_lifecycle/common/chart_components.tsxβ€Ž

Lines changed: 18 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -26,52 +26,34 @@ import moment from 'moment';
2626
import React, { useMemo } from 'react';
2727
import { orderIlmPhases } from '../helpers/helpers';
2828
import { formatBytes } from '../helpers/format_bytes';
29-
import type { DataStreamStats } from '../hooks/use_data_stream_stats';
3029
import { useIlmPhasesColorAndDescription } from '../hooks/use_ilm_phases_color_and_description';
31-
import type { useAggregations } from '../hooks/use_ingestion_rate';
30+
import type { StreamAggregations } from '../hooks/use_ingestion_rate';
3231
import { useIngestionRate, useIngestionRatePerTier } from '../hooks/use_ingestion_rate';
33-
import type { FailureStoreStats } from '../hooks/use_failure_store_stats';
3432
import { useTimefilter } from '../../../../hooks/use_timefilter';
33+
import type { CalculatedStats } from '../helpers/get_calculated_stats';
3534

36-
interface BaseChartComponentProps {
35+
interface ChartComponentProps {
3736
definition: Streams.ingest.all.GetResponse;
3837
timeState: TimeState;
3938
isLoadingStats: boolean;
39+
stats?: CalculatedStats;
40+
aggregations?: StreamAggregations;
41+
statsError: Error | undefined;
4042
}
4143

42-
interface MainStreamChartProps extends BaseChartComponentProps {
43-
stats?: DataStreamStats;
44-
isLoadingAggregations: boolean;
45-
aggregations?: ReturnType<typeof useAggregations>['aggregations'];
46-
aggregationsError: Error | undefined;
47-
}
48-
49-
interface FailureStoreChartProps extends BaseChartComponentProps {
50-
stats?: FailureStoreStats;
51-
isLoadingAggregations: boolean;
52-
aggregations?: ReturnType<typeof useAggregations>['aggregations'];
53-
aggregationsError: Error | undefined;
54-
}
55-
56-
type ChartComponentProps = MainStreamChartProps | FailureStoreChartProps;
57-
type ChartPhasesComponentProps = BaseChartComponentProps & {
58-
stats?: DataStreamStats;
59-
};
60-
6144
export function ChartBarSeries({
6245
stats,
6346
timeState,
6447
isLoadingStats,
65-
isLoadingAggregations,
6648
aggregations,
67-
aggregationsError,
49+
statsError,
6850
}: ChartComponentProps) {
6951
const mainStreamResult = useIngestionRate({
70-
stats,
52+
calculatedStats: stats,
7153
timeState,
7254
aggregations,
73-
isLoading: isLoadingAggregations,
74-
error: aggregationsError,
55+
isLoading: isLoadingStats,
56+
error: statsError,
7557
});
7658

7759
const formatAsBytes = !!stats;
@@ -98,16 +80,15 @@ export function FailureStoreChartBarSeries({
9880
stats,
9981
timeState,
10082
isLoadingStats,
101-
isLoadingAggregations,
10283
aggregations,
103-
aggregationsError,
84+
statsError,
10485
}: ChartComponentProps) {
10586
const failureStoreResult = useIngestionRate({
106-
stats,
87+
calculatedStats: stats,
10788
timeState,
10889
aggregations,
109-
isLoading: isLoadingAggregations,
110-
error: aggregationsError,
90+
isLoading: isLoadingStats,
91+
error: statsError,
11192
});
11293

11394
const formatAsBytes = !!stats;
@@ -151,7 +132,7 @@ export function ChartBarSeriesBase({
151132

152133
return ingestionRateError ? (
153134
'Failed to load ingestion rate'
154-
) : isLoadingStats || isLoadingIngestionRate || !ingestionRate ? (
135+
) : !ingestionRate && (isLoadingStats || isLoadingIngestionRate || !ingestionRate) ? (
155136
<EuiLoadingChart />
156137
) : (
157138
<>
@@ -215,7 +196,7 @@ function ChartBarPhasesSeriesBase({
215196

216197
return ingestionRateError ? (
217198
'Failed to load ingestion rate'
218-
) : isLoadingStats || isLoadingIngestionRate || !ingestionRate ? (
199+
) : !ingestionRate && (isLoadingStats || isLoadingIngestionRate || !ingestionRate) ? (
219200
<EuiLoadingChart />
220201
) : (
221202
<>
@@ -266,14 +247,14 @@ export function ChartBarPhasesSeries({
266247
stats,
267248
timeState,
268249
isLoadingStats,
269-
}: ChartPhasesComponentProps) {
250+
}: ChartComponentProps) {
270251
const { timeState: defaultTimeState } = useTimefilter();
271252
const currentTimeState = timeState || defaultTimeState;
272253

273254
// Use the appropriate hook based on isFailureStore flag
274255
const mainStreamResult = useIngestionRatePerTier({
275256
definition,
276-
stats,
257+
calculatedStats: stats,
277258
timeState: currentTimeState,
278259
});
279260

β€Žx-pack/platform/plugins/shared/streams_app/public/components/data_management/stream_detail_lifecycle/failure_store/cards/ingestion_card.tsxβ€Ž

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,15 @@ import { EuiIconTip } from '@elastic/eui';
1212
import { PrivilegesWarningIconWrapper } from '../../../../insufficient_privileges/insufficient_privileges';
1313
import { BaseMetricCard } from '../../common/base_metric_card';
1414
import { formatBytes } from '../../helpers/format_bytes';
15-
import type { FailureStoreStats } from '../../hooks/use_failure_store_stats';
15+
import type { EnhancedFailureStoreStats } from '../../hooks/use_data_stream_stats';
1616

1717
export const IngestionCard = ({
1818
definition,
1919
stats,
2020
statsError,
2121
}: {
2222
definition: Streams.ingest.all.GetResponse;
23-
stats?: FailureStoreStats;
23+
stats?: EnhancedFailureStoreStats;
2424
statsError?: Error;
2525
}) => {
2626
const hasPrivileges = definition.privileges?.manage_failure_store;

β€Žx-pack/platform/plugins/shared/streams_app/public/components/data_management/stream_detail_lifecycle/failure_store/cards/storage_size_card.tsxβ€Ž

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,16 @@ import type { Streams } from '@kbn/streams-schema';
1010
import { formatNumber } from '@elastic/eui';
1111
import { PrivilegesWarningIconWrapper } from '../../../../insufficient_privileges/insufficient_privileges';
1212
import { BaseMetricCard } from '../../common/base_metric_card';
13-
import type { FailureStoreStats } from '../../hooks/use_failure_store_stats';
1413
import { formatBytes } from '../../helpers/format_bytes';
14+
import type { EnhancedFailureStoreStats } from '../../hooks/use_data_stream_stats';
1515

1616
export const StorageSizeCard = ({
1717
definition,
1818
stats,
1919
statsError,
2020
}: {
2121
definition: Streams.ingest.all.GetResponse;
22-
stats?: FailureStoreStats;
22+
stats?: EnhancedFailureStoreStats;
2323
statsError?: Error;
2424
}) => {
2525
const hasPrivileges = definition.privileges?.manage_failure_store;

β€Žx-pack/platform/plugins/shared/streams_app/public/components/data_management/stream_detail_lifecycle/failure_store/failure_store_info.tsxβ€Ž

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ import { RetentionCard } from './cards/retention_card';
1414
import { StorageSizeCard } from './cards/storage_size_card';
1515
import { IngestionCard } from './cards/ingestion_card';
1616
import { FailureStoreIngestionRate } from './ingestion_rate';
17-
import type { FailureStoreStats } from '../hooks/use_failure_store_stats';
18-
import type { useAggregations } from '../hooks/use_ingestion_rate';
17+
import type { StreamAggregations } from '../hooks/use_ingestion_rate';
18+
import type { EnhancedFailureStoreStats } from '../hooks/use_data_stream_stats';
1919

2020
export const FailureStoreInfo = ({
2121
openModal,
@@ -26,19 +26,15 @@ export const FailureStoreInfo = ({
2626
config,
2727
timeState,
2828
aggregations,
29-
isLoadingAggregations,
30-
aggregationsError,
3129
}: {
3230
openModal: (show: boolean) => void;
3331
definition: Streams.ingest.all.GetResponse;
3432
statsError: Error | undefined;
3533
isLoadingStats: boolean;
36-
stats?: FailureStoreStats;
34+
stats?: EnhancedFailureStoreStats;
3735
config?: FailureStore;
3836
timeState: TimeState;
39-
aggregations?: ReturnType<typeof useAggregations>['aggregations'];
40-
isLoadingAggregations: boolean;
41-
aggregationsError: Error | undefined;
37+
aggregations?: StreamAggregations;
4238
}) => {
4339
return (
4440
<>
@@ -72,8 +68,7 @@ export const FailureStoreInfo = ({
7268
isLoadingStats={isLoadingStats}
7369
stats={stats}
7470
timeState={timeState}
75-
isLoadingAggregations={isLoadingAggregations}
76-
aggregationsError={aggregationsError}
71+
statsError={statsError}
7772
aggregations={aggregations}
7873
/>
7974
</>

β€Žx-pack/platform/plugins/shared/streams_app/public/components/data_management/stream_detail_lifecycle/failure_store/index.tsxβ€Ž

Lines changed: 14 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,8 @@ import { FailureStoreInfo } from './failure_store_info';
1414
import { useUpdateFailureStore } from '../../../../hooks/use_update_failure_store';
1515
import { useKibana } from '../../../../hooks/use_kibana';
1616
import { NoPermissionBanner } from './no_permission_banner';
17-
import { useFailureStoreStats } from '../hooks/use_failure_store_stats';
1817
import { useTimefilter } from '../../../../hooks/use_timefilter';
19-
import { useAggregations } from '../hooks/use_ingestion_rate';
18+
import type { useDataStreamStats } from '../hooks/use_data_stream_stats';
2019

2120
// Lazy load the FailureStoreModal to reduce bundle size
2221
const LazyFailureStoreModal = React.lazy(async () => ({
@@ -27,8 +26,10 @@ const FailureStoreModal = withSuspense(LazyFailureStoreModal);
2726

2827
export const StreamDetailFailureStore = ({
2928
definition,
29+
data,
3030
}: {
3131
definition: Streams.ingest.all.GetResponse;
32+
data: ReturnType<typeof useDataStreamStats>;
3233
}) => {
3334
const [isFailureStoreModalOpen, setIsFailureStoreModalOpen] = useState(false);
3435
const { updateFailureStore } = useUpdateFailureStore();
@@ -37,15 +38,6 @@ export const StreamDetailFailureStore = ({
3738
} = useKibana();
3839

3940
const { timeState } = useTimefilter();
40-
const {
41-
aggregations,
42-
isLoading: isLoadingAggregations,
43-
error: aggregationsError,
44-
} = useAggregations({
45-
definition,
46-
timeState,
47-
isFailureStore: true,
48-
});
4941

5042
const {
5143
privileges: {
@@ -58,13 +50,6 @@ export const StreamDetailFailureStore = ({
5850
setIsFailureStoreModalOpen(false);
5951
};
6052

61-
const {
62-
data,
63-
isLoading: isLoadingStats,
64-
error: statsError,
65-
refresh,
66-
} = useFailureStoreStats({ definition, timeState, aggregations });
67-
6853
const handleSaveModal = async (update: {
6954
failureStoreEnabled: boolean;
7055
customRetentionPeriod?: string;
@@ -89,37 +74,35 @@ export const StreamDetailFailureStore = ({
8974
});
9075
}
9176
closeModal();
92-
refresh();
77+
data.refresh();
9378
};
9479

9580
return (
9681
<EuiFlexItem grow={false}>
9782
<EuiFlexGroup direction="column" gutterSize="m">
9883
{readFailureStorePrivilege ? (
9984
<>
100-
{isFailureStoreModalOpen && manageFailureStorePrivilege && data?.config && (
85+
{isFailureStoreModalOpen && manageFailureStorePrivilege && data?.stats?.fs.config && (
10186
<FailureStoreModal
10287
onCloseModal={closeModal}
10388
onSaveModal={handleSaveModal}
10489
failureStoreProps={{
105-
failureStoreEnabled: data?.config.enabled,
106-
defaultRetentionPeriod: data?.config.retentionPeriod.default,
107-
customRetentionPeriod: data?.config.retentionPeriod.custom,
90+
failureStoreEnabled: data?.stats?.fs.config.enabled,
91+
defaultRetentionPeriod: data?.stats?.fs.config.retentionPeriod.default,
92+
customRetentionPeriod: data?.stats?.fs.config.retentionPeriod.custom,
10893
}}
10994
/>
11095
)}
111-
{isLoadingStats || data?.config.enabled ? (
96+
{data.isLoading || data?.stats?.fs.config.enabled ? (
11297
<FailureStoreInfo
11398
openModal={setIsFailureStoreModalOpen}
11499
definition={definition}
115-
statsError={statsError}
116-
isLoadingStats={isLoadingStats}
117-
stats={data?.stats}
118-
config={data?.config}
100+
statsError={data.error}
101+
isLoadingStats={data.isLoading}
102+
stats={data.stats?.fs.stats}
103+
config={data?.stats?.fs.config}
119104
timeState={timeState}
120-
isLoadingAggregations={isLoadingAggregations}
121-
aggregationsError={aggregationsError}
122-
aggregations={aggregations}
105+
aggregations={data?.stats?.fs.aggregations}
123106
/>
124107
) : (
125108
<NoFailureStorePanel openModal={setIsFailureStoreModalOpen} definition={definition} />

β€Žx-pack/platform/plugins/shared/streams_app/public/components/data_management/stream_detail_lifecycle/failure_store/ingestion_rate.tsxβ€Ž

Lines changed: 30 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -5,45 +5,56 @@
55
* 2.0.
66
*/
77
import React from 'react';
8-
import { EuiFlexGroup, EuiFlexItem, EuiPanel, EuiSpacer, EuiText } from '@elastic/eui';
8+
import {
9+
EuiFlexGroup,
10+
EuiFlexItem,
11+
EuiLoadingSpinner,
12+
EuiPanel,
13+
EuiSpacer,
14+
EuiText,
15+
} from '@elastic/eui';
916
import { i18n } from '@kbn/i18n';
1017
import type { Streams } from '@kbn/streams-schema';
1118
import type { TimeState } from '@kbn/es-query';
12-
import type { FailureStoreStats } from '../hooks/use_failure_store_stats';
1319
import { FailureStoreChartBarSeries } from '../common/chart_components';
1420
import { StreamsAppSearchBar } from '../../../streams_app_search_bar';
15-
import type { useAggregations } from '../hooks/use_ingestion_rate';
21+
import type { StreamAggregations } from '../hooks/use_ingestion_rate';
22+
import type { EnhancedFailureStoreStats } from '../hooks/use_data_stream_stats';
1623

1724
export function FailureStoreIngestionRate({
1825
definition,
1926
stats,
2027
isLoadingStats,
2128
timeState,
22-
isLoadingAggregations,
2329
aggregations,
24-
aggregationsError,
30+
statsError,
2531
}: {
2632
definition: Streams.ingest.all.GetResponse;
27-
stats?: FailureStoreStats;
33+
stats?: EnhancedFailureStoreStats;
2834
isLoadingStats: boolean;
2935
timeState: TimeState;
30-
isLoadingAggregations: boolean;
31-
aggregations?: ReturnType<typeof useAggregations>['aggregations'];
32-
aggregationsError: Error | undefined;
36+
aggregations?: StreamAggregations;
37+
statsError: Error | undefined;
3338
}) {
3439
return (
3540
<EuiPanel hasShadow={false} hasBorder paddingSize="m" grow={false}>
3641
<EuiPanel hasShadow={false} hasBorder={false} paddingSize="s">
3742
<EuiFlexGroup alignItems="center">
38-
<EuiFlexItem grow={3}>
39-
<EuiText>
40-
<h5>
41-
{i18n.translate('xpack.streams.failureStoreEnabled.ingestionRatePanel', {
42-
defaultMessage: 'Failure ingestion rate over time',
43-
})}
44-
</h5>
45-
</EuiText>
46-
</EuiFlexItem>
43+
<EuiFlexGroup gutterSize="s" alignItems="center">
44+
<EuiFlexItem grow={false}>
45+
<EuiText>
46+
<h5>
47+
{i18n.translate('xpack.streams.failureStoreEnabled.ingestionRatePanel', {
48+
defaultMessage: 'Failure ingestion rate over time',
49+
})}
50+
</h5>
51+
</EuiText>
52+
</EuiFlexItem>
53+
54+
<EuiFlexItem grow={false}>
55+
{isLoadingStats && aggregations && <EuiLoadingSpinner size="s" />}
56+
</EuiFlexItem>
57+
</EuiFlexGroup>
4758

4859
<EuiFlexItem grow={false}>
4960
<StreamsAppSearchBar showDatePicker />
@@ -65,8 +76,7 @@ export function FailureStoreIngestionRate({
6576
stats={stats}
6677
timeState={timeState}
6778
isLoadingStats={isLoadingStats}
68-
isLoadingAggregations={isLoadingAggregations}
69-
aggregationsError={aggregationsError}
79+
statsError={statsError}
7080
aggregations={aggregations}
7181
/>
7282
</EuiFlexGroup>

0 commit comments

Comments
Β (0)