mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
# Backport This will backport the following commits from `main` to `8.x`: - [[Synthetics] Added drilldown to synthetics stats overview embeddable (#217688)](https://github.com/elastic/kibana/pull/217688) <!--- Backport version: 9.6.6 --> ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sorenlouv/backport) <!--BACKPORT [{"author":{"name":"Francesco Fagnani","email":"fagnani.francesco@gmail.com"},"sourceCommit":{"committedDate":"2025-04-16T07:52:16Z","message":"[Synthetics] Added drilldown to synthetics stats overview embeddable (#217688)\n\nThis PR closes #208066 by adding drilldowns to the synthetics stats\noverview embeddable.\n\n\n\nhttps://github.com/user-attachments/assets/fe8d9eb0-ecdc-449d-93af-7d165c541d46","sha":"ec88cca373b879b265df08965a9a590a7dc65217","branchLabelMapping":{"^v9.1.0$":"main","^v8.19.0$":"8.x","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:feature","Team:obs-ux-management","backport:version","v9.1.0","v8.19.0"],"title":"[Synthetics] Added drilldown to synthetics stats overview embeddable","number":217688,"url":"https://github.com/elastic/kibana/pull/217688","mergeCommit":{"message":"[Synthetics] Added drilldown to synthetics stats overview embeddable (#217688)\n\nThis PR closes #208066 by adding drilldowns to the synthetics stats\noverview embeddable.\n\n\n\nhttps://github.com/user-attachments/assets/fe8d9eb0-ecdc-449d-93af-7d165c541d46","sha":"ec88cca373b879b265df08965a9a590a7dc65217"}},"sourceBranch":"main","suggestedTargetBranches":["8.x"],"targetPullRequestStates":[{"branch":"main","label":"v9.1.0","branchLabelMappingKey":"^v9.1.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/217688","number":217688,"mergeCommit":{"message":"[Synthetics] Added drilldown to synthetics stats overview embeddable (#217688)\n\nThis PR closes #208066 by adding drilldowns to the synthetics stats\noverview embeddable.\n\n\n\nhttps://github.com/user-attachments/assets/fe8d9eb0-ecdc-449d-93af-7d165c541d46","sha":"ec88cca373b879b265df08965a9a590a7dc65217"}},{"branch":"8.x","label":"v8.19.0","branchLabelMappingKey":"^v8.19.0$","isSourceBranch":false,"state":"NOT_CREATED"}]}] BACKPORT-->
This commit is contained in:
parent
6458959c21
commit
54d58acf36
6 changed files with 175 additions and 49 deletions
|
@ -56,7 +56,8 @@
|
|||
"spaces",
|
||||
"telemetry",
|
||||
"licenseManagement",
|
||||
"observabilityAIAssistant"
|
||||
"observabilityAIAssistant",
|
||||
"embeddableEnhanced",
|
||||
],
|
||||
"requiredBundles": [
|
||||
"data",
|
||||
|
|
|
@ -62,6 +62,7 @@ const WithFiltersComponent = ({ filters }: { filters: MonitorFilters }) => {
|
|||
<OverviewStatus
|
||||
titleAppend={hasFilters ? <ShowSelectedFilters filters={filters ?? {}} /> : null}
|
||||
hideTitle={true}
|
||||
areStatsClickable
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -17,9 +17,16 @@ import {
|
|||
PublishesTitle,
|
||||
SerializedTitles,
|
||||
HasEditCapabilities,
|
||||
getUnchangingComparator,
|
||||
HasSupportedTriggers,
|
||||
} from '@kbn/presentation-publishing';
|
||||
import { BehaviorSubject, Subject } from 'rxjs';
|
||||
import type { StartServicesAccessor } from '@kbn/core-lifecycle-browser';
|
||||
import {
|
||||
DynamicActionsSerializedState,
|
||||
ReactEmbeddableDynamicActionsApi,
|
||||
} from '@kbn/embeddable-enhanced-plugin/public/plugin';
|
||||
import { HasDynamicActions } from '@kbn/embeddable-enhanced-plugin/public';
|
||||
import { MonitorFilters } from '../monitors_overview/types';
|
||||
import { SYNTHETICS_STATS_OVERVIEW_EMBEDDABLE } from '../constants';
|
||||
import { ClientPluginsStart } from '../../../plugin';
|
||||
|
@ -31,14 +38,50 @@ export const getOverviewPanelTitle = () =>
|
|||
defaultMessage: 'Synthetics Stats Overview',
|
||||
});
|
||||
|
||||
export type OverviewEmbeddableState = SerializedTitles & {
|
||||
filters: MonitorFilters;
|
||||
};
|
||||
export type OverviewEmbeddableState = SerializedTitles &
|
||||
DynamicActionsSerializedState & {
|
||||
filters: MonitorFilters;
|
||||
};
|
||||
|
||||
export type StatsOverviewApi = DefaultEmbeddableApi<OverviewEmbeddableState> &
|
||||
PublishesWritableTitle &
|
||||
PublishesTitle &
|
||||
HasEditCapabilities;
|
||||
HasEditCapabilities &
|
||||
HasDynamicActions &
|
||||
HasSupportedTriggers;
|
||||
|
||||
type DynamicActionsData = {
|
||||
serializedDynamicActions: DynamicActionsSerializedState;
|
||||
stopDynamicActions?: () => void;
|
||||
} & Pick<ReactEmbeddableDynamicActionsApi, 'dynamicActionsApi' | 'dynamicActionsComparator'>;
|
||||
|
||||
const getDynamicActionsData = (
|
||||
extractor?: () => ReactEmbeddableDynamicActionsApi
|
||||
): DynamicActionsData => {
|
||||
if (extractor) {
|
||||
const {
|
||||
serializeDynamicActions,
|
||||
startDynamicActions,
|
||||
dynamicActionsApi,
|
||||
dynamicActionsComparator,
|
||||
} = extractor();
|
||||
return {
|
||||
serializedDynamicActions: serializeDynamicActions(),
|
||||
stopDynamicActions: startDynamicActions().stopDynamicActions,
|
||||
dynamicActionsApi,
|
||||
dynamicActionsComparator,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
serializedDynamicActions: {},
|
||||
stopDynamicActions: undefined,
|
||||
dynamicActionsApi: {},
|
||||
dynamicActionsComparator: {
|
||||
enhancements: getUnchangingComparator(),
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export const getStatsOverviewEmbeddableFactory = (
|
||||
getStartServices: StartServicesAccessor<ClientPluginsStart>
|
||||
|
@ -52,7 +95,7 @@ export const getStatsOverviewEmbeddableFactory = (
|
|||
deserializeState: (state) => {
|
||||
return state.rawState as OverviewEmbeddableState;
|
||||
},
|
||||
buildEmbeddable: async (state, buildApi, uuid, parentApi) => {
|
||||
buildEmbeddable: async (state, buildApi, uuid) => {
|
||||
const [coreStart, pluginStart] = await getStartServices();
|
||||
|
||||
const titleManager = initializeTitleManager(state);
|
||||
|
@ -60,9 +103,28 @@ export const getStatsOverviewEmbeddableFactory = (
|
|||
const reload$ = new Subject<boolean>();
|
||||
const filters$ = new BehaviorSubject(state.filters);
|
||||
|
||||
const { embeddableEnhanced } = pluginStart;
|
||||
const {
|
||||
dynamicActionsApi,
|
||||
dynamicActionsComparator,
|
||||
serializedDynamicActions,
|
||||
stopDynamicActions,
|
||||
} = getDynamicActionsData(
|
||||
embeddableEnhanced
|
||||
? () =>
|
||||
embeddableEnhanced.initializeReactEmbeddableDynamicActions(
|
||||
uuid,
|
||||
() => titleManager.api.title$.getValue(),
|
||||
state
|
||||
)
|
||||
: undefined
|
||||
);
|
||||
|
||||
const api = buildApi(
|
||||
{
|
||||
...titleManager.api,
|
||||
...dynamicActionsApi,
|
||||
supportedTriggers: () => [],
|
||||
defaultTitle$,
|
||||
getTypeDisplayName: () =>
|
||||
i18n.translate('xpack.synthetics.editSloOverviewEmbeddableTitle.typeDisplayName', {
|
||||
|
@ -92,6 +154,7 @@ export const getStatsOverviewEmbeddableFactory = (
|
|||
rawState: {
|
||||
...titleManager.serialize(),
|
||||
filters: filters$.getValue(),
|
||||
...serializedDynamicActions,
|
||||
},
|
||||
};
|
||||
},
|
||||
|
@ -99,6 +162,7 @@ export const getStatsOverviewEmbeddableFactory = (
|
|||
{
|
||||
...titleManager.comparators,
|
||||
filters: [filters$, (value) => filters$.next(value)],
|
||||
...dynamicActionsComparator,
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -116,6 +180,7 @@ export const getStatsOverviewEmbeddableFactory = (
|
|||
useEffect(() => {
|
||||
return () => {
|
||||
fetchSubscription.unsubscribe();
|
||||
if (stopDynamicActions) stopDynamicActions();
|
||||
};
|
||||
}, []);
|
||||
return (
|
||||
|
|
|
@ -5,28 +5,69 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { EuiFlexGroup, EuiFlexItem, EuiStat } from '@elastic/eui';
|
||||
import { EuiButtonEmpty, EuiFlexGroup, EuiFlexItem, EuiStat } from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import { useKibana } from '@kbn/kibana-react-plugin/public';
|
||||
import { EmbeddablePanelWrapper } from '../../../common/components/embeddable_panel_wrapper';
|
||||
import { clearOverviewStatusErrorAction } from '../../../../state/overview_status';
|
||||
import { kibanaService } from '../../../../../../utils/kibana_service';
|
||||
import { useGetUrlParams } from '../../../../hooks/use_url_params';
|
||||
import { useOverviewStatus } from '../../hooks/use_overview_status';
|
||||
import { PLUGIN } from '../../../../../../../common/constants/plugin';
|
||||
|
||||
function title(t?: number) {
|
||||
return t ?? '-';
|
||||
}
|
||||
|
||||
interface MonitorStatProps {
|
||||
dataTestSubj: string;
|
||||
statName: string;
|
||||
statNo: number | '-';
|
||||
numberColor: string;
|
||||
isClickable: boolean;
|
||||
onClickStat: () => void;
|
||||
}
|
||||
|
||||
const MonitorStat = ({
|
||||
dataTestSubj,
|
||||
statName,
|
||||
statNo,
|
||||
numberColor,
|
||||
isClickable,
|
||||
onClickStat,
|
||||
}: MonitorStatProps) => {
|
||||
const statComponent = (
|
||||
<EuiStat
|
||||
data-test-subj={dataTestSubj}
|
||||
description={statName}
|
||||
reverse
|
||||
title={statNo}
|
||||
titleColor={numberColor}
|
||||
titleSize="m"
|
||||
/>
|
||||
);
|
||||
return isClickable ? (
|
||||
<EuiButtonEmpty data-test-subj={`${dataTestSubj}Btn`} onClick={onClickStat}>
|
||||
{statComponent}
|
||||
</EuiButtonEmpty>
|
||||
) : (
|
||||
statComponent
|
||||
);
|
||||
};
|
||||
|
||||
export function OverviewStatus({
|
||||
titleAppend,
|
||||
hideTitle,
|
||||
areStatsClickable = false,
|
||||
}: {
|
||||
titleAppend?: React.ReactNode;
|
||||
hideTitle?: boolean;
|
||||
areStatsClickable?: boolean;
|
||||
}) {
|
||||
const { statusFilter } = useGetUrlParams();
|
||||
const { application } = useKibana().services;
|
||||
|
||||
const {
|
||||
status,
|
||||
|
@ -97,6 +138,58 @@ export function OverviewStatus({
|
|||
}
|
||||
}, [status, statusFilter]);
|
||||
|
||||
const getOnClickStat = useCallback(
|
||||
(statusFilterName: string) => {
|
||||
return () => {
|
||||
application?.navigateToApp(PLUGIN.SYNTHETICS_PLUGIN_ID, {
|
||||
path: `?statusFilter=${statusFilterName}`,
|
||||
});
|
||||
};
|
||||
},
|
||||
[application]
|
||||
);
|
||||
|
||||
const monitorStatData = useMemo(() => {
|
||||
const stats: MonitorStatProps[] = [
|
||||
{
|
||||
dataTestSubj: 'syntheticsOverviewUp',
|
||||
statName: upDescription,
|
||||
statNo: title(statusConfig?.up),
|
||||
numberColor: 'success',
|
||||
isClickable: areStatsClickable,
|
||||
onClickStat: getOnClickStat('up'),
|
||||
},
|
||||
{
|
||||
dataTestSubj: 'syntheticsOverviewDown',
|
||||
statName: downDescription,
|
||||
statNo: title(statusConfig?.down),
|
||||
numberColor: 'danger',
|
||||
isClickable: areStatsClickable,
|
||||
onClickStat: getOnClickStat('down'),
|
||||
},
|
||||
{
|
||||
dataTestSubj: 'xpack.uptime.synthetics.overview.status.disabled',
|
||||
statName: disabledDescription,
|
||||
statNo: title(statusConfig?.disabledCount),
|
||||
numberColor: 'subdued',
|
||||
isClickable: areStatsClickable,
|
||||
onClickStat: getOnClickStat('disabled'),
|
||||
},
|
||||
];
|
||||
|
||||
if (statusConfig?.pending) {
|
||||
stats.push({
|
||||
dataTestSubj: 'xpack.uptime.synthetics.overview.status.pending',
|
||||
statName: pendingDescription,
|
||||
statNo: title(statusConfig.pending),
|
||||
numberColor: 'subdued',
|
||||
isClickable: areStatsClickable,
|
||||
onClickStat: getOnClickStat('pending'),
|
||||
});
|
||||
}
|
||||
return stats;
|
||||
}, [areStatsClickable, getOnClickStat, statusConfig]);
|
||||
|
||||
return (
|
||||
<EmbeddablePanelWrapper
|
||||
title={headingText}
|
||||
|
@ -105,48 +198,11 @@ export function OverviewStatus({
|
|||
hideTitle={hideTitle}
|
||||
>
|
||||
<EuiFlexGroup gutterSize="xl" justifyContent="spaceAround">
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiStat
|
||||
data-test-subj="syntheticsOverviewUp"
|
||||
description={upDescription}
|
||||
reverse
|
||||
title={title(statusConfig?.up)}
|
||||
titleColor="success"
|
||||
titleSize="m"
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiStat
|
||||
data-test-subj="syntheticsOverviewDown"
|
||||
description={downDescription}
|
||||
reverse
|
||||
title={title(statusConfig?.down)}
|
||||
titleColor="danger"
|
||||
titleSize="m"
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiStat
|
||||
data-test-subj="xpack.uptime.synthetics.overview.status.disabled"
|
||||
description={disabledDescription}
|
||||
reverse
|
||||
title={title(statusConfig?.disabledCount)}
|
||||
titleColor="subdued"
|
||||
titleSize="m"
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
{(statusConfig?.pending || 0) > 0 && (
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiStat
|
||||
data-test-subj="xpack.uptime.synthetics.overview.status.pending"
|
||||
description={pendingDescription}
|
||||
reverse
|
||||
title={title(statusConfig?.pending)}
|
||||
titleColor="subdued"
|
||||
titleSize="m"
|
||||
/>
|
||||
{monitorStatData.map((props) => (
|
||||
<EuiFlexItem grow={false} key={props.dataTestSubj}>
|
||||
<MonitorStat {...props} />
|
||||
</EuiFlexItem>
|
||||
)}
|
||||
))}
|
||||
</EuiFlexGroup>
|
||||
</EmbeddablePanelWrapper>
|
||||
);
|
||||
|
|
|
@ -63,6 +63,7 @@ import { DashboardStart } from '@kbn/dashboard-plugin/public';
|
|||
import { SLOPublicStart } from '@kbn/slo-plugin/public';
|
||||
import type { ChartsPluginStart } from '@kbn/charts-plugin/public';
|
||||
import { FieldsMetadataPublicStart } from '@kbn/fields-metadata-plugin/public';
|
||||
import { EmbeddableEnhancedPluginStart } from '@kbn/embeddable-enhanced-plugin/public';
|
||||
import { registerSyntheticsEmbeddables } from './apps/embeddables/register_embeddables';
|
||||
import { kibanaService } from './utils/kibana_service';
|
||||
import { PLUGIN } from '../common/constants/plugin';
|
||||
|
@ -97,6 +98,7 @@ export interface ClientPluginsStart {
|
|||
discover: DiscoverStart;
|
||||
inspector: InspectorPluginStart;
|
||||
embeddable: EmbeddableStart;
|
||||
embeddableEnhanced?: EmbeddableEnhancedPluginStart;
|
||||
exploratoryView: ExploratoryViewPublicStart;
|
||||
observability: ObservabilityPublicStart;
|
||||
observabilityShared: ObservabilitySharedPluginStart;
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
"@kbn/discover-plugin",
|
||||
"@kbn/home-plugin",
|
||||
"@kbn/embeddable-plugin",
|
||||
"@kbn/embeddable-enhanced-plugin",
|
||||
"@kbn/data-plugin",
|
||||
"@kbn/kibana-utils-plugin",
|
||||
"@kbn/inspector-plugin",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue