= ({
shouldRerunAnalysis={shouldRerunAnalysis || searchQueryUpdated}
analysisInfo={}
>
-
-
+ <>
+ {embeddingOrigin !== AIOPS_EMBEDDABLE_ORIGIN.DASHBOARD && (
+
+ )}
+ {embeddingOrigin === AIOPS_EMBEDDABLE_ORIGIN.DASHBOARD && (
- {groupResultsMessage}
+
+
+
-
-
-
-
-
-
-
-
-
- void}
- />
-
+ )}
+ >
+ {embeddingOrigin === AIOPS_EMBEDDABLE_ORIGIN.DASHBOARD && embeddableOptionsVisible && (
+ <>
+
+
+
+
+ >
+ )}
+
{errors.length > 0 ? (
<>
diff --git a/x-pack/plugins/aiops/public/components/log_rate_analysis_results_table/index.ts b/x-pack/plugins/aiops/public/components/log_rate_analysis_results_table/index.ts
index 6813e71704918..c5112723e2784 100644
--- a/x-pack/plugins/aiops/public/components/log_rate_analysis_results_table/index.ts
+++ b/x-pack/plugins/aiops/public/components/log_rate_analysis_results_table/index.ts
@@ -8,4 +8,3 @@
export { getGroupTableItems } from './get_group_table_items';
export { LogRateAnalysisResultsTable } from './log_rate_analysis_results_table';
export { LogRateAnalysisResultsGroupsTable } from './log_rate_analysis_results_table_groups';
-export type { ColumnNames } from './use_columns';
diff --git a/x-pack/plugins/aiops/public/components/log_rate_analysis_results_table/log_rate_analysis_results_table.tsx b/x-pack/plugins/aiops/public/components/log_rate_analysis_results_table/log_rate_analysis_results_table.tsx
index 83be306e93f50..e9072c2929f14 100644
--- a/x-pack/plugins/aiops/public/components/log_rate_analysis_results_table/log_rate_analysis_results_table.tsx
+++ b/x-pack/plugins/aiops/public/components/log_rate_analysis_results_table/log_rate_analysis_results_table.tsx
@@ -83,13 +83,11 @@ export const LogRateAnalysisResultsTable: FC
=
}, [allSignificantItems, groupFilter]);
const zeroDocsFallback = useAppSelector((s) => s.logRateAnalysisResults.zeroDocsFallback);
- const pinnedGroup = useAppSelector((s) => s.logRateAnalysisTableRow.pinnedGroup);
- const selectedGroup = useAppSelector((s) => s.logRateAnalysisTableRow.selectedGroup);
- const pinnedSignificantItem = useAppSelector(
- (s) => s.logRateAnalysisTableRow.pinnedSignificantItem
- );
+ const pinnedGroup = useAppSelector((s) => s.logRateAnalysisTable.pinnedGroup);
+ const selectedGroup = useAppSelector((s) => s.logRateAnalysisTable.selectedGroup);
+ const pinnedSignificantItem = useAppSelector((s) => s.logRateAnalysisTable.pinnedSignificantItem);
const selectedSignificantItem = useAppSelector(
- (s) => s.logRateAnalysisTableRow.selectedSignificantItem
+ (s) => s.logRateAnalysisTable.selectedSignificantItem
);
const dispatch = useAppDispatch();
diff --git a/x-pack/plugins/aiops/public/components/log_rate_analysis_results_table/log_rate_analysis_results_table_groups.tsx b/x-pack/plugins/aiops/public/components/log_rate_analysis_results_table/log_rate_analysis_results_table_groups.tsx
index d69a0fec7200f..6bd0a5e4ce213 100644
--- a/x-pack/plugins/aiops/public/components/log_rate_analysis_results_table/log_rate_analysis_results_table_groups.tsx
+++ b/x-pack/plugins/aiops/public/components/log_rate_analysis_results_table/log_rate_analysis_results_table_groups.tsx
@@ -91,8 +91,8 @@ export const LogRateAnalysisResultsGroupsTable: FC s.logRateAnalysisTableRow.pinnedGroup);
- const selectedGroup = useAppSelector((s) => s.logRateAnalysisTableRow.selectedGroup);
+ const pinnedGroup = useAppSelector((s) => s.logRateAnalysisTable.pinnedGroup);
+ const selectedGroup = useAppSelector((s) => s.logRateAnalysisTable.selectedGroup);
const dispatch = useAppDispatch();
const isMounted = useMountedState();
diff --git a/x-pack/plugins/aiops/public/components/log_rate_analysis_results_table/use_columns.tsx b/x-pack/plugins/aiops/public/components/log_rate_analysis_results_table/use_columns.tsx
index f3b8195767101..c5b7a83e33641 100644
--- a/x-pack/plugins/aiops/public/components/log_rate_analysis_results_table/use_columns.tsx
+++ b/x-pack/plugins/aiops/public/components/log_rate_analysis_results_table/use_columns.tsx
@@ -21,6 +21,11 @@ import { type SignificantItem, SIGNIFICANT_ITEM_TYPE } from '@kbn/ml-agg-utils';
import { getCategoryQuery } from '@kbn/aiops-log-pattern-analysis/get_category_query';
import type { FieldStatsServices } from '@kbn/unified-field-list/src/components/field_stats';
import { useAppSelector } from '@kbn/aiops-log-rate-analysis/state';
+import {
+ commonColumns,
+ significantItemColumns,
+ type LogRateAnalysisResultsTableColumnName,
+} from '@kbn/aiops-log-rate-analysis/state/log_rate_analysis_table_slice';
import {
getBaselineAndDeviationRates,
getLogRateChange,
@@ -40,55 +45,6 @@ const TRUNCATE_TEXT_LINES = 3;
const UNIQUE_COLUMN_WIDTH = '40px';
const NOT_AVAILABLE = '--';
-export const commonColumns = {
- ['Log rate']: i18n.translate('xpack.aiops.logRateAnalysis.resultsTable.logRateColumnTitle', {
- defaultMessage: 'Log rate',
- }),
- ['Doc count']: i18n.translate('xpack.aiops.logRateAnalysis.resultsTable.docCountColumnTitle', {
- defaultMessage: 'Doc count',
- }),
- ['p-value']: i18n.translate('xpack.aiops.logRateAnalysis.resultsTable.pValueColumnTitle', {
- defaultMessage: 'p-value',
- }),
- ['Impact']: i18n.translate('xpack.aiops.logRateAnalysis.resultsTable.impactColumnTitle', {
- defaultMessage: 'Impact',
- }),
- ['Baseline rate']: i18n.translate(
- 'xpack.aiops.logRateAnalysis.resultsTable.baselineRateColumnTitle',
- {
- defaultMessage: 'Baseline rate',
- }
- ),
- ['Deviation rate']: i18n.translate(
- 'xpack.aiops.logRateAnalysis.resultsTable.deviationRateColumnTitle',
- {
- defaultMessage: 'Deviation rate',
- }
- ),
- ['Log rate change']: i18n.translate(
- 'xpack.aiops.logRateAnalysis.resultsTable.logRateChangeColumnTitle',
- {
- defaultMessage: 'Log rate change',
- }
- ),
- ['Actions']: i18n.translate('xpack.aiops.logRateAnalysis.resultsTable.actionsColumnTitle', {
- defaultMessage: 'Actions',
- }),
-};
-
-export const significantItemColumns = {
- ['Field name']: i18n.translate('xpack.aiops.logRateAnalysis.resultsTable.fieldNameColumnTitle', {
- defaultMessage: 'Field name',
- }),
- ['Field value']: i18n.translate(
- 'xpack.aiops.logRateAnalysis.resultsTable.fieldValueColumnTitle',
- {
- defaultMessage: 'Field value',
- }
- ),
- ...commonColumns,
-} as const;
-
export const LOG_RATE_ANALYSIS_RESULTS_TABLE_TYPE = {
GROUPS: 'groups',
SIGNIFICANT_ITEMS: 'significantItems',
@@ -96,8 +52,6 @@ export const LOG_RATE_ANALYSIS_RESULTS_TABLE_TYPE = {
export type LogRateAnalysisResultsTableType =
(typeof LOG_RATE_ANALYSIS_RESULTS_TABLE_TYPE)[keyof typeof LOG_RATE_ANALYSIS_RESULTS_TABLE_TYPE];
-export type ColumnNames = keyof typeof significantItemColumns | 'unique';
-
const logRateHelpMessage = i18n.translate(
'xpack.aiops.logRateAnalysis.resultsTable.logRateColumnTooltip',
{
@@ -213,7 +167,7 @@ export const useColumns = (
const { earliest, latest } = useAppSelector((s) => s.logRateAnalysis);
const timeRangeMs = { from: earliest ?? 0, to: latest ?? 0 };
- const loading = useAppSelector((s) => s.logRateAnalysisStream.isRunning);
+ const loading = useAppSelector((s) => s.stream.isRunning);
const zeroDocsFallback = useAppSelector((s) => s.logRateAnalysisResults.zeroDocsFallback);
const {
documentStats: { documentCountStats },
@@ -271,7 +225,10 @@ export const useColumns = (
[currentAnalysisType, buckets]
);
- const columnsMap: Record> = useMemo(
+ const columnsMap: Record<
+ LogRateAnalysisResultsTableColumnName,
+ EuiBasicTableColumn
+ > = useMemo(
() => ({
['Field name']: {
'data-test-subj': 'aiopsLogRateAnalysisResultsTableColumnFieldName',
@@ -615,20 +572,21 @@ export const useColumns = (
);
const columns = useMemo(() => {
- const columnNamesToReturn: Partial> = isGroupsTable
- ? commonColumns
- : significantItemColumns;
+ const columnNamesToReturn: Partial> =
+ isGroupsTable ? commonColumns : significantItemColumns;
const columnsToReturn = [];
for (const columnName in columnNamesToReturn) {
if (
Object.hasOwn(columnNamesToReturn, columnName) === false ||
- skippedColumns.includes(columnNamesToReturn[columnName as ColumnNames] as string) ||
+ skippedColumns.includes(
+ columnNamesToReturn[columnName as LogRateAnalysisResultsTableColumnName] as string
+ ) ||
((columnName === 'p-value' || columnName === 'Impact') && zeroDocsFallback)
)
continue;
- columnsToReturn.push(columnsMap[columnName as ColumnNames]);
+ columnsToReturn.push(columnsMap[columnName as LogRateAnalysisResultsTableColumnName]);
}
if (isExpandedRow === true) {
diff --git a/x-pack/plugins/aiops/public/components/log_rate_analysis_results_table/use_view_in_discover_action.tsx b/x-pack/plugins/aiops/public/components/log_rate_analysis_results_table/use_view_in_discover_action.tsx
index ec4284d6452e5..765f1435a93ad 100644
--- a/x-pack/plugins/aiops/public/components/log_rate_analysis_results_table/use_view_in_discover_action.tsx
+++ b/x-pack/plugins/aiops/public/components/log_rate_analysis_results_table/use_view_in_discover_action.tsx
@@ -28,8 +28,8 @@ export const useViewInDiscoverAction = (dataViewId?: string): TableItemAction =>
const { application, share, data } = useAiopsAppContext();
const discoverLocator = useMemo(
- () => share.url.locators.get('DISCOVER_APP_LOCATOR'),
- [share.url.locators]
+ () => share?.url.locators.get('DISCOVER_APP_LOCATOR'),
+ [share?.url.locators]
);
const discoverUrlError = useMemo(() => {
diff --git a/x-pack/plugins/aiops/public/components/log_rate_analysis_results_table/use_view_in_log_pattern_analysis_action.tsx b/x-pack/plugins/aiops/public/components/log_rate_analysis_results_table/use_view_in_log_pattern_analysis_action.tsx
index dbac6fbe8c9f3..ec1f6774b6b46 100644
--- a/x-pack/plugins/aiops/public/components/log_rate_analysis_results_table/use_view_in_log_pattern_analysis_action.tsx
+++ b/x-pack/plugins/aiops/public/components/log_rate_analysis_results_table/use_view_in_log_pattern_analysis_action.tsx
@@ -32,7 +32,7 @@ const viewInLogPatternAnalysisMessage = i18n.translate(
export const useViewInLogPatternAnalysisAction = (dataViewId?: string): TableItemAction => {
const { application, share, data } = useAiopsAppContext();
- const mlLocator = useMemo(() => share.url.locators.get('ML_APP_LOCATOR'), [share.url.locators]);
+ const mlLocator = useMemo(() => share?.url.locators.get('ML_APP_LOCATOR'), [share?.url.locators]);
const generateLogPatternAnalysisUrl = async (
groupTableItem: GroupTableItem | SignificantItem
diff --git a/x-pack/plugins/aiops/public/components/time_field_warning.tsx b/x-pack/plugins/aiops/public/components/time_field_warning.tsx
new file mode 100644
index 0000000000000..beb64917af538
--- /dev/null
+++ b/x-pack/plugins/aiops/public/components/time_field_warning.tsx
@@ -0,0 +1,32 @@
+/*
+ * 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 { EuiSpacer, EuiCallOut } from '@elastic/eui';
+import { i18n } from '@kbn/i18n';
+import React from 'react';
+
+export const TimeFieldWarning = () => {
+ return (
+ <>
+
+
+ {i18n.translate('xpack.aiops.embeddableMenu.timeFieldWarning.title.description', {
+ defaultMessage: 'The analysis can only be run on data views with a time field.',
+ })}
+
+
+
+ >
+ );
+};
diff --git a/x-pack/plugins/aiops/public/embeddables/change_point_chart/change_point_chart_initializer.tsx b/x-pack/plugins/aiops/public/embeddables/change_point_chart/change_point_chart_initializer.tsx
index 08cf6ffd7dcb1..e69511fe45f92 100644
--- a/x-pack/plugins/aiops/public/embeddables/change_point_chart/change_point_chart_initializer.tsx
+++ b/x-pack/plugins/aiops/public/embeddables/change_point_chart/change_point_chart_initializer.tsx
@@ -18,16 +18,23 @@ import {
EuiHorizontalRule,
EuiTitle,
} from '@elastic/eui';
+import { DatePickerContextProvider, type DatePickerDependencies } from '@kbn/ml-date-picker';
+import { UI_SETTINGS } from '@kbn/data-plugin/common';
+import type { FieldStatsServices } from '@kbn/unified-field-list/src/components/field_stats';
import { ES_FIELD_TYPES } from '@kbn/field-types';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n-react';
import { isPopulatedObject } from '@kbn/ml-is-populated-object';
+import { FieldStatsFlyoutProvider } from '@kbn/ml-field-stats-flyout';
+import { useTimefilter } from '@kbn/ml-date-picker';
import { pick } from 'lodash';
import type { FC } from 'react';
import React, { useCallback, useEffect, useMemo, useState } from 'react';
import usePrevious from 'react-use/lib/usePrevious';
import {
+ ChangePointDetectionContextProvider,
ChangePointDetectionControlsContextProvider,
+ useChangePointDetectionContext,
useChangePointDetectionControlsContext,
} from '../../components/change_point_detection/change_point_detection_context';
import { DEFAULT_AGG_FUNCTION } from '../../components/change_point_detection/constants';
@@ -38,7 +45,8 @@ import { PartitionsSelector } from '../../components/change_point_detection/part
import { SplitFieldSelector } from '../../components/change_point_detection/split_field_selector';
import { ViewTypeSelector } from '../../components/change_point_detection/view_type_selector';
import { useAiopsAppContext } from '../../hooks/use_aiops_app_context';
-import { DataSourceContextProvider } from '../../hooks/use_data_source';
+import { useDataSource, DataSourceContextProvider } from '../../hooks/use_data_source';
+import { FilterQueryContextProvider } from '../../hooks/use_filters_query';
import { DEFAULT_SERIES } from './const';
import type { ChangePointEmbeddableRuntimeState } from './types';
@@ -53,11 +61,18 @@ export const ChangePointChartInitializer: FC = ({
onCreate,
onCancel,
}) => {
+ const appContextValue = useAiopsAppContext();
const {
+ data: { dataViews },
unifiedSearch: {
ui: { IndexPatternSelect },
},
- } = useAiopsAppContext();
+ } = appContextValue;
+
+ const datePickerDeps: DatePickerDependencies = {
+ ...pick(appContextValue, ['data', 'http', 'notifications', 'theme', 'uiSettings', 'i18n']),
+ uiSettingsKeys: UI_SETTINGS,
+ };
const [dataViewId, setDataViewId] = useState(initialInput?.dataViewId ?? '');
const [viewType, setViewType] = useState(initialInput?.viewType ?? 'charts');
@@ -135,15 +150,21 @@ export const ChangePointChartInitializer: FC = ({
}}
/>
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
@@ -190,7 +211,13 @@ export const FormControls: FC<{
onChange: (update: FormControlsProps) => void;
onValidationChange: (isValid: boolean) => void;
}> = ({ formInput, onChange, onValidationChange }) => {
+ const { charts, data, fieldFormats, theme, uiSettings } = useAiopsAppContext();
+ const { dataView } = useDataSource();
+ const { combinedQuery } = useChangePointDetectionContext();
const { metricFieldOptions, splitFieldsOptions } = useChangePointDetectionControlsContext();
+ const timefilter = useTimefilter();
+ const timefilterActiveBounds = timefilter.getActiveBounds();
+
const prevMetricFieldOptions = usePrevious(metricFieldOptions);
const enableSearch = useMemo(() => {
@@ -238,10 +265,33 @@ export const FormControls: FC<{
[formInput, onChange]
);
+ const fieldStatsServices: FieldStatsServices = useMemo(() => {
+ return {
+ uiSettings,
+ dataViews: data.dataViews,
+ data,
+ fieldFormats,
+ charts,
+ };
+ }, [uiSettings, data, fieldFormats, charts]);
+
if (!isPopulatedObject(formInput)) return null;
return (
- <>
+
updateCallback({ maxSeriesToPlot: v })}
onValidationChange={(result) => onValidationChange(result === null)}
/>
- >
+
);
};
diff --git a/x-pack/plugins/aiops/public/embeddables/change_point_chart/embeddable_change_point_chart_factory.tsx b/x-pack/plugins/aiops/public/embeddables/change_point_chart/embeddable_change_point_chart_factory.tsx
index 7cf39eb1cf4ae..2ce1a46780db1 100644
--- a/x-pack/plugins/aiops/public/embeddables/change_point_chart/embeddable_change_point_chart_factory.tsx
+++ b/x-pack/plugins/aiops/public/embeddables/change_point_chart/embeddable_change_point_chart_factory.tsx
@@ -11,7 +11,6 @@ import {
} from '@kbn/aiops-change-point-detection/constants';
import type { Reference } from '@kbn/content-management-utils';
import type { StartServicesAccessor } from '@kbn/core-lifecycle-browser';
-import { type DataPublicPluginStart } from '@kbn/data-plugin/public';
import type { DataView } from '@kbn/data-views-plugin/common';
import { DATA_VIEW_SAVED_OBJECT_TYPE } from '@kbn/data-views-plugin/common';
import type { ReactEmbeddableFactory } from '@kbn/embeddable-plugin/public';
@@ -38,32 +37,8 @@ import type {
ChangePointEmbeddableState,
} from './types';
-export interface EmbeddableChangePointChartStartServices {
- data: DataPublicPluginStart;
-}
-
export type EmbeddableChangePointChartType = typeof EMBEDDABLE_CHANGE_POINT_CHART_TYPE;
-export const getDependencies = async (
- getStartServices: StartServicesAccessor
-) => {
- const [
- { http, uiSettings, notifications, ...startServices },
- { lens, data, usageCollection, fieldFormats },
- ] = await getStartServices();
-
- return {
- http,
- uiSettings,
- data,
- notifications,
- lens,
- usageCollection,
- fieldFormats,
- ...startServices,
- };
-};
-
export const getChangePointChartEmbeddableFactory = (
getStartServices: StartServicesAccessor
) => {
@@ -88,20 +63,6 @@ export const getChangePointChartEmbeddableFactory = (
buildEmbeddable: async (state, buildApi, uuid, parentApi) => {
const [coreStart, pluginStart] = await getStartServices();
- const { http, uiSettings, notifications, ...startServices } = coreStart;
- const { lens, data, usageCollection, fieldFormats } = pluginStart;
-
- const deps = {
- http,
- uiSettings,
- data,
- notifications,
- lens,
- usageCollection,
- fieldFormats,
- ...startServices,
- };
-
const {
api: timeRangeApi,
comparators: timeRangeComparators,
@@ -120,7 +81,7 @@ export const getChangePointChartEmbeddableFactory = (
const blockingError = new BehaviorSubject(undefined);
const dataViews$ = new BehaviorSubject([
- await deps.data.dataViews.get(state.dataViewId),
+ await pluginStart.data.dataViews.get(state.dataViewId),
]);
const api = buildApi(
diff --git a/x-pack/plugins/aiops/public/embeddables/change_point_chart/types.ts b/x-pack/plugins/aiops/public/embeddables/change_point_chart/types.ts
index 4a39020a299c9..f86270bdaf19d 100644
--- a/x-pack/plugins/aiops/public/embeddables/change_point_chart/types.ts
+++ b/x-pack/plugins/aiops/public/embeddables/change_point_chart/types.ts
@@ -15,14 +15,6 @@ import type {
SerializedTimeRange,
SerializedTitles,
} from '@kbn/presentation-publishing';
-import type { FC } from 'react';
-import type { SelectedChangePoint } from '../../components/change_point_detection/change_point_detection_context';
-
-export type ViewComponent = FC<{
- changePoints: SelectedChangePoint[];
- interval: string;
- onRenderComplete?: () => void;
-}>;
export interface ChangePointComponentApi {
viewType: PublishingSubject;
diff --git a/x-pack/plugins/aiops/public/embeddables/index.ts b/x-pack/plugins/aiops/public/embeddables/index.ts
index b7d9ad25951fb..dae1f0eb3eeec 100644
--- a/x-pack/plugins/aiops/public/embeddables/index.ts
+++ b/x-pack/plugins/aiops/public/embeddables/index.ts
@@ -9,6 +9,7 @@ import type { CoreSetup } from '@kbn/core-lifecycle-browser';
import type { EmbeddableSetup } from '@kbn/embeddable-plugin/public';
import { EMBEDDABLE_CHANGE_POINT_CHART_TYPE } from '@kbn/aiops-change-point-detection/constants';
import { EMBEDDABLE_PATTERN_ANALYSIS_TYPE } from '@kbn/aiops-log-pattern-analysis/constants';
+import { EMBEDDABLE_LOG_RATE_ANALYSIS_TYPE } from '@kbn/aiops-log-rate-analysis/constants';
import type { AiopsPluginStart, AiopsPluginStartDeps } from '../types';
export const registerEmbeddables = (
@@ -23,4 +24,8 @@ export const registerEmbeddables = (
const { getPatternAnalysisEmbeddableFactory } = await import('./pattern_analysis');
return getPatternAnalysisEmbeddableFactory(core.getStartServices);
});
+ embeddable.registerReactEmbeddableFactory(EMBEDDABLE_LOG_RATE_ANALYSIS_TYPE, async () => {
+ const { getLogRateAnalysisEmbeddableFactory } = await import('./log_rate_analysis');
+ return getLogRateAnalysisEmbeddableFactory(core.getStartServices);
+ });
};
diff --git a/x-pack/plugins/aiops/public/embeddables/log_rate_analysis/embeddable_log_rate_analysis_factory.tsx b/x-pack/plugins/aiops/public/embeddables/log_rate_analysis/embeddable_log_rate_analysis_factory.tsx
new file mode 100644
index 0000000000000..592ec32cef120
--- /dev/null
+++ b/x-pack/plugins/aiops/public/embeddables/log_rate_analysis/embeddable_log_rate_analysis_factory.tsx
@@ -0,0 +1,211 @@
+/*
+ * 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 {
+ EMBEDDABLE_LOG_RATE_ANALYSIS_TYPE,
+ LOG_RATE_ANALYSIS_DATA_VIEW_REF_NAME,
+} from '@kbn/aiops-log-rate-analysis/constants';
+import type { Reference } from '@kbn/content-management-utils';
+import type { StartServicesAccessor } from '@kbn/core-lifecycle-browser';
+import type { DataView } from '@kbn/data-views-plugin/common';
+import { DATA_VIEW_SAVED_OBJECT_TYPE } from '@kbn/data-views-plugin/common';
+import type { ReactEmbeddableFactory } from '@kbn/embeddable-plugin/public';
+import { i18n } from '@kbn/i18n';
+import {
+ apiHasExecutionContext,
+ fetch$,
+ initializeTimeRange,
+ initializeTitles,
+ useBatchedPublishingSubjects,
+} from '@kbn/presentation-publishing';
+
+import fastIsEqual from 'fast-deep-equal';
+import { cloneDeep } from 'lodash';
+import React, { useMemo } from 'react';
+import useObservable from 'react-use/lib/useObservable';
+import { BehaviorSubject, distinctUntilChanged, map, skipWhile } from 'rxjs';
+import { getLogRateAnalysisEmbeddableWrapperComponent } from '../../shared_components';
+import type { AiopsPluginStart, AiopsPluginStartDeps } from '../../types';
+import { initializeLogRateAnalysisControls } from './initialize_log_rate_analysis_analysis_controls';
+import type {
+ LogRateAnalysisEmbeddableApi,
+ LogRateAnalysisEmbeddableRuntimeState,
+ LogRateAnalysisEmbeddableState,
+} from './types';
+
+export const getLogRateAnalysisEmbeddableFactory = (
+ getStartServices: StartServicesAccessor
+) => {
+ const factory: ReactEmbeddableFactory<
+ LogRateAnalysisEmbeddableState,
+ LogRateAnalysisEmbeddableRuntimeState,
+ LogRateAnalysisEmbeddableApi
+ > = {
+ type: EMBEDDABLE_LOG_RATE_ANALYSIS_TYPE,
+ deserializeState: (state) => {
+ const serializedState = cloneDeep(state.rawState);
+ // inject the reference
+ const dataViewIdRef = state.references?.find(
+ (ref) => ref.name === LOG_RATE_ANALYSIS_DATA_VIEW_REF_NAME
+ );
+ // if the serializedState already contains a dataViewId, we don't want to overwrite it. (Unsaved state can cause this)
+ if (dataViewIdRef && serializedState && !serializedState.dataViewId) {
+ serializedState.dataViewId = dataViewIdRef?.id;
+ }
+ return serializedState;
+ },
+ buildEmbeddable: async (state, buildApi, uuid, parentApi) => {
+ const [coreStart, pluginStart] = await getStartServices();
+
+ const {
+ api: timeRangeApi,
+ comparators: timeRangeComparators,
+ serialize: serializeTimeRange,
+ } = initializeTimeRange(state);
+
+ const { titlesApi, titleComparators, serializeTitles } = initializeTitles(state);
+
+ const {
+ logRateAnalysisControlsApi,
+ serializeLogRateAnalysisChartState,
+ logRateAnalysisControlsComparators,
+ } = initializeLogRateAnalysisControls(state);
+
+ const dataLoading = new BehaviorSubject(true);
+ const blockingError = new BehaviorSubject(undefined);
+
+ const dataViews$ = new BehaviorSubject([
+ await pluginStart.data.dataViews.get(
+ state.dataViewId ?? (await pluginStart.data.dataViews.getDefaultId())
+ ),
+ ]);
+
+ const api = buildApi(
+ {
+ ...timeRangeApi,
+ ...titlesApi,
+ ...logRateAnalysisControlsApi,
+ getTypeDisplayName: () =>
+ i18n.translate('xpack.aiops.logRateAnalysis.typeDisplayName', {
+ defaultMessage: 'log rate analysis',
+ }),
+ isEditingEnabled: () => true,
+ onEdit: async () => {
+ try {
+ const { resolveEmbeddableLogRateAnalysisUserInput } = await import(
+ './resolve_log_rate_analysis_config_input'
+ );
+
+ const result = await resolveEmbeddableLogRateAnalysisUserInput(
+ coreStart,
+ pluginStart,
+ parentApi,
+ uuid,
+ false,
+ logRateAnalysisControlsApi,
+ undefined,
+ serializeLogRateAnalysisChartState()
+ );
+
+ logRateAnalysisControlsApi.updateUserInput(result);
+ } catch (e) {
+ return Promise.reject();
+ }
+ },
+ dataLoading,
+ blockingError,
+ dataViews: dataViews$,
+ serializeState: () => {
+ const dataViewId = logRateAnalysisControlsApi.dataViewId.getValue();
+ const references: Reference[] = dataViewId
+ ? [
+ {
+ type: DATA_VIEW_SAVED_OBJECT_TYPE,
+ name: LOG_RATE_ANALYSIS_DATA_VIEW_REF_NAME,
+ id: dataViewId,
+ },
+ ]
+ : [];
+ return {
+ rawState: {
+ timeRange: undefined,
+ ...serializeTitles(),
+ ...serializeTimeRange(),
+ ...serializeLogRateAnalysisChartState(),
+ },
+ references,
+ };
+ },
+ },
+ {
+ ...timeRangeComparators,
+ ...titleComparators,
+ ...logRateAnalysisControlsComparators,
+ }
+ );
+
+ const LogRateAnalysisEmbeddableWrapper = getLogRateAnalysisEmbeddableWrapperComponent(
+ coreStart,
+ pluginStart
+ );
+
+ const onLoading = (v: boolean) => dataLoading.next(v);
+ const onRenderComplete = () => dataLoading.next(false);
+ const onError = (error: Error) => blockingError.next(error);
+
+ return {
+ api,
+ Component: () => {
+ if (!apiHasExecutionContext(parentApi)) {
+ throw new Error('Parent API does not have execution context');
+ }
+
+ const [dataViewId] = useBatchedPublishingSubjects(api.dataViewId);
+
+ const reload$ = useMemo(
+ () =>
+ fetch$(api).pipe(
+ skipWhile((fetchContext) => !fetchContext.isReload),
+ map((fetchContext) => Date.now())
+ ),
+ []
+ );
+
+ const timeRange$ = useMemo(
+ () =>
+ fetch$(api).pipe(
+ map((fetchContext) => fetchContext.timeRange),
+ distinctUntilChanged(fastIsEqual)
+ ),
+ []
+ );
+
+ const lastReloadRequestTime = useObservable(reload$, Date.now());
+ const timeRange = useObservable(timeRange$, undefined);
+
+ const embeddingOrigin = apiHasExecutionContext(parentApi)
+ ? parentApi.executionContext.type
+ : undefined;
+
+ return (
+
+ );
+ },
+ };
+ },
+ };
+
+ return factory;
+};
diff --git a/x-pack/plugins/aiops/public/embeddables/log_rate_analysis/index.ts b/x-pack/plugins/aiops/public/embeddables/log_rate_analysis/index.ts
new file mode 100644
index 0000000000000..2203d4c64bc8b
--- /dev/null
+++ b/x-pack/plugins/aiops/public/embeddables/log_rate_analysis/index.ts
@@ -0,0 +1,8 @@
+/*
+ * 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.
+ */
+
+export { getLogRateAnalysisEmbeddableFactory } from './embeddable_log_rate_analysis_factory';
diff --git a/x-pack/plugins/aiops/public/embeddables/log_rate_analysis/initialize_log_rate_analysis_analysis_controls.ts b/x-pack/plugins/aiops/public/embeddables/log_rate_analysis/initialize_log_rate_analysis_analysis_controls.ts
new file mode 100644
index 0000000000000..9d8a49b8f0e9c
--- /dev/null
+++ b/x-pack/plugins/aiops/public/embeddables/log_rate_analysis/initialize_log_rate_analysis_analysis_controls.ts
@@ -0,0 +1,43 @@
+/*
+ * 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 type { StateComparators } from '@kbn/presentation-publishing';
+import { BehaviorSubject } from 'rxjs';
+import type { LogRateAnalysisComponentApi, LogRateAnalysisEmbeddableState } from './types';
+
+type LogRateAnalysisEmbeddableCustomState = Omit<
+ LogRateAnalysisEmbeddableState,
+ 'timeRange' | 'title' | 'description' | 'hidePanelTitles'
+>;
+
+export const initializeLogRateAnalysisControls = (rawState: LogRateAnalysisEmbeddableState) => {
+ const dataViewId = new BehaviorSubject(rawState.dataViewId);
+
+ const updateUserInput = (update: LogRateAnalysisEmbeddableCustomState) => {
+ dataViewId.next(update.dataViewId);
+ };
+
+ const serializeLogRateAnalysisChartState = (): LogRateAnalysisEmbeddableCustomState => {
+ return {
+ dataViewId: dataViewId.getValue(),
+ };
+ };
+
+ const logRateAnalysisControlsComparators: StateComparators =
+ {
+ dataViewId: [dataViewId, (arg) => dataViewId.next(arg)],
+ };
+
+ return {
+ logRateAnalysisControlsApi: {
+ dataViewId,
+ updateUserInput,
+ } as unknown as LogRateAnalysisComponentApi,
+ serializeLogRateAnalysisChartState,
+ logRateAnalysisControlsComparators,
+ };
+};
diff --git a/x-pack/plugins/aiops/public/embeddables/log_rate_analysis/log_rate_analysis_embeddable_initializer.tsx b/x-pack/plugins/aiops/public/embeddables/log_rate_analysis/log_rate_analysis_embeddable_initializer.tsx
new file mode 100644
index 0000000000000..bf53f07677739
--- /dev/null
+++ b/x-pack/plugins/aiops/public/embeddables/log_rate_analysis/log_rate_analysis_embeddable_initializer.tsx
@@ -0,0 +1,230 @@
+/*
+ * 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 type { FC } from 'react';
+import React, { useEffect, useMemo, useState, useCallback } from 'react';
+import { pick } from 'lodash';
+import useMountedState from 'react-use/lib/useMountedState';
+
+import {
+ EuiFlyoutHeader,
+ EuiTitle,
+ EuiFlyoutBody,
+ EuiForm,
+ EuiFormRow,
+ EuiButton,
+ EuiButtonEmpty,
+ EuiFlexGroup,
+ EuiFlexItem,
+ EuiFlyoutFooter,
+ EuiSpacer,
+} from '@elastic/eui';
+
+import type { IndexPatternSelectProps } from '@kbn/unified-search-plugin/public';
+import { euiThemeVars } from '@kbn/ui-theme';
+import { i18n } from '@kbn/i18n';
+import { FormattedMessage } from '@kbn/i18n-react';
+import { isPopulatedObject } from '@kbn/ml-is-populated-object';
+import type { DataViewsPublicPluginStart } from '@kbn/data-views-plugin/public';
+
+import { TimeFieldWarning } from '../../components/time_field_warning';
+
+import type { LogRateAnalysisEmbeddableRuntimeState } from './types';
+
+export interface LogRateAnalysisEmbeddableInitializerProps {
+ dataViews: DataViewsPublicPluginStart;
+ IndexPatternSelect: React.ComponentType;
+ initialInput?: Partial;
+ onCreate: (props: LogRateAnalysisEmbeddableRuntimeState) => void;
+ onCancel: () => void;
+ onPreview: (update: LogRateAnalysisEmbeddableRuntimeState) => Promise;
+ isNewPanel: boolean;
+}
+
+export const LogRateAnalysisEmbeddableInitializer: FC<
+ LogRateAnalysisEmbeddableInitializerProps
+> = ({
+ dataViews,
+ IndexPatternSelect,
+ initialInput,
+ onCreate,
+ onCancel,
+ onPreview,
+ isNewPanel,
+}) => {
+ const isMounted = useMountedState();
+
+ const [formInput, setFormInput] = useState(
+ pick(initialInput ?? {}, ['dataViewId']) as LogRateAnalysisEmbeddableRuntimeState
+ );
+
+ // State to track if the selected data view is time based, undefined is used
+ // to track that the check is in progress.
+ const [isDataViewTimeBased, setIsDataViewTimeBased] = useState();
+
+ const isFormValid = useMemo(
+ () =>
+ isPopulatedObject(formInput, ['dataViewId']) &&
+ formInput.dataViewId !== '' &&
+ isDataViewTimeBased === true,
+ [formInput, isDataViewTimeBased]
+ );
+
+ const updatedProps = useMemo(() => {
+ return {
+ ...formInput,
+ title: isPopulatedObject(formInput)
+ ? i18n.translate('xpack.aiops.embeddableLogRateAnalysis.attachmentTitle', {
+ defaultMessage: 'Log rate analysis',
+ })
+ : '',
+ };
+ }, [formInput]);
+
+ useEffect(
+ function previewChanges() {
+ if (isFormValid) {
+ onPreview(updatedProps);
+ }
+ },
+ [isFormValid, onPreview, updatedProps, isDataViewTimeBased]
+ );
+
+ const setDataViewId = useCallback(
+ (dataViewId: string | undefined) => {
+ setFormInput({
+ ...formInput,
+ dataViewId: dataViewId ?? '',
+ });
+ setIsDataViewTimeBased(undefined);
+ },
+ [formInput]
+ );
+
+ useEffect(
+ function checkIsDataViewTimeBased() {
+ setIsDataViewTimeBased(undefined);
+
+ const { dataViewId } = formInput;
+
+ if (!dataViewId) {
+ return;
+ }
+
+ dataViews
+ .get(dataViewId)
+ .then((dataView) => {
+ if (!isMounted()) {
+ return;
+ }
+ setIsDataViewTimeBased(dataView.isTimeBased());
+ })
+ .catch(() => {
+ setIsDataViewTimeBased(undefined);
+ });
+ },
+ [dataViews, formInput, isMounted]
+ );
+
+ return (
+ <>
+
+
+
+ {isNewPanel
+ ? i18n.translate('xpack.aiops.embeddableLogRateAnalysis.config.title.new', {
+ defaultMessage: 'Create log rate analysis',
+ })
+ : i18n.translate('xpack.aiops.embeddableLogRateAnalysis.config.title.edit', {
+ defaultMessage: 'Edit log rate analysis',
+ })}
+
+
+
+
+
+
+
+ <>
+ {
+ setDataViewId(newId ?? '');
+ }}
+ data-test-subj="aiopsLogRateAnalysisEmbeddableDataViewSelector"
+ />
+ {isDataViewTimeBased === false && (
+ <>
+
+
+ >
+ )}
+ >
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ >
+ );
+};
diff --git a/x-pack/plugins/aiops/public/embeddables/log_rate_analysis/resolve_log_rate_analysis_config_input.tsx b/x-pack/plugins/aiops/public/embeddables/log_rate_analysis/resolve_log_rate_analysis_config_input.tsx
new file mode 100644
index 0000000000000..a066b5bc722f2
--- /dev/null
+++ b/x-pack/plugins/aiops/public/embeddables/log_rate_analysis/resolve_log_rate_analysis_config_input.tsx
@@ -0,0 +1,94 @@
+/*
+ * 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 type { CoreStart } from '@kbn/core/public';
+import { tracksOverlays } from '@kbn/presentation-containers';
+import { toMountPoint } from '@kbn/react-kibana-mount';
+import React from 'react';
+import type { AiopsPluginStartDeps } from '../../types';
+import { LogRateAnalysisEmbeddableInitializer } from './log_rate_analysis_embeddable_initializer';
+import type { LogRateAnalysisComponentApi, LogRateAnalysisEmbeddableState } from './types';
+
+export async function resolveEmbeddableLogRateAnalysisUserInput(
+ coreStart: CoreStart,
+ pluginStart: AiopsPluginStartDeps,
+ parentApi: unknown,
+ focusedPanelId: string,
+ isNewPanel: boolean,
+ logRateAnalysisControlsApi: LogRateAnalysisComponentApi,
+ deletePanel?: () => void,
+ initialState?: LogRateAnalysisEmbeddableState
+): Promise {
+ const { overlays } = coreStart;
+
+ const overlayTracker = tracksOverlays(parentApi) ? parentApi : undefined;
+
+ let hasChanged = false;
+ return new Promise(async (resolve, reject) => {
+ try {
+ const cancelChanges = () => {
+ if (isNewPanel && deletePanel) {
+ deletePanel();
+ } else if (hasChanged && logRateAnalysisControlsApi && initialState) {
+ // Reset to initialState in case user has changed the preview state
+ logRateAnalysisControlsApi.updateUserInput(initialState);
+ }
+
+ flyoutSession.close();
+ overlayTracker?.clearOverlays();
+ };
+
+ const update = async (nextUpdate: LogRateAnalysisEmbeddableState) => {
+ resolve(nextUpdate);
+ flyoutSession.close();
+ overlayTracker?.clearOverlays();
+ };
+
+ const preview = async (nextUpdate: LogRateAnalysisEmbeddableState) => {
+ if (logRateAnalysisControlsApi) {
+ logRateAnalysisControlsApi.updateUserInput(nextUpdate);
+ hasChanged = true;
+ }
+ };
+
+ const flyoutSession = overlays.openFlyout(
+ toMountPoint(
+ ,
+ coreStart
+ ),
+ {
+ ownFocus: true,
+ size: 's',
+ type: 'push',
+ paddingSize: 'm',
+ hideCloseButton: true,
+ 'data-test-subj': 'aiopsLogRateAnalysisEmbeddableInitializer',
+ 'aria-labelledby': 'logRateAnalysisConfig',
+ onClose: () => {
+ reject();
+ flyoutSession.close();
+ overlayTracker?.clearOverlays();
+ },
+ }
+ );
+
+ if (tracksOverlays(parentApi)) {
+ parentApi.openOverlay(flyoutSession, { focusedPanelId });
+ }
+ } catch (error) {
+ reject(error);
+ }
+ });
+}
diff --git a/x-pack/plugins/aiops/public/embeddables/log_rate_analysis/types.ts b/x-pack/plugins/aiops/public/embeddables/log_rate_analysis/types.ts
new file mode 100644
index 0000000000000..d2255e6dacb87
--- /dev/null
+++ b/x-pack/plugins/aiops/public/embeddables/log_rate_analysis/types.ts
@@ -0,0 +1,39 @@
+/*
+ * 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 type { DefaultEmbeddableApi } from '@kbn/embeddable-plugin/public';
+import type {
+ HasEditCapabilities,
+ PublishesDataViews,
+ PublishesTimeRange,
+ PublishingSubject,
+ SerializedTimeRange,
+ SerializedTitles,
+} from '@kbn/presentation-publishing';
+
+export interface LogRateAnalysisComponentApi {
+ dataViewId: PublishingSubject;
+ updateUserInput: (update: LogRateAnalysisEmbeddableState) => void;
+}
+
+export type LogRateAnalysisEmbeddableApi = DefaultEmbeddableApi &
+ HasEditCapabilities &
+ PublishesDataViews &
+ PublishesTimeRange &
+ LogRateAnalysisComponentApi;
+
+export interface LogRateAnalysisEmbeddableState extends SerializedTitles, SerializedTimeRange {
+ dataViewId: string;
+}
+
+export interface LogRateAnalysisEmbeddableInitialState
+ extends SerializedTitles,
+ SerializedTimeRange {
+ dataViewId?: string;
+}
+
+export type LogRateAnalysisEmbeddableRuntimeState = LogRateAnalysisEmbeddableState;
diff --git a/x-pack/plugins/aiops/public/embeddables/pattern_analysis/embeddable_pattern_analysis_factory.tsx b/x-pack/plugins/aiops/public/embeddables/pattern_analysis/embeddable_pattern_analysis_factory.tsx
index e7b1d6da3be61..d84043ea5f637 100644
--- a/x-pack/plugins/aiops/public/embeddables/pattern_analysis/embeddable_pattern_analysis_factory.tsx
+++ b/x-pack/plugins/aiops/public/embeddables/pattern_analysis/embeddable_pattern_analysis_factory.tsx
@@ -11,7 +11,6 @@ import {
} from '@kbn/aiops-log-pattern-analysis/constants';
import type { Reference } from '@kbn/content-management-utils';
import type { StartServicesAccessor } from '@kbn/core-lifecycle-browser';
-import { type DataPublicPluginStart } from '@kbn/data-plugin/public';
import type { DataView } from '@kbn/data-views-plugin/common';
import { DATA_VIEW_SAVED_OBJECT_TYPE } from '@kbn/data-views-plugin/common';
import type { ReactEmbeddableFactory } from '@kbn/embeddable-plugin/public';
@@ -37,32 +36,6 @@ import type {
PatternAnalysisEmbeddableState,
} from './types';
-export interface EmbeddablePatternAnalysisStartServices {
- data: DataPublicPluginStart;
-}
-
-export type EmbeddablePatternAnalysisType = typeof EMBEDDABLE_PATTERN_ANALYSIS_TYPE;
-
-export const getDependencies = async (
- getStartServices: StartServicesAccessor
-) => {
- const [
- { http, uiSettings, notifications, ...startServices },
- { lens, data, usageCollection, fieldFormats },
- ] = await getStartServices();
-
- return {
- http,
- uiSettings,
- data,
- notifications,
- lens,
- usageCollection,
- fieldFormats,
- ...startServices,
- };
-};
-
export const getPatternAnalysisEmbeddableFactory = (
getStartServices: StartServicesAccessor
) => {
@@ -87,20 +60,6 @@ export const getPatternAnalysisEmbeddableFactory = (
buildEmbeddable: async (state, buildApi, uuid, parentApi) => {
const [coreStart, pluginStart] = await getStartServices();
- const { http, uiSettings, notifications, ...startServices } = coreStart;
- const { lens, data, usageCollection, fieldFormats } = pluginStart;
-
- const deps = {
- http,
- uiSettings,
- data,
- notifications,
- lens,
- usageCollection,
- fieldFormats,
- ...startServices,
- };
-
const {
api: timeRangeApi,
comparators: timeRangeComparators,
@@ -119,8 +78,8 @@ export const getPatternAnalysisEmbeddableFactory = (
const blockingError = new BehaviorSubject(undefined);
const dataViews$ = new BehaviorSubject([
- await deps.data.dataViews.get(
- state.dataViewId ?? (await deps.data.dataViews.getDefaultId())
+ await pluginStart.data.dataViews.get(
+ state.dataViewId ?? (await pluginStart.data.dataViews.getDefaultId())
),
]);
diff --git a/x-pack/plugins/aiops/public/embeddables/pattern_analysis/pattern_analysys_component_wrapper.tsx b/x-pack/plugins/aiops/public/embeddables/pattern_analysis/pattern_analysis_component_wrapper.tsx
similarity index 100%
rename from x-pack/plugins/aiops/public/embeddables/pattern_analysis/pattern_analysys_component_wrapper.tsx
rename to x-pack/plugins/aiops/public/embeddables/pattern_analysis/pattern_analysis_component_wrapper.tsx
diff --git a/x-pack/plugins/aiops/public/embeddables/pattern_analysis/pattern_analysis_initializer.tsx b/x-pack/plugins/aiops/public/embeddables/pattern_analysis/pattern_analysis_initializer.tsx
index f44fff343fb50..ef185518638b8 100644
--- a/x-pack/plugins/aiops/public/embeddables/pattern_analysis/pattern_analysis_initializer.tsx
+++ b/x-pack/plugins/aiops/public/embeddables/pattern_analysis/pattern_analysis_initializer.tsx
@@ -33,6 +33,7 @@ import { useAiopsAppContext } from '../../hooks/use_aiops_app_context';
import { DataSourceContextProvider } from '../../hooks/use_data_source';
import type { PatternAnalysisEmbeddableRuntimeState } from './types';
import { PatternAnalysisSettings } from '../../components/log_categorization/log_categorization_for_embeddable/embeddable_menu';
+import { TimeFieldWarning } from '../../components/time_field_warning';
import { RandomSampler } from '../../components/log_categorization/sampling_menu';
import {
DEFAULT_PROBABILITY,
@@ -62,6 +63,7 @@ export const PatternAnalysisEmbeddableInitializer: FC {
const {
+ data: { dataViews },
unifiedSearch: {
ui: { IndexPatternSelect },
},
@@ -166,7 +168,7 @@ export const PatternAnalysisEmbeddableInitializer: FC
-
+
{
>
);
};
-
-const TimeFieldWarning = () => {
- return (
- <>
-
-
- {i18n.translate(
- 'xpack.aiops.logCategorization.embeddableMenu.timeFieldWarning.title.description',
- {
- defaultMessage: 'Pattern analysis can only be run on data views with a time field.',
- }
- )}
-
-
-
- >
- );
-};
diff --git a/x-pack/plugins/aiops/public/embeddables/pattern_analysis/types.ts b/x-pack/plugins/aiops/public/embeddables/pattern_analysis/types.ts
index f78934b9075f1..710e18823a2bb 100644
--- a/x-pack/plugins/aiops/public/embeddables/pattern_analysis/types.ts
+++ b/x-pack/plugins/aiops/public/embeddables/pattern_analysis/types.ts
@@ -14,18 +14,12 @@ import type {
SerializedTimeRange,
SerializedTitles,
} from '@kbn/presentation-publishing';
-import type { FC } from 'react';
import type { MinimumTimeRangeOption } from '../../components/log_categorization/log_categorization_for_embeddable/minimum_time_range';
import type {
RandomSamplerOption,
RandomSamplerProbability,
} from '../../components/log_categorization/sampling_menu/random_sampler';
-export type ViewComponent = FC<{
- interval: string;
- onRenderComplete?: () => void;
-}>;
-
export interface PatternAnalysisComponentApi {
dataViewId: PublishingSubject;
fieldName: PublishingSubject;
diff --git a/x-pack/plugins/aiops/public/hooks/use_aiops_app_context.ts b/x-pack/plugins/aiops/public/hooks/use_aiops_app_context.ts
index 03762a7ba70ba..c240ec90bc1df 100644
--- a/x-pack/plugins/aiops/public/hooks/use_aiops_app_context.ts
+++ b/x-pack/plugins/aiops/public/hooks/use_aiops_app_context.ts
@@ -5,7 +5,7 @@
* 2.0.
*/
-import { createContext, type FC, type PropsWithChildren, useContext } from 'react';
+import { createContext, type FC, useContext } from 'react';
import type { ObservabilityAIAssistantPublicStart } from '@kbn/observability-ai-assistant-plugin/public';
import type { IStorageWrapper } from '@kbn/kibana-utils-plugin/public';
@@ -24,17 +24,12 @@ import type {
ThemeServiceStart,
} from '@kbn/core/public';
import type { LensPublicStart } from '@kbn/lens-plugin/public';
-import { type EuiComboBoxProps } from '@elastic/eui/src/components/combo_box/combo_box';
-import { type DataView } from '@kbn/data-views-plugin/common';
-import type {
- FieldStatsProps,
- FieldStatsServices,
-} from '@kbn/unified-field-list/src/components/field_stats';
-import type { TimeRange as TimeRangeMs } from '@kbn/ml-date-picker';
import type { EmbeddableStart } from '@kbn/embeddable-plugin/public';
import type { CasesPublicStart } from '@kbn/cases-plugin/public';
import type { UsageCollectionSetup } from '@kbn/usage-collection-plugin/public';
import type { UiActionsStart } from '@kbn/ui-actions-plugin/public';
+import type { FieldStatsFlyoutProviderProps } from '@kbn/ml-field-stats-flyout/field_stats_flyout_provider';
+import type { UseFieldStatsTrigger } from '@kbn/ml-field-stats-flyout/use_field_stats_trigger';
/**
* AIOps app context value to be provided via React context.
@@ -98,7 +93,7 @@ export interface AiopsAppContextValue {
/**
* Used to create deep links to other plugins.
*/
- share: SharePluginStart;
+ share?: SharePluginStart;
/**
* Used to create lens embeddables.
*/
@@ -115,18 +110,8 @@ export interface AiopsAppContextValue {
* Deps for unified fields stats.
*/
fieldStats?: {
- useFieldStatsTrigger: () => {
- renderOption: EuiComboBoxProps['renderOption'];
- closeFlyout: () => void;
- };
- FieldStatsFlyoutProvider: FC<
- PropsWithChildren<{
- dataView: DataView;
- fieldStatsServices: FieldStatsServices;
- timeRangeMs?: TimeRangeMs;
- dslQuery?: FieldStatsProps['dslQuery'];
- }>
- >;
+ useFieldStatsTrigger: UseFieldStatsTrigger;
+ FieldStatsFlyoutProvider: FC;
};
embeddable?: EmbeddableStart;
cases?: CasesPublicStart;
diff --git a/x-pack/plugins/aiops/public/hooks/use_data_source.tsx b/x-pack/plugins/aiops/public/hooks/use_data_source.tsx
index 081e10a34de65..ef574a348b928 100644
--- a/x-pack/plugins/aiops/public/hooks/use_data_source.tsx
+++ b/x-pack/plugins/aiops/public/hooks/use_data_source.tsx
@@ -8,10 +8,10 @@
import type { FC, PropsWithChildren } from 'react';
import React, { createContext, useCallback, useContext, useEffect, useState } from 'react';
import type { DataView } from '@kbn/data-views-plugin/common';
+import type { DataViewsPublicPluginStart } from '@kbn/data-views-plugin/public';
import type { SavedSearch } from '@kbn/saved-search-plugin/public';
import { EuiEmptyPrompt } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n-react';
-import { useAiopsAppContext } from './use_aiops_app_context';
export const DataSourceContext = createContext({
get dataView(): never {
@@ -30,6 +30,7 @@ export interface DataViewAndSavedSearch {
}
export interface DataSourceContextProviderProps {
+ dataViews: DataViewsPublicPluginStart;
dataViewId?: string;
savedSearchId?: string;
/** Output resolves data view objects */
@@ -43,20 +44,14 @@ export interface DataSourceContextProviderProps {
* @constructor
*/
export const DataSourceContextProvider: FC> = ({
+ dataViews,
dataViewId,
- savedSearchId,
children,
onChange,
}) => {
const [value, setValue] = useState();
const [error, setError] = useState();
- const {
- data: { dataViews },
- // uiSettings,
- // savedSearch: savedSearchService,
- } = useAiopsAppContext();
-
/**
* Resolve data view or saved search if exists.
*/
diff --git a/x-pack/plugins/aiops/public/shared_components/change_point_detection.tsx b/x-pack/plugins/aiops/public/shared_components/change_point_detection.tsx
index 9afbd9e1c4c8d..53997219fd639 100644
--- a/x-pack/plugins/aiops/public/shared_components/change_point_detection.tsx
+++ b/x-pack/plugins/aiops/public/shared_components/change_point_detection.tsx
@@ -11,7 +11,6 @@ import type { CoreStart } from '@kbn/core-lifecycle-browser';
import { UI_SETTINGS } from '@kbn/data-service';
import type { TimeRange } from '@kbn/es-query';
import { DatePickerContextProvider } from '@kbn/ml-date-picker';
-import { KibanaRenderContextProvider } from '@kbn/react-kibana-context-render';
import { pick } from 'lodash';
import React, { useEffect, useMemo, useState, type FC } from 'react';
import type { Observable } from 'rxjs';
@@ -141,33 +140,34 @@ const ChangePointDetectionWrapper: FC = ({
width: 100%;
`}
>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
);
};
diff --git a/x-pack/plugins/aiops/public/shared_components/index.tsx b/x-pack/plugins/aiops/public/shared_components/index.tsx
index 1c5b85c4b79b6..b347d3ee24cac 100644
--- a/x-pack/plugins/aiops/public/shared_components/index.tsx
+++ b/x-pack/plugins/aiops/public/shared_components/index.tsx
@@ -11,6 +11,7 @@ import type { CoreStart } from '@kbn/core-lifecycle-browser';
import type { AiopsPluginStartDeps } from '../types';
import type { ChangePointDetectionSharedComponent } from './change_point_detection';
import type { PatternAnalysisSharedComponent } from './pattern_analysis';
+import type { LogRateAnalysisEmbeddableWrapper } from './log_rate_analysis_embeddable_wrapper';
const ChangePointDetectionLazy = dynamic(async () => import('./change_point_detection'));
@@ -37,3 +38,24 @@ export const getPatternAnalysisComponent = (
};
export type { PatternAnalysisSharedComponent } from './pattern_analysis';
+
+const LogRateAnalysisEmbeddableWrapperLazy = dynamic(
+ async () => import('./log_rate_analysis_embeddable_wrapper')
+);
+
+export const getLogRateAnalysisEmbeddableWrapperComponent = (
+ coreStart: CoreStart,
+ pluginStart: AiopsPluginStartDeps
+): LogRateAnalysisEmbeddableWrapper => {
+ return React.memo((props) => {
+ return (
+