Skip to content
Merged
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
631e69f
initial version
rStelmach May 27, 2025
520379b
update documentation link
rStelmach May 27, 2025
38e0bfe
Merge branch 'main' into 221006-dataset-quality-indicate-if-failure-s…
rStelmach May 28, 2025
7839491
[CI] Auto-commit changed files from 'node scripts/eslint --no-cache -…
kibanamachine May 28, 2025
35cc59c
add hasFailureStore flag to DataStreamStat model, distinguish dataset…
rStelmach May 30, 2025
eff4e3b
use passed hasFailureStore value instead of hardcoded false
rStelmach May 30, 2025
cfdedcd
adjust tests
rStelmach Jun 2, 2025
b10ef94
Merge branch 'main' into 221006-dataset-quality-indicate-if-failure-s…
rStelmach Jun 2, 2025
243b2b3
adjust functional tests
rStelmach Jun 2, 2025
c63c5f4
add hasFailureStore to dataStreamStats
rStelmach Jun 4, 2025
0597801
remove unnecessary type
rStelmach Jun 4, 2025
1f654d9
Merge branch 'main' into 221006-dataset-quality-indicate-if-failure-s…
rStelmach Jun 4, 2025
677be06
Check if failure store is enabled for datastream in dataset quality d…
rStelmach Jun 5, 2025
956d139
Merge branch 'main' into 221006-dataset-quality-indicate-if-failure-s…
rStelmach Jun 6, 2025
43f94cc
adjust functional tests
rStelmach Jun 6, 2025
6fa40e7
Merge branch 'main' into 221006-dataset-quality-indicate-if-failure-s…
yngrdyn Jun 10, 2025
7f6db0e
add tests for hovering functionality. update tests to have `handleFai…
rStelmach Jun 18, 2025
d3358c6
[CI] Auto-commit changed files from 'node scripts/eslint --no-cache -…
kibanamachine Jun 18, 2025
9f3fef1
Merge branch 'main' into 221006-dataset-quality-indicate-if-failure-s…
rStelmach Jun 18, 2025
257b60d
add api integration tests
rStelmach Jun 18, 2025
77abd1c
replace link to docs with datastream details locator
rStelmach Jun 20, 2025
66a42f1
Merge branch 'main' into 221006-dataset-quality-indicate-if-failure-s…
rStelmach Jun 20, 2025
1362929
resolve conflicts. add translation to 'N/A'. remove icon from warning
rStelmach Jun 23, 2025
ca558e8
Merge branch 'main' into 221006-dataset-quality-indicate-if-failure-s…
rStelmach Jun 23, 2025
ed15c9a
wait until tooltip dissapears in ftr
rStelmach Jun 23, 2025
f2bb67a
move mouse back to the table after veryfing tooltip next
rStelmach Jun 23, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ export const dataStreamStatRt = rt.intersection([
integration: rt.string,
totalDocs: rt.number,
creationDate: rt.number,
hasFailureStore: rt.boolean,
}),
]);

Expand Down Expand Up @@ -236,6 +237,7 @@ export const dataStreamSettingsRt = rt.partial({
export type DataStreamSettings = rt.TypeOf<typeof dataStreamSettingsRt>;

export const dataStreamDetailsRt = rt.partial({
hasFailureStore: rt.boolean,
lastActivity: rt.number,
degradedDocsCount: rt.number,
failedDocsCount: rt.number,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export class DataStreamStat {
docsInTimeRange?: number;
degradedDocs: QualityStat;
failedDocs: QualityStat;
hasFailureStore?: DataStreamStatType['hasFailureStore'];

private constructor(dataStreamStat: DataStreamStat) {
this.rawName = dataStreamStat.rawName;
Expand All @@ -49,13 +50,15 @@ export class DataStreamStat {
this.docsInTimeRange = dataStreamStat.docsInTimeRange;
this.degradedDocs = dataStreamStat.degradedDocs;
this.failedDocs = dataStreamStat.failedDocs;
this.hasFailureStore = dataStreamStat.hasFailureStore;
}

public static create(dataStreamStat: DataStreamStatType) {
const { type, dataset, namespace } = indexNameToDataStreamParts(dataStreamStat.name);

const dataStreamStatProps = {
rawName: dataStreamStat.name,
hasFailureStore: dataStreamStat.hasFailureStore,
type,
name: dataset,
title: dataset,
Expand All @@ -79,17 +82,20 @@ export class DataStreamStat {
failedDocStat,
datasetIntegrationMap,
totalDocs,
hasFailureStore,
}: {
datasetName: string;
degradedDocStat: QualityStat;
failedDocStat: QualityStat;
datasetIntegrationMap: Record<string, { integration: Integration; title: string }>;
totalDocs: number;
hasFailureStore?: boolean;
}) {
const { type, dataset, namespace } = indexNameToDataStreamParts(datasetName);

const dataStreamStatProps = {
rawName: datasetName,
hasFailureStore,
type,
name: dataset,
title: datasetIntegrationMap[dataset]?.title || dataset,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -355,29 +355,67 @@ export const getDatasetQualityTableColumns = ({
),
field: 'failedDocs.percentage',
sortable: true,
render: (_: any, dataStreamStat: DataStreamStat) => (
<PrivilegesWarningIconWrapper
title={`sizeBytes-${dataStreamStat.title}`}
hasPrivileges={dataStreamStat.userPrivileges?.canReadFailureStore ?? true}
>
<QualityStatPercentageLink
isLoading={loadingFailedStats}
dataStreamStat={dataStreamStat}
timeRange={timeRange}
accessor="failedDocs"
selector={FAILURE_STORE_SELECTOR}
fewDocStatsTooltip={(failedDocsCount: number) =>
i18n.translate('xpack.datasetQuality.fewFailedDocsTooltip', {
defaultMessage: '{failedDocsCount} failed docs in this data set.',
values: {
failedDocsCount,
},
})
}
dataTestSubj="datasetQualityFailedDocsPercentageLink"
/>
</PrivilegesWarningIconWrapper>
),
render: (_: any, dataStreamStat: DataStreamStat) => {
if (!dataStreamStat.hasFailureStore) {
const FailureStoreHoverLink = () => {
const [hovered, setHovered] = React.useState(false);
const locator = urlService.locators.get('INDEX_MANAGEMENT_LOCATOR_ID');
const params = {
page: 'data_streams_details',
dataStreamName: dataStreamStat.rawName,
} as const;

return (
<EuiToolTip
content={i18n.translate('xpack.datasetQuality.failureStore.notEnabled', {
defaultMessage:
'Failure store is not enabled for this data stream. Enable failure store.',
})}
>
<EuiLink
href={locator?.getRedirectUrl(params)}
target="_blank"
external={false}
data-test-subj="datasetQualitySetFailureStoreLink"
onMouseEnter={() => setHovered(true)}
onMouseLeave={() => setHovered(false)}
css={{ fontWeight: 'normal' }}
>
{hovered
? i18n.translate('xpack.datasetQuality.failureStore.enable', {
defaultMessage: 'Set failure store',
})
: 'N/A'}
Copy link
Contributor

Choose a reason for hiding this comment

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

This should also be translated

</EuiLink>
</EuiToolTip>
);
};
return <FailureStoreHoverLink />;
}
return (
<PrivilegesWarningIconWrapper
title={`sizeBytes-${dataStreamStat.title}`}
hasPrivileges={dataStreamStat.userPrivileges?.canReadFailureStore ?? true}
>
<QualityStatPercentageLink
isLoading={loadingFailedStats}
dataStreamStat={dataStreamStat}
timeRange={timeRange}
accessor="failedDocs"
selector={FAILURE_STORE_SELECTOR}
fewDocStatsTooltip={(failedDocsCount: number) =>
i18n.translate('xpack.datasetQuality.fewFailedDocsTooltip', {
defaultMessage: '{failedDocsCount} failed docs in this data set.',
values: {
failedDocsCount,
},
})
}
dataTestSubj="datasetQualityFailedDocsPercentageLink"
/>
</PrivilegesWarningIconWrapper>
);
},
width: '140px',
},
]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ export const Table = () => {
</EuiFlexGroup>
</EuiFlexGroup>
<EuiSpacer size="s" />
<EuiHorizontalRule margin="none" style={{ height: 2 }} />
<EuiHorizontalRule margin="none" css={{ height: 2 }} />
<EuiBasicTable
tableLayout="auto"
sorting={sort}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ const degradedDocsTooltip = (
// Allow for lazy loading
// eslint-disable-next-line import/no-default-export
export default function DocumentTrends({ lastReloadTime }: { lastReloadTime: number }) {
const { timeRange, updateTimeRange, docsTrendChart, canUserReadFailureStore } =
const { timeRange, updateTimeRange, docsTrendChart, canShowFailureStoreInfo } =
useDatasetQualityDetailsState();
const {
dataView,
Expand All @@ -81,7 +81,7 @@ export default function DocumentTrends({ lastReloadTime }: { lastReloadTime: num
[updateTimeRange, timeRange.refresh]
);

const accordionTitle = !canUserReadFailureStore ? (
const accordionTitle = !canShowFailureStoreInfo ? (
<EuiFlexItem
css={css`
flex-direction: row;
Expand Down Expand Up @@ -127,7 +127,7 @@ export default function DocumentTrends({ lastReloadTime }: { lastReloadTime: num
<EuiSpacer size="m" />
<EuiFlexGroup justifyContent="flexEnd" gutterSize="s">
<EuiFlexItem>
{canUserReadFailureStore && (
{canShowFailureStoreInfo && (
<EuiButtonGroup
data-test-subj="datasetQualityDetailsChartTypeButtonGroup"
legend={i18n.translate('xpack.datasetQuality.details.chartTypeLegend', {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@

import React, { useCallback, useState } from 'react';
import { dynamic } from '@kbn/shared-ux-utility';
import { EuiCallOut, EuiFlexItem, EuiSpacer, OnRefreshProps } from '@elastic/eui';
import { EuiCallOut, EuiFlexItem, EuiLink, EuiSpacer, OnRefreshProps } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { noAccessToFailureStoreWarningDescription } from '../../../../common/translations';
import { useDatasetQualityDetailsState } from '../../../hooks';
import { AggregationNotSupported } from './aggregation_not_supported';
import { QualityIssues } from './quality_issues';
import { useKibanaContextForPlugin } from '../../../utils/use_kibana';

const OverviewHeader = dynamic(() => import('./header'));
const Summary = dynamic(() => import('./summary'));
Expand All @@ -22,9 +24,20 @@ export function Overview() {
dataStream,
isNonAggregatable,
canUserReadFailureStore,
hasFailureStore,
updateTimeRange,
loadingState: { dataStreamSettingsLoading },
} = useDatasetQualityDetailsState();

const {
services: {
share: { url: urlService },
},
} = useKibanaContextForPlugin();

const locator = urlService.locators.get('INDEX_MANAGEMENT_LOCATOR_ID');
const locatorParams = { page: 'data_streams_details', dataStreamName: dataStream } as const;

const [lastReloadTime, setLastReloadTime] = useState<number>(Date.now());

const handleRefresh = useCallback(
Expand All @@ -39,6 +52,32 @@ export function Overview() {
{isNonAggregatable && <AggregationNotSupported dataStream={dataStream} />}
<OverviewHeader handleRefresh={handleRefresh} />
<EuiSpacer size="m" />
{!dataStreamSettingsLoading && !hasFailureStore && canUserReadFailureStore && (
<div style={{ marginBottom: 16 }}>
<EuiCallOut
color="warning"
iconType="warning"
title={
<>
{i18n.translate('xpack.datasetQuality.noFailureStoreTitle', {
defaultMessage: 'Failure store is not enabled for this data stream. ',
})}
<EuiLink
href={locator?.getRedirectUrl(locatorParams)}
target="_blank"
external={false}
color="warning"
css={{ textDecoration: 'underline' }}
>
{i18n.translate('xpack.datasetQuality.enableFailureStore', {
defaultMessage: 'Enable failure store',
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 make this to look more like a link?
image

Copy link
Contributor

Choose a reason for hiding this comment

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

Adding an icon would be beneficial here @patpscal?

Copy link
Contributor Author

@rStelmach rStelmach Jun 23, 2025

Choose a reason for hiding this comment

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

Screenshot 2025-06-23 at 11 29 05

How about this ?

})}
</EuiLink>
</>
}
/>
</div>
)}
{!dataStreamSettingsLoading && !canUserReadFailureStore && (
<EuiFlexItem>
<EuiCallOut
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ const failedDocsColumnTooltip = (
// Allow for lazy loading
// eslint-disable-next-line import/no-default-export
export default function Summary() {
const { canUserReadFailureStore } = useDatasetQualityDetailsState();
const { canShowFailureStoreInfo } = useDatasetQualityDetailsState();
const {
isSummaryPanelLoading,
totalDocsCount,
Expand Down Expand Up @@ -103,7 +103,7 @@ export default function Summary() {
isLoading={isSummaryPanelLoading}
tooltip={degradedDocsTooltip}
/>
{canUserReadFailureStore && (
{canShowFailureStoreInfo && (
<PanelIndicator
label={overviewPanelDatasetQualityIndicatorFailedDocs}
value={totalFailedDocsCount}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,9 @@ export const useDatasetQualityDetailsState = () => {
[service]
);

const hasFailureStore = Boolean(dataStreamDetails?.hasFailureStore);
const canShowFailureStoreInfo = canUserReadFailureStore && hasFailureStore;

return {
service,
telemetryClient,
Expand All @@ -182,6 +185,8 @@ export const useDatasetQualityDetailsState = () => {
canUserAccessDashboards,
canUserViewIntegrations,
canUserReadFailureStore,
hasFailureStore,
canShowFailureStoreInfo,
expandedQualityIssue,
isQualityIssueFlyoutOpen,
};
Expand Down
Loading