Skip to content

Commit 54d58ac

Browse files
authored
[8.x] [Synthetics] Added drilldown to synthetics stats overview embeddable (elastic#217688) (elastic#218387)
# Backport This will backport the following commits from `main` to `8.x`: - [[Synthetics] Added drilldown to synthetics stats overview embeddable (elastic#217688)](elastic#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":"[email protected]"},"sourceCommit":{"committedDate":"2025-04-16T07:52:16Z","message":"[Synthetics] Added drilldown to synthetics stats overview embeddable (elastic#217688)\n\nThis PR closes elastic#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 (elastic#217688)\n\nThis PR closes elastic#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 (elastic#217688)\n\nThis PR closes elastic#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-->
1 parent 6458959 commit 54d58ac

File tree

6 files changed

+175
-49
lines changed

6 files changed

+175
-49
lines changed

x-pack/solutions/observability/plugins/synthetics/kibana.jsonc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,8 @@
5656
"spaces",
5757
"telemetry",
5858
"licenseManagement",
59-
"observabilityAIAssistant"
59+
"observabilityAIAssistant",
60+
"embeddableEnhanced",
6061
],
6162
"requiredBundles": [
6263
"data",

x-pack/solutions/observability/plugins/synthetics/public/apps/embeddables/stats_overview/stats_overview_component.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ const WithFiltersComponent = ({ filters }: { filters: MonitorFilters }) => {
6262
<OverviewStatus
6363
titleAppend={hasFilters ? <ShowSelectedFilters filters={filters ?? {}} /> : null}
6464
hideTitle={true}
65+
areStatsClickable
6566
/>
6667
);
6768
};

x-pack/solutions/observability/plugins/synthetics/public/apps/embeddables/stats_overview/stats_overview_embeddable_factory.tsx

Lines changed: 70 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,16 @@ import {
1717
PublishesTitle,
1818
SerializedTitles,
1919
HasEditCapabilities,
20+
getUnchangingComparator,
21+
HasSupportedTriggers,
2022
} from '@kbn/presentation-publishing';
2123
import { BehaviorSubject, Subject } from 'rxjs';
2224
import type { StartServicesAccessor } from '@kbn/core-lifecycle-browser';
25+
import {
26+
DynamicActionsSerializedState,
27+
ReactEmbeddableDynamicActionsApi,
28+
} from '@kbn/embeddable-enhanced-plugin/public/plugin';
29+
import { HasDynamicActions } from '@kbn/embeddable-enhanced-plugin/public';
2330
import { MonitorFilters } from '../monitors_overview/types';
2431
import { SYNTHETICS_STATS_OVERVIEW_EMBEDDABLE } from '../constants';
2532
import { ClientPluginsStart } from '../../../plugin';
@@ -31,14 +38,50 @@ export const getOverviewPanelTitle = () =>
3138
defaultMessage: 'Synthetics Stats Overview',
3239
});
3340

34-
export type OverviewEmbeddableState = SerializedTitles & {
35-
filters: MonitorFilters;
36-
};
41+
export type OverviewEmbeddableState = SerializedTitles &
42+
DynamicActionsSerializedState & {
43+
filters: MonitorFilters;
44+
};
3745

3846
export type StatsOverviewApi = DefaultEmbeddableApi<OverviewEmbeddableState> &
3947
PublishesWritableTitle &
4048
PublishesTitle &
41-
HasEditCapabilities;
49+
HasEditCapabilities &
50+
HasDynamicActions &
51+
HasSupportedTriggers;
52+
53+
type DynamicActionsData = {
54+
serializedDynamicActions: DynamicActionsSerializedState;
55+
stopDynamicActions?: () => void;
56+
} & Pick<ReactEmbeddableDynamicActionsApi, 'dynamicActionsApi' | 'dynamicActionsComparator'>;
57+
58+
const getDynamicActionsData = (
59+
extractor?: () => ReactEmbeddableDynamicActionsApi
60+
): DynamicActionsData => {
61+
if (extractor) {
62+
const {
63+
serializeDynamicActions,
64+
startDynamicActions,
65+
dynamicActionsApi,
66+
dynamicActionsComparator,
67+
} = extractor();
68+
return {
69+
serializedDynamicActions: serializeDynamicActions(),
70+
stopDynamicActions: startDynamicActions().stopDynamicActions,
71+
dynamicActionsApi,
72+
dynamicActionsComparator,
73+
};
74+
}
75+
76+
return {
77+
serializedDynamicActions: {},
78+
stopDynamicActions: undefined,
79+
dynamicActionsApi: {},
80+
dynamicActionsComparator: {
81+
enhancements: getUnchangingComparator(),
82+
},
83+
};
84+
};
4285

4386
export const getStatsOverviewEmbeddableFactory = (
4487
getStartServices: StartServicesAccessor<ClientPluginsStart>
@@ -52,17 +95,36 @@ export const getStatsOverviewEmbeddableFactory = (
5295
deserializeState: (state) => {
5396
return state.rawState as OverviewEmbeddableState;
5497
},
55-
buildEmbeddable: async (state, buildApi, uuid, parentApi) => {
98+
buildEmbeddable: async (state, buildApi, uuid) => {
5699
const [coreStart, pluginStart] = await getStartServices();
57100

58101
const titleManager = initializeTitleManager(state);
59102
const defaultTitle$ = new BehaviorSubject<string | undefined>(getOverviewPanelTitle());
60103
const reload$ = new Subject<boolean>();
61104
const filters$ = new BehaviorSubject(state.filters);
62105

106+
const { embeddableEnhanced } = pluginStart;
107+
const {
108+
dynamicActionsApi,
109+
dynamicActionsComparator,
110+
serializedDynamicActions,
111+
stopDynamicActions,
112+
} = getDynamicActionsData(
113+
embeddableEnhanced
114+
? () =>
115+
embeddableEnhanced.initializeReactEmbeddableDynamicActions(
116+
uuid,
117+
() => titleManager.api.title$.getValue(),
118+
state
119+
)
120+
: undefined
121+
);
122+
63123
const api = buildApi(
64124
{
65125
...titleManager.api,
126+
...dynamicActionsApi,
127+
supportedTriggers: () => [],
66128
defaultTitle$,
67129
getTypeDisplayName: () =>
68130
i18n.translate('xpack.synthetics.editSloOverviewEmbeddableTitle.typeDisplayName', {
@@ -92,13 +154,15 @@ export const getStatsOverviewEmbeddableFactory = (
92154
rawState: {
93155
...titleManager.serialize(),
94156
filters: filters$.getValue(),
157+
...serializedDynamicActions,
95158
},
96159
};
97160
},
98161
},
99162
{
100163
...titleManager.comparators,
101164
filters: [filters$, (value) => filters$.next(value)],
165+
...dynamicActionsComparator,
102166
}
103167
);
104168

@@ -116,6 +180,7 @@ export const getStatsOverviewEmbeddableFactory = (
116180
useEffect(() => {
117181
return () => {
118182
fetchSubscription.unsubscribe();
183+
if (stopDynamicActions) stopDynamicActions();
119184
};
120185
}, []);
121186
return (

x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/overview_status.tsx

Lines changed: 99 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -5,28 +5,69 @@
55
* 2.0.
66
*/
77

8-
import { EuiFlexGroup, EuiFlexItem, EuiStat } from '@elastic/eui';
8+
import { EuiButtonEmpty, EuiFlexGroup, EuiFlexItem, EuiStat } from '@elastic/eui';
99
import { i18n } from '@kbn/i18n';
10-
import React, { useEffect, useState } from 'react';
10+
import React, { useCallback, useEffect, useMemo, useState } from 'react';
1111
import { useDispatch } from 'react-redux';
12+
import { useKibana } from '@kbn/kibana-react-plugin/public';
1213
import { EmbeddablePanelWrapper } from '../../../common/components/embeddable_panel_wrapper';
1314
import { clearOverviewStatusErrorAction } from '../../../../state/overview_status';
1415
import { kibanaService } from '../../../../../../utils/kibana_service';
1516
import { useGetUrlParams } from '../../../../hooks/use_url_params';
1617
import { useOverviewStatus } from '../../hooks/use_overview_status';
18+
import { PLUGIN } from '../../../../../../../common/constants/plugin';
1719

1820
function title(t?: number) {
1921
return t ?? '-';
2022
}
2123

24+
interface MonitorStatProps {
25+
dataTestSubj: string;
26+
statName: string;
27+
statNo: number | '-';
28+
numberColor: string;
29+
isClickable: boolean;
30+
onClickStat: () => void;
31+
}
32+
33+
const MonitorStat = ({
34+
dataTestSubj,
35+
statName,
36+
statNo,
37+
numberColor,
38+
isClickable,
39+
onClickStat,
40+
}: MonitorStatProps) => {
41+
const statComponent = (
42+
<EuiStat
43+
data-test-subj={dataTestSubj}
44+
description={statName}
45+
reverse
46+
title={statNo}
47+
titleColor={numberColor}
48+
titleSize="m"
49+
/>
50+
);
51+
return isClickable ? (
52+
<EuiButtonEmpty data-test-subj={`${dataTestSubj}Btn`} onClick={onClickStat}>
53+
{statComponent}
54+
</EuiButtonEmpty>
55+
) : (
56+
statComponent
57+
);
58+
};
59+
2260
export function OverviewStatus({
2361
titleAppend,
2462
hideTitle,
63+
areStatsClickable = false,
2564
}: {
2665
titleAppend?: React.ReactNode;
2766
hideTitle?: boolean;
67+
areStatsClickable?: boolean;
2868
}) {
2969
const { statusFilter } = useGetUrlParams();
70+
const { application } = useKibana().services;
3071

3172
const {
3273
status,
@@ -97,6 +138,58 @@ export function OverviewStatus({
97138
}
98139
}, [status, statusFilter]);
99140

141+
const getOnClickStat = useCallback(
142+
(statusFilterName: string) => {
143+
return () => {
144+
application?.navigateToApp(PLUGIN.SYNTHETICS_PLUGIN_ID, {
145+
path: `?statusFilter=${statusFilterName}`,
146+
});
147+
};
148+
},
149+
[application]
150+
);
151+
152+
const monitorStatData = useMemo(() => {
153+
const stats: MonitorStatProps[] = [
154+
{
155+
dataTestSubj: 'syntheticsOverviewUp',
156+
statName: upDescription,
157+
statNo: title(statusConfig?.up),
158+
numberColor: 'success',
159+
isClickable: areStatsClickable,
160+
onClickStat: getOnClickStat('up'),
161+
},
162+
{
163+
dataTestSubj: 'syntheticsOverviewDown',
164+
statName: downDescription,
165+
statNo: title(statusConfig?.down),
166+
numberColor: 'danger',
167+
isClickable: areStatsClickable,
168+
onClickStat: getOnClickStat('down'),
169+
},
170+
{
171+
dataTestSubj: 'xpack.uptime.synthetics.overview.status.disabled',
172+
statName: disabledDescription,
173+
statNo: title(statusConfig?.disabledCount),
174+
numberColor: 'subdued',
175+
isClickable: areStatsClickable,
176+
onClickStat: getOnClickStat('disabled'),
177+
},
178+
];
179+
180+
if (statusConfig?.pending) {
181+
stats.push({
182+
dataTestSubj: 'xpack.uptime.synthetics.overview.status.pending',
183+
statName: pendingDescription,
184+
statNo: title(statusConfig.pending),
185+
numberColor: 'subdued',
186+
isClickable: areStatsClickable,
187+
onClickStat: getOnClickStat('pending'),
188+
});
189+
}
190+
return stats;
191+
}, [areStatsClickable, getOnClickStat, statusConfig]);
192+
100193
return (
101194
<EmbeddablePanelWrapper
102195
title={headingText}
@@ -105,48 +198,11 @@ export function OverviewStatus({
105198
hideTitle={hideTitle}
106199
>
107200
<EuiFlexGroup gutterSize="xl" justifyContent="spaceAround">
108-
<EuiFlexItem grow={false}>
109-
<EuiStat
110-
data-test-subj="syntheticsOverviewUp"
111-
description={upDescription}
112-
reverse
113-
title={title(statusConfig?.up)}
114-
titleColor="success"
115-
titleSize="m"
116-
/>
117-
</EuiFlexItem>
118-
<EuiFlexItem grow={false}>
119-
<EuiStat
120-
data-test-subj="syntheticsOverviewDown"
121-
description={downDescription}
122-
reverse
123-
title={title(statusConfig?.down)}
124-
titleColor="danger"
125-
titleSize="m"
126-
/>
127-
</EuiFlexItem>
128-
<EuiFlexItem grow={false}>
129-
<EuiStat
130-
data-test-subj="xpack.uptime.synthetics.overview.status.disabled"
131-
description={disabledDescription}
132-
reverse
133-
title={title(statusConfig?.disabledCount)}
134-
titleColor="subdued"
135-
titleSize="m"
136-
/>
137-
</EuiFlexItem>
138-
{(statusConfig?.pending || 0) > 0 && (
139-
<EuiFlexItem grow={false}>
140-
<EuiStat
141-
data-test-subj="xpack.uptime.synthetics.overview.status.pending"
142-
description={pendingDescription}
143-
reverse
144-
title={title(statusConfig?.pending)}
145-
titleColor="subdued"
146-
titleSize="m"
147-
/>
201+
{monitorStatData.map((props) => (
202+
<EuiFlexItem grow={false} key={props.dataTestSubj}>
203+
<MonitorStat {...props} />
148204
</EuiFlexItem>
149-
)}
205+
))}
150206
</EuiFlexGroup>
151207
</EmbeddablePanelWrapper>
152208
);

x-pack/solutions/observability/plugins/synthetics/public/plugin.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ import { DashboardStart } from '@kbn/dashboard-plugin/public';
6363
import { SLOPublicStart } from '@kbn/slo-plugin/public';
6464
import type { ChartsPluginStart } from '@kbn/charts-plugin/public';
6565
import { FieldsMetadataPublicStart } from '@kbn/fields-metadata-plugin/public';
66+
import { EmbeddableEnhancedPluginStart } from '@kbn/embeddable-enhanced-plugin/public';
6667
import { registerSyntheticsEmbeddables } from './apps/embeddables/register_embeddables';
6768
import { kibanaService } from './utils/kibana_service';
6869
import { PLUGIN } from '../common/constants/plugin';
@@ -97,6 +98,7 @@ export interface ClientPluginsStart {
9798
discover: DiscoverStart;
9899
inspector: InspectorPluginStart;
99100
embeddable: EmbeddableStart;
101+
embeddableEnhanced?: EmbeddableEnhancedPluginStart;
100102
exploratoryView: ExploratoryViewPublicStart;
101103
observability: ObservabilityPublicStart;
102104
observabilityShared: ObservabilitySharedPluginStart;

x-pack/solutions/observability/plugins/synthetics/tsconfig.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
"@kbn/discover-plugin",
2828
"@kbn/home-plugin",
2929
"@kbn/embeddable-plugin",
30+
"@kbn/embeddable-enhanced-plugin",
3031
"@kbn/data-plugin",
3132
"@kbn/kibana-utils-plugin",
3233
"@kbn/inspector-plugin",

0 commit comments

Comments
 (0)