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

[Dataset quality] Enable page for metrics and traces #190043

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
8f8db0e
Integrations are not tied anymore to type
yngrdyn Aug 5, 2024
7513c79
Fetching data per dataStreamType
yngrdyn Aug 6, 2024
81a94c3
Updating states
yngrdyn Aug 6, 2024
8eb15a7
Not allowing users to uncheck all types
yngrdyn Aug 6, 2024
3e4b1d5
When no type is selected we show all datastreams in all types
yngrdyn Aug 7, 2024
7d394e5
logs explorer vs discover
yngrdyn Aug 7, 2024
49e9484
Adding types to url in data quality
yngrdyn Aug 7, 2024
4b796e2
fixing tests
yngrdyn Aug 8, 2024
ff533d4
fixing tests
yngrdyn Aug 8, 2024
3f9fb63
Merge remote-tracking branch 'origin/main' into 3454-dataset-quality-…
yngrdyn Aug 19, 2024
6a62ecc
Merge branch 'main' into 3454-dataset-quality-enable-pages-for-metric…
yngrdyn Aug 19, 2024
2780763
update translations
yngrdyn Aug 19, 2024
083074e
fixing types
yngrdyn Aug 19, 2024
a295e95
Integrations endpoint doesn't discriminate by type anymore
yngrdyn Aug 20, 2024
f040b0b
updating access to plugin
yngrdyn Aug 20, 2024
2c3a2e5
Merge branch 'main' into 3454-dataset-quality-enable-pages-for-metric…
yngrdyn Aug 20, 2024
f50a34b
Fixing PR comments
yngrdyn Aug 21, 2024
fbcec23
Getting all types for datastreamstats
yngrdyn Aug 22, 2024
ae42b56
using a single request for nonAggregatableDatasets
yngrdyn Aug 22, 2024
81d9e43
Merge remote-tracking branch 'origin/main' into 3454-dataset-quality-…
yngrdyn Aug 22, 2024
24edfcf
[CI] Auto-commit changed files from 'node scripts/lint_ts_projects --…
kibanamachine Aug 22, 2024
60a3c7b
fix build
yngrdyn Aug 22, 2024
e177c64
Merge branch '3454-dataset-quality-enable-pages-for-metrics-and-trace…
yngrdyn Aug 22, 2024
88ceb50
Merge branch 'main' into 3454-dataset-quality-enable-pages-for-metric…
yngrdyn Aug 22, 2024
17fa51c
fixing build
yngrdyn Aug 23, 2024
88b44d5
Merge branch 'main' into 3454-dataset-quality-enable-pages-for-metric…
yngrdyn Aug 23, 2024
d9ab772
Merge branch 'main' into 3454-dataset-quality-enable-pages-for-metric…
yngrdyn Aug 26, 2024
7a92cc4
fixing build
yngrdyn Aug 27, 2024
59a69da
Merge branch '3454-dataset-quality-enable-pages-for-metrics-and-trace…
yngrdyn Aug 27, 2024
21d53e6
Merge remote-tracking branch 'origin/main' into 3454-dataset-quality-…
yngrdyn Aug 27, 2024
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 @@ -13,6 +13,7 @@ export const filtersRT = rt.exact(
inactive: rt.boolean,
fullNames: rt.boolean,
timeRange: timeRangeRT,
types: rt.array(rt.string),
integrations: rt.array(rt.string),
namespaces: rt.array(rt.string),
qualities: rt.array(rt.union([rt.literal('poor'), rt.literal('degraded'), rt.literal('good')])),
Expand Down
14 changes: 14 additions & 0 deletions x-pack/plugins/data_quality/server/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,20 @@ export class DataQualityPlugin implements Plugin<void, void, any, any> {
['logs-*-*']: ['read'],
},
},
{
ui: [],
requiredClusterPrivileges: [],
requiredIndexPrivileges: {
['traces-*-*']: ['read'],
},
},
{
ui: [],
requiredClusterPrivileges: [],
requiredIndexPrivileges: {
['metrics-*-*']: ['read'],
},
},
],
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@
* 2.0.
*/

import { QualityIndicators } from './types';
import { DataStreamType, QualityIndicators } from './types';

export const DATASET_QUALITY_APP_ID = 'dataset_quality';
export const DEFAULT_DATASET_TYPE = 'logs';
export const DEFAULT_DATASET_TYPE: DataStreamType = 'logs';
export const DEFAULT_LOGS_DATA_VIEW = 'logs-*-*';

export const POOR_QUALITY_MINIMUM_PERCENTAGE = 3;
Expand Down Expand Up @@ -41,3 +41,5 @@ export const MAX_DEGRADED_FIELDS = 1000;

export const MASKED_FIELD_PLACEHOLDER = '<custom field>';
export const UNKOWN_FIELD_PLACEHOLDER = '<unkwon>';

export const KNOWN_TYPES: DataStreamType[] = ['logs', 'metrics', 'traces'];
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,6 @@
* 2.0.
*/

import { DataStreamType } from '../types';

export interface GetDataStreamIntegrationParams {
type: DataStreamType;
integrationName: string;
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,6 @@ export type GetDataStreamsStatsResponse =
export type DataStreamStatType = GetDataStreamsStatsResponse['dataStreamsStats'][0];
export type DataStreamStatServiceResponse = GetDataStreamsStatsResponse;

export type GetIntegrationsParams =
yngrdyn marked this conversation as resolved.
Show resolved Hide resolved
APIClientRequestParamsOf<`GET /internal/dataset_quality/integrations`>['params'];

export type GetDataStreamsDegradedDocsStatsParams =
APIClientRequestParamsOf<`GET /internal/dataset_quality/data_streams/degraded_docs`>['params'];
export type GetDataStreamsDegradedDocsStatsQuery = GetDataStreamsDegradedDocsStatsParams['query'];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,33 @@ import { EuiSuperDatePicker } from '@elastic/eui';
import { UI_SETTINGS } from '@kbn/data-service';
import { TimePickerQuickRange } from '@kbn/observability-shared-plugin/public/hooks/use_quick_time_ranges';
import React, { useMemo } from 'react';
import { i18n } from '@kbn/i18n';
import { useDatasetQualityFilters } from '../../../hooks/use_dataset_quality_filters';
import { useKibanaContextForPlugin } from '../../../utils/use_kibana';
import { FilterBar } from './filter_bar';
import { IntegrationsSelector } from './integrations_selector';
import { NamespacesSelector } from './namespaces_selector';
import { QualitiesSelector } from './qualities_selector';
import { Selector } from './selector';

const typesLabel = i18n.translate('xpack.datasetQuality.types.label', {
defaultMessage: 'Types',
});

const typesSearchPlaceholder = i18n.translate(
'xpack.datasetQuality.selector.types.search.placeholder',
{
defaultMessage: 'Filter types',
}
);

const typesNoneMatching = i18n.translate('xpack.datasetQuality.selector.types.noneMatching', {
defaultMessage: 'No types found',
});

const typesNoneAvailable = i18n.translate('xpack.datasetQuality.selector.types.noneAvailable', {
defaultMessage: 'No types available',
});

// Allow for lazy loading
// eslint-disable-next-line import/no-default-export
Expand All @@ -29,9 +50,11 @@ export default function Filters() {
integrations,
namespaces,
qualities,
types,
onIntegrationsChange,
onNamespacesChange,
onQualitiesChange,
onTypesChange,
selectedQuery,
onQueryChange,
} = useDatasetQualityFilters();
Expand Down Expand Up @@ -65,6 +88,14 @@ export default function Filters() {
integrations={integrations}
onIntegrationsChange={onIntegrationsChange}
/>
<Selector
label={typesLabel}
searchPlaceholder={typesSearchPlaceholder}
noneMatchingMessage={typesNoneMatching}
noneAvailableMessage={typesNoneAvailable}
options={types}
onOptionsChange={onTypesChange}
/>
<NamespacesSelector
isLoading={isLoading}
namespaces={namespaces}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import { EuiFilterButton, EuiPopover, EuiPopoverTitle, EuiSelectable, EuiText } from '@elastic/eui';
import React, { useState } from 'react';
import type { EuiSelectableOptionCheckedType } from '@elastic/eui/src/components/selectable/selectable_option';
import { i18n } from '@kbn/i18n';

const selectorLoading = i18n.translate('xpack.datasetQuality.selector.loading', {
defaultMessage: 'Loading',
});

interface SelectorProps {
isLoading?: boolean;
options: Item[];
loadingMessage?: string;
label: string;
searchPlaceholder: string;
noneAvailableMessage: string;
noneMatchingMessage: string;
onOptionsChange: (options: Item[]) => void;
}

export interface Item {
label: string;
checked?: EuiSelectableOptionCheckedType;
}

export function Selector({
isLoading,
options,
loadingMessage,
label,
searchPlaceholder,
noneAvailableMessage,
noneMatchingMessage,
onOptionsChange,
}: SelectorProps) {
const [isPopoverOpen, setIsPopoverOpen] = useState(false);

const onButtonClick = () => {
setIsPopoverOpen(!isPopoverOpen);
};

const closePopover = () => {
setIsPopoverOpen(false);
};

const renderOption = (option: Item) => <EuiText size="s">{option.label}</EuiText>;

const button = (
<EuiFilterButton
data-test-subj="datasetQualitySelectableButton"
iconType="arrowDown"
badgeColor="success"
onClick={onButtonClick}
isSelected={isPopoverOpen}
numFilters={options.length}
hasActiveFilters={!!options.find((item) => item.checked === 'on')}
numActiveFilters={options.filter((item) => item.checked === 'on').length}
>
{label}
</EuiFilterButton>
);

return (
<EuiPopover
button={button}
isOpen={isPopoverOpen}
closePopover={closePopover}
panelPaddingSize="none"
>
<EuiSelectable
data-test-subj="datasetQualitySelectableOptions"
searchable
searchProps={{
placeholder: searchPlaceholder,
compressed: true,
}}
aria-label={label}
options={options}
onChange={onOptionsChange}
isLoading={isLoading}
loadingMessage={loadingMessage ?? selectorLoading}
emptyMessage={noneAvailableMessage}
noMatchesMessage={noneMatchingMessage}
renderOption={(option) => renderOption(option)}
>
{(list, search) => (
<div style={{ width: 300 }}>
<EuiPopoverTitle paddingSize="s">{search}</EuiPopoverTitle>
{list}
</div>
)}
</EuiSelectable>
</EuiPopover>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { EuiBetaBadge, EuiLink, EuiPageHeader, EuiCode } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n-react';

import { DEFAULT_LOGS_DATA_VIEW } from '../../../common/constants';
import { KNOWN_TYPES } from '../../../common/constants';
import { datasetQualityAppTitle } from '../../../common/translations';

// Allow for lazy loading
Expand All @@ -33,9 +33,16 @@ export default function Header() {
description={
<FormattedMessage
id="xpack.datasetQuality.appDescription"
defaultMessage="Monitor the data set quality for {logsPattern} data streams that follow the {dsNamingSchemeLink}."
defaultMessage="Monitor the data set quality for {types} data streams that follow the {dsNamingSchemeLink}."
values={{
logsPattern: <EuiCode>{DEFAULT_LOGS_DATA_VIEW}</EuiCode>,
types: KNOWN_TYPES.map((type, index) => {
return (
<>
{index > 0 && ', '}
<EuiCode>{type}</EuiCode>
</>
);
}),
dsNamingSchemeLink: (
<EuiLink
data-test-subj="datasetQualityAppDescriptionDsNamingSchemeLink"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ const namespaceColumnName = i18n.translate('xpack.datasetQuality.namespaceColumn
defaultMessage: 'Namespace',
});

const typeColumnName = i18n.translate('xpack.datasetQuality.typeColumnName', {
defaultMessage: 'Type',
});

const sizeColumnName = i18n.translate('xpack.datasetQuality.sizeColumnName', {
defaultMessage: 'Size',
});
Expand Down Expand Up @@ -213,6 +217,15 @@ export const getDatasetQualityTableColumns = ({
),
width: '160px',
},
{
name: typeColumnName,
field: 'type',
sortable: true,
render: (_, dataStreamStat: DataStreamStat) => (
<EuiBadge color="hollow">{dataStreamStat.type}</EuiBadge>
),
width: '160px',
},
...(isSizeStatsAvailable && canUserMonitorDataset && canUserMonitorAnyDataStream
? [
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
*/

import React, { useCallback, useEffect, useState } from 'react';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n-react';
import {
EuiAccordion,
Expand Down Expand Up @@ -133,7 +134,10 @@ export default function DegradedDocs({ lastReloadTime }: { lastReloadTime: numbe
<EuiButtonIcon
display="base"
iconType="discoverApp"
aria-label="Discover"
aria-label={i18n.translate(
'xpack.datasetQuality.degradedDocs.euiButtonIcon.discoverLabel',
{ defaultMessage: 'Discover' }
)}
size="s"
data-test-subj="datasetQualityDetailsLinkToDiscover"
{...degradedDocLinkLogsExplorer.linkProps}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@
import { OnRefreshChangeProps } from '@elastic/eui';
import { useSelector } from '@xstate/react';
import { useCallback, useMemo } from 'react';
import { QualityIndicators } from '../../common/types';
import { KNOWN_TYPES } from '../../common/constants';
import { DataStreamType, QualityIndicators } from '../../common/types';
import { Integration } from '../../common/data_streams_stats/integration';
import { useDatasetQualityContext } from '../components/dataset_quality/context';
import { IntegrationItem } from '../components/dataset_quality/filters/integrations_selector';
import { NamespaceItem } from '../components/dataset_quality/filters/namespaces_selector';
import { QualityItem } from '../components/dataset_quality/filters/qualities_selector';
import { Item } from '../components/dataset_quality/filters/selector';

export const useDatasetQualityFilters = () => {
const { service } = useDatasetQualityContext();
Expand All @@ -22,13 +24,14 @@ export const useDatasetQualityFilters = () => {
service,
(state) =>
state.matches('integrations.fetching') &&
(state.matches('datasets.fetching') || state.matches('degradedDocs.fetching'))
(state.matches('stats.datasets.fetching') || state.matches('stats.degradedDocs.fetching'))
);

const {
timeRange,
integrations: selectedIntegrations,
namespaces: selectedNamespaces,
types: selectedTypes,
qualities: selectedQualities,
query: selectedQuery,
} = useSelector(service, (state) => state.context.filters);
Expand Down Expand Up @@ -169,6 +172,25 @@ export const useDatasetQualityFilters = () => {
[service]
);

const typeItems: Item[] = useMemo(() => {
return KNOWN_TYPES.map((type) => ({
label: type,
checked: selectedTypes.includes(type) ? 'on' : undefined,
}));
}, [selectedTypes]);

const onTypesChange = useCallback(
(newTypeItems: Item[]) => {
service.send({
type: 'UPDATE_TYPES',
types: newTypeItems
.filter((quality) => quality.checked === 'on')
.map((type) => type.label as DataStreamType),
});
},
[service]
);

const onQueryChange = useCallback(
(query: string) => {
service.send({
Expand All @@ -187,9 +209,11 @@ export const useDatasetQualityFilters = () => {
integrations: integrationItems,
namespaces: namespaceItems,
qualities: qualityItems,
types: typeItems,
onIntegrationsChange,
onNamespacesChange,
onQualitiesChange,
onTypesChange,
isLoading,
selectedQuery,
onQueryChange,
Expand Down
Loading