Skip to content

Commit

Permalink
[Dataset quality] Fix Degraded Docs Percentage Rounding (#177934)
Browse files Browse the repository at this point in the history
closes #173739

## 📝  Summary

This PR adds a tooltip when there are few degraded docs, basically below
0.005 to avoid rounding issues and still show a notification to the user
that they have few degraded docs on a specific fataset.

## 🎥 Demo



https://github.com/elastic/kibana/assets/11225826/ae4f9c48-0532-4a20-9211-d895c2ff46ef
  • Loading branch information
mohamedhamed-ahmed authored Mar 7, 2024
1 parent 20aa335 commit cfd1961
Show file tree
Hide file tree
Showing 10 changed files with 103 additions and 37 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ export type Integration = rt.TypeOf<typeof integrationRt>;
export const degradedDocsRt = rt.type({
dataset: rt.string,
percentage: rt.number,
count: rt.number,
});

export type DegradedDocs = rt.TypeOf<typeof degradedDocsRt>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@ export const DEFAULT_SORT_DIRECTION = 'asc';
export const NONE = 'none';

export const DEFAULT_TIME_RANGE = { from: 'now-24h', to: 'now' };
export const DEFAULT_DEGRADED_DOCS = { percentage: 0, count: 0 };
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
* 2.0.
*/

import { DEFAULT_DEGRADED_DOCS } from '../constants';
import { DataStreamType } from '../types';
import { indexNameToDataStreamParts } from '../utils';
import { Integration } from './integration';
Expand All @@ -20,7 +21,10 @@ export class DataStreamStat {
sizeBytes?: DataStreamStatType['sizeBytes'];
lastActivity?: DataStreamStatType['lastActivity'];
integration?: Integration;
degradedDocs?: number;
degradedDocs: {
percentage: number;
count: number;
};

private constructor(dataStreamStat: DataStreamStat) {
this.rawName = dataStreamStat.rawName;
Expand All @@ -32,7 +36,10 @@ export class DataStreamStat {
this.sizeBytes = dataStreamStat.sizeBytes;
this.lastActivity = dataStreamStat.lastActivity;
this.integration = dataStreamStat.integration;
this.degradedDocs = dataStreamStat.degradedDocs;
this.degradedDocs = {
percentage: dataStreamStat.degradedDocs.percentage,
count: dataStreamStat.degradedDocs.count,
};
}

public static create(dataStreamStat: DataStreamStatType) {
Expand All @@ -50,6 +57,7 @@ export class DataStreamStat {
integration: dataStreamStat.integration
? Integration.create(dataStreamStat.integration)
: undefined,
degradedDocs: DEFAULT_DEGRADED_DOCS,
};

return new DataStreamStat(dataStreamStatProps);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,12 @@ import { DegradedDocsStatType } from './types';
export class DegradedDocsStat {
dataset: DegradedDocsStatType['dataset'];
percentage: DegradedDocsStatType['percentage'];
count: DegradedDocsStatType['count'];

private constructor(degradedDocsStat: DegradedDocsStat) {
this.dataset = degradedDocsStat.dataset;
this.percentage = degradedDocsStat.percentage;
this.count = degradedDocsStat.count;
}

public static create(degradedDocsStat: DegradedDocsStatType) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ export const getDatasetQualityTableColumns = ({
</span>
</EuiToolTip>
),
field: 'degradedDocs',
field: 'degradedDocs.percentage',
sortable: true,
render: (_, dataStreamStat: DataStreamStat) => (
<DegradedDocsPercentageLink
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,27 +18,29 @@ export const DegradedDocsPercentageLink = ({
isLoading: boolean;
dataStreamStat: DataStreamStat;
}) => {
const {
degradedDocs: { percentage, count },
} = dataStreamStat;

const logsExplorerLinkProps = useLinkToLogsExplorer({
dataStreamStat,
query: { language: 'kuery', query: '_ignored:*' },
});

return (
<>
<EuiSkeletonRectangle width="50px" height="20px" borderRadius="m" isLoading={isLoading}>
<EuiFlexGroup alignItems="center" gutterSize="s">
{dataStreamStat.degradedDocs ? (
<EuiLink
data-test-subj="datasetQualityDegradedDocsPercentageLink"
{...logsExplorerLinkProps}
>
<QualityPercentageIndicator percentage={dataStreamStat.degradedDocs} />
</EuiLink>
) : (
<QualityPercentageIndicator percentage={dataStreamStat.degradedDocs} />
)}
</EuiFlexGroup>
</EuiSkeletonRectangle>
</>
<EuiSkeletonRectangle width="50px" height="20px" borderRadius="m" isLoading={isLoading}>
<EuiFlexGroup alignItems="center" gutterSize="s">
{percentage ? (
<EuiLink
data-test-subj="datasetQualityDegradedDocsPercentageLink"
{...logsExplorerLinkProps}
>
<QualityPercentageIndicator percentage={percentage} degradedDocsCount={count} />
</EuiLink>
) : (
<QualityPercentageIndicator percentage={percentage} />
)}
</EuiFlexGroup>
</EuiSkeletonRectangle>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,57 @@
* 2.0.
*/

import { EuiText } from '@elastic/eui';
import { EuiIcon, EuiText, EuiToolTip } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { FormattedNumber } from '@kbn/i18n-react';
import React from 'react';
import { mapPercentageToQuality } from './helpers';
import { QualityIndicator } from './indicator';

export function QualityPercentageIndicator({ percentage = 0 }: { percentage?: number }) {
const FEW_DEGRADED_DOCS_THRESHOLD = 0.0005;

export function QualityPercentageIndicator({
percentage,
degradedDocsCount,
}: {
percentage: number;
degradedDocsCount?: number;
}) {
const quality = mapPercentageToQuality(percentage);

const description = (
<EuiText size="s">
<FormattedNumber value={percentage} />%
</EuiText>
const isFewDegradedDocsAvailable = percentage && percentage < FEW_DEGRADED_DOCS_THRESHOLD;

const description = isFewDegradedDocsAvailable ? (
<DatasetWithFewDegradedDocs degradedDocsCount={degradedDocsCount} />
) : (
<DatasetWithManyDegradedDocs percentage={percentage} />
);

return <QualityIndicator quality={quality} description={description} />;
}

const DatasetWithFewDegradedDocs = ({ degradedDocsCount }: { degradedDocsCount?: number }) => {
return (
<EuiText size="s">
~0%{' '}
<EuiToolTip
content={i18n.translate('xpack.datasetQuality.fewDegradedDocsTooltip', {
defaultMessage: '{degradedDocsCount} degraded docs in this dataset.',
values: {
degradedDocsCount,
},
})}
>
<EuiIcon type="warning" color="warning" size="s" />
</EuiToolTip>
</EuiText>
);
};

const DatasetWithManyDegradedDocs = ({ percentage }: { percentage: number }) => {
return (
<EuiText size="s">
<FormattedNumber value={percentage} />%
</EuiText>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,20 @@ export function mergeDegradedStatsIntoDataStreams(
dataStreamStats: DataStreamStat[],
degradedDocStats: DegradedDocsStat[]
) {
const degradedMap: Record<DegradedDocsStat['dataset'], DegradedDocsStat['percentage']> =
degradedDocStats.reduce(
(degradedMapAcc, { dataset, percentage }) =>
Object.assign(degradedMapAcc, { [dataset]: percentage }),
{}
);
const degradedMap: Record<
DegradedDocsStat['dataset'],
{
percentage: DegradedDocsStat['percentage'];
count: DegradedDocsStat['count'];
}
> = degradedDocStats.reduce(
(degradedMapAcc, { dataset, percentage, count }) =>
Object.assign(degradedMapAcc, { [dataset]: { percentage, count } }),
{}
);

return dataStreamStats?.map((dataStream) => ({
...dataStream,
degradedDocs: degradedMap[dataStream.rawName],
degradedDocs: degradedMap[dataStream.rawName] || dataStream.degradedDocs,
}));
}
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ export async function getDegradedDocsPaginated(options: {
response.aggregations?.datasets.buckets.map((bucket) => ({
dataset: `${type}-${bucket.key.dataset}-${bucket.key.namespace}`,
percentage: (bucket.degraded.doc_count * 100) / bucket.doc_count,
count: bucket.degraded.doc_count,
})) ?? [];

const degradedDocs = [...prevResults, ...currDegradedDocs];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,16 +70,25 @@ export default function ApiTest({ getService }: FtrProviderContext) {
const stats = await callApiAs('datasetQualityLogsUser');
expect(stats.body.degradedDocs.length).to.be(2);

const percentages = stats.body.degradedDocs.reduce(
const degradedDocsStats = stats.body.degradedDocs.reduce(
(acc, curr) => ({
...acc,
[curr.dataset]: curr.percentage,
[curr.dataset]: {
percentage: curr.percentage,
count: curr.count,
},
}),
{} as Record<string, number>
{} as Record<string, { percentage: number; count: number }>
);

expect(percentages['logs-synth.1-default']).to.be(0);
expect(percentages['logs-synth.2-default']).to.be(100);
expect(degradedDocsStats['logs-synth.1-default']).to.eql({
percentage: 0,
count: 0,
});
expect(degradedDocsStats['logs-synth.2-default']).to.eql({
percentage: 100,
count: 1,
});
});

after(async () => {
Expand Down

0 comments on commit cfd1961

Please sign in to comment.