mirror of
https://github.com/elastic/kibana.git
synced 2025-06-27 18:51:07 -04:00
[ML] AIOps: Additional props for Change Point embeddable (#167606)
This commit is contained in:
parent
ee1f448d64
commit
772739ab40
4 changed files with 67 additions and 20 deletions
|
@ -18,6 +18,7 @@ import { EuiLoadingChart } from '@elastic/eui';
|
||||||
import { EMBEDDABLE_CHANGE_POINT_CHART_TYPE } from '../../common/constants';
|
import { EMBEDDABLE_CHANGE_POINT_CHART_TYPE } from '../../common/constants';
|
||||||
import type { AiopsPluginStartDeps } from '../types';
|
import type { AiopsPluginStartDeps } from '../types';
|
||||||
import type { EmbeddableChangePointChartInput } from './embeddable_change_point_chart';
|
import type { EmbeddableChangePointChartInput } from './embeddable_change_point_chart';
|
||||||
|
import type { ChangePointAnnotation } from '../components/change_point_detection/change_point_detection_context';
|
||||||
|
|
||||||
export interface EmbeddableChangePointChartProps {
|
export interface EmbeddableChangePointChartProps {
|
||||||
dataViewId: string;
|
dataViewId: string;
|
||||||
|
@ -27,6 +28,18 @@ export interface EmbeddableChangePointChartProps {
|
||||||
splitField?: string;
|
splitField?: string;
|
||||||
partitions?: string[];
|
partitions?: string[];
|
||||||
maxSeriesToPlot?: number;
|
maxSeriesToPlot?: number;
|
||||||
|
/**
|
||||||
|
* Component to render if there are no change points found
|
||||||
|
*/
|
||||||
|
emptyState?: React.ReactElement;
|
||||||
|
/**
|
||||||
|
* Outputs the most recent change point data
|
||||||
|
*/
|
||||||
|
onChange?: (changePointData: ChangePointAnnotation[]) => void;
|
||||||
|
/**
|
||||||
|
* Last reload request time, can be used for manual reload
|
||||||
|
*/
|
||||||
|
lastReloadRequestTime?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getEmbeddableChangePointChart(core: CoreStart, plugins: AiopsPluginStartDeps) {
|
export function getEmbeddableChangePointChart(core: CoreStart, plugins: AiopsPluginStartDeps) {
|
||||||
|
|
|
@ -5,8 +5,9 @@
|
||||||
* 2.0.
|
* 2.0.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { type Observable } from 'rxjs';
|
import { BehaviorSubject, type Observable, combineLatest } from 'rxjs';
|
||||||
import React, { FC, useEffect, useMemo } from 'react';
|
import { map, distinctUntilChanged } from 'rxjs/operators';
|
||||||
|
import React, { FC, useEffect, useMemo, useState } from 'react';
|
||||||
import { useTimefilter } from '@kbn/ml-date-picker';
|
import { useTimefilter } from '@kbn/ml-date-picker';
|
||||||
import { css } from '@emotion/react';
|
import { css } from '@emotion/react';
|
||||||
import useObservable from 'react-use/lib/useObservable';
|
import useObservable from 'react-use/lib/useObservable';
|
||||||
|
@ -55,8 +56,31 @@ export const EmbeddableInputTracker: FC<EmbeddableInputTrackerProps> = ({
|
||||||
}) => {
|
}) => {
|
||||||
const input = useObservable(input$, initialInput);
|
const input = useObservable(input$, initialInput);
|
||||||
|
|
||||||
|
const [manualReload$] = useState<BehaviorSubject<number>>(
|
||||||
|
new BehaviorSubject<number>(initialInput.lastReloadRequestTime ?? Date.now())
|
||||||
|
);
|
||||||
|
|
||||||
|
useEffect(
|
||||||
|
function updateManualReloadSubject() {
|
||||||
|
if (
|
||||||
|
input.lastReloadRequestTime === initialInput.lastReloadRequestTime ||
|
||||||
|
!input.lastReloadRequestTime
|
||||||
|
)
|
||||||
|
return;
|
||||||
|
manualReload$.next(input.lastReloadRequestTime);
|
||||||
|
},
|
||||||
|
[input.lastReloadRequestTime, initialInput.lastReloadRequestTime, manualReload$]
|
||||||
|
);
|
||||||
|
|
||||||
|
const resultObservable$ = useMemo<Observable<number>>(() => {
|
||||||
|
return combineLatest([reload$, manualReload$]).pipe(
|
||||||
|
map(([reload, manualReload]) => Math.max(reload, manualReload)),
|
||||||
|
distinctUntilChanged()
|
||||||
|
);
|
||||||
|
}, [manualReload$, reload$]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ReloadContextProvider reload$={reload$}>
|
<ReloadContextProvider reload$={resultObservable$}>
|
||||||
<DataSourceContextProvider dataViewId={input.dataViewId}>
|
<DataSourceContextProvider dataViewId={input.dataViewId}>
|
||||||
<FilterQueryContextProvider timeRange={input.timeRange}>
|
<FilterQueryContextProvider timeRange={input.timeRange}>
|
||||||
<ChartGridEmbeddableWrapper
|
<ChartGridEmbeddableWrapper
|
||||||
|
@ -70,6 +94,8 @@ export const EmbeddableInputTracker: FC<EmbeddableInputTrackerProps> = ({
|
||||||
onLoading={onLoading}
|
onLoading={onLoading}
|
||||||
onRenderComplete={onRenderComplete}
|
onRenderComplete={onRenderComplete}
|
||||||
onError={onError}
|
onError={onError}
|
||||||
|
onChange={input.onChange}
|
||||||
|
emptyState={input.emptyState}
|
||||||
/>
|
/>
|
||||||
</FilterQueryContextProvider>
|
</FilterQueryContextProvider>
|
||||||
</DataSourceContextProvider>
|
</DataSourceContextProvider>
|
||||||
|
@ -103,6 +129,8 @@ export const ChartGridEmbeddableWrapper: FC<
|
||||||
onError,
|
onError,
|
||||||
onLoading,
|
onLoading,
|
||||||
onRenderComplete,
|
onRenderComplete,
|
||||||
|
onChange,
|
||||||
|
emptyState,
|
||||||
}) => {
|
}) => {
|
||||||
const { filters, query, timeRange } = useFilerQueryUpdates();
|
const { filters, query, timeRange } = useFilerQueryUpdates();
|
||||||
|
|
||||||
|
@ -189,8 +217,12 @@ export const ChartGridEmbeddableWrapper: FC<
|
||||||
resultChangePoints = resultChangePoints.slice(0, maxSeriesToPlot);
|
resultChangePoints = resultChangePoints.slice(0, maxSeriesToPlot);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (onChange) {
|
||||||
|
onChange(resultChangePoints);
|
||||||
|
}
|
||||||
|
|
||||||
return resultChangePoints;
|
return resultChangePoints;
|
||||||
}, [results, maxSeriesToPlot]);
|
}, [results, maxSeriesToPlot, onChange]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
|
@ -205,6 +237,8 @@ export const ChartGridEmbeddableWrapper: FC<
|
||||||
interval={requestParams.interval}
|
interval={requestParams.interval}
|
||||||
onRenderComplete={onRenderComplete}
|
onRenderComplete={onRenderComplete}
|
||||||
/>
|
/>
|
||||||
|
) : emptyState ? (
|
||||||
|
emptyState
|
||||||
) : (
|
) : (
|
||||||
<NoChangePointsWarning />
|
<NoChangePointsWarning />
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -17,8 +17,8 @@ import type { UiActionsStart, UiActionsSetup } from '@kbn/ui-actions-plugin/publ
|
||||||
import type { UnifiedSearchPublicPluginStart } from '@kbn/unified-search-plugin/public';
|
import type { UnifiedSearchPublicPluginStart } from '@kbn/unified-search-plugin/public';
|
||||||
import type { EmbeddableSetup, EmbeddableStart } from '@kbn/embeddable-plugin/public';
|
import type { EmbeddableSetup, EmbeddableStart } from '@kbn/embeddable-plugin/public';
|
||||||
import type { CasesUiSetup } from '@kbn/cases-plugin/public';
|
import type { CasesUiSetup } from '@kbn/cases-plugin/public';
|
||||||
import { LicensingPluginSetup } from '@kbn/licensing-plugin/public';
|
import type { LicensingPluginSetup } from '@kbn/licensing-plugin/public';
|
||||||
import type { EmbeddableChangePointChartProps } from './embeddable';
|
import type { EmbeddableChangePointChartInput } from './embeddable/embeddable_change_point_chart';
|
||||||
|
|
||||||
export interface AiopsPluginSetupDeps {
|
export interface AiopsPluginSetupDeps {
|
||||||
embeddable: EmbeddableSetup;
|
embeddable: EmbeddableSetup;
|
||||||
|
@ -44,5 +44,5 @@ export interface AiopsPluginStartDeps {
|
||||||
|
|
||||||
export type AiopsPluginSetup = void;
|
export type AiopsPluginSetup = void;
|
||||||
export interface AiopsPluginStart {
|
export interface AiopsPluginStart {
|
||||||
EmbeddableChangePointChart: React.ComponentType<EmbeddableChangePointChartProps>;
|
EmbeddableChangePointChart: React.ComponentType<EmbeddableChangePointChartInput>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -213,19 +213,19 @@ export default function AlertDetailsAppSection({
|
||||||
<EuiSpacer size="l" />
|
<EuiSpacer size="l" />
|
||||||
<EuiFlexGroup direction="column" data-test-subj="thresholdAlertRelatedEventsSection">
|
<EuiFlexGroup direction="column" data-test-subj="thresholdAlertRelatedEventsSection">
|
||||||
{ruleParams.criteria.map((criterion, criterionIndex) =>
|
{ruleParams.criteria.map((criterion, criterionIndex) =>
|
||||||
criterion.metrics?.map(
|
criterion.metrics?.map((metric, metricIndex) => {
|
||||||
(metric, metricIndex) =>
|
const id = `embeddableChart-criterion${criterionIndex}-metric${metricIndex}`;
|
||||||
dataView &&
|
return dataView?.id ? (
|
||||||
dataView.id && (
|
<EmbeddableChangePointChart
|
||||||
<EmbeddableChangePointChart
|
id={id}
|
||||||
key={`embeddableChart-criterion${criterionIndex}-metric${metricIndex}`}
|
key={id}
|
||||||
dataViewId={dataView.id}
|
dataViewId={dataView.id}
|
||||||
timeRange={relatedEventsTimeRange(criterion)}
|
timeRange={relatedEventsTimeRange(criterion)}
|
||||||
fn={metric.aggType ?? ''}
|
fn={metric.aggType ?? ''}
|
||||||
metricField={metric.field ?? ''}
|
metricField={metric.field ?? ''}
|
||||||
/>
|
/>
|
||||||
)
|
) : null;
|
||||||
)
|
})
|
||||||
)}
|
)}
|
||||||
</EuiFlexGroup>
|
</EuiFlexGroup>
|
||||||
</>
|
</>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue