[Logs] Use central log sources setting in Logs Explorer as the default data source (#190438)

## Summary

Implements https://github.com/elastic/logs-dev/issues/169.

This uses the new central log sources setting as the default data source
in the Logs Explorer. The `AllSelection` is now amended to use a set of
indices, this `AllSelection` can be defined by the consumer (or falls
back to a default). In the case of the Observability Logs Explorer this
value is resolved from the setting and used as the `AllSelection` passed
to the Logs Explorer controller.
This commit is contained in:
Kerry Gallagher 2024-08-22 17:00:53 +01:00 committed by GitHub
parent d673743aa4
commit 2d80214cf0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
33 changed files with 186 additions and 52 deletions

View file

@ -8,16 +8,18 @@
import { Dataset } from '../datasets';
import { DataSourceSelectionStrategy } from './types';
const SELECTION_TYPE = 'all' as const;
export class AllDatasetSelection implements DataSourceSelectionStrategy {
selectionType: 'all';
selectionType: typeof SELECTION_TYPE;
selection: {
dataset: Dataset;
};
private constructor() {
this.selectionType = 'all';
private constructor({ indices }: { indices: string }) {
this.selectionType = SELECTION_TYPE;
this.selection = {
dataset: Dataset.createAllLogsDataset(),
dataset: Dataset.createAllLogsDataset({ indices }),
};
}
@ -30,8 +32,13 @@ export class AllDatasetSelection implements DataSourceSelectionStrategy {
selectionType: this.selectionType,
};
}
public static getLocatorPlainSelection() {
return {
selectionType: SELECTION_TYPE,
};
}
public static create() {
return new AllDatasetSelection();
public static create({ indices }: { indices: string }) {
return new AllDatasetSelection({ indices });
}
}

View file

@ -11,9 +11,12 @@ import { SingleDatasetSelection } from './single_dataset_selection';
import { DataSourceSelectionPlain } from './types';
import { UnresolvedDatasetSelection } from './unresolved_dataset_selection';
export const hydrateDataSourceSelection = (dataSourceSelection: DataSourceSelectionPlain) => {
export const hydrateDataSourceSelection = (
dataSourceSelection: DataSourceSelectionPlain,
allSelection: AllDatasetSelection
) => {
if (dataSourceSelection.selectionType === 'all') {
return AllDatasetSelection.create();
return allSelection;
} else if (dataSourceSelection.selectionType === 'single') {
return SingleDatasetSelection.fromSelection(dataSourceSelection.selection);
} else if (dataSourceSelection.selectionType === 'dataView') {

View file

@ -72,9 +72,9 @@ export class Dataset {
return new Dataset({ ...dataset, title: datasetTitle }, parentIntegration);
}
public static createAllLogsDataset() {
public static createAllLogsDataset({ indices }: { indices: string }) {
return new Dataset({
name: 'logs-*-*' as IndexPattern,
name: indices as IndexPattern,
title: 'All logs',
iconType: 'pagesSelect',
});

View file

@ -64,7 +64,7 @@ const KibanaReactContext = createKibanaReactContext(coreMock);
const DataSourceSelectorTemplate: Story<DataSourceSelectorProps> = (args) => {
const [dataSourceSelection, setDataSourceSelection] = useState<DataSourceSelection>(() =>
AllDatasetSelection.create()
AllDatasetSelection.create({ indices: 'logs-*-*' })
);
const [search, setSearch] = useState<DataSourceSelectorSearchParams>({

View file

@ -40,6 +40,7 @@ import { DataViewsFilter } from './sub_components/data_view_filter';
export function DataSourceSelector({
datasets,
dataSourceSelection,
allSelection,
datasetsError,
dataViews,
dataViewCount,
@ -307,7 +308,11 @@ export function DataSourceSelector({
/>
<EuiHorizontalRule margin="none" />
<SelectorFooter>
<ShowAllLogsButton isSelected={isAllMode} onClick={selectAllLogs} />
<ShowAllLogsButton
isSelected={isAllMode}
onClick={selectAllLogs}
allSelection={allSelection}
/>
{isEsqlEnabled && <ESQLButton {...discoverEsqlUrlProps} />}
</SelectorFooter>
</SelectorPopover>

View file

@ -5,7 +5,7 @@
* 2.0.
*/
import { AllDatasetSelection } from '../../../../common/data_source_selection';
import { DEFAULT_ALL_SELECTION } from '../../../state_machines/logs_explorer_controller';
import { HashedCache } from '../../../../common/hashed_cache';
import { INTEGRATIONS_PANEL_ID, INTEGRATIONS_TAB_ID } from '../constants';
import { DataSourceSelectorSearchParams } from '../types';
@ -17,7 +17,8 @@ export const defaultSearch: DataSourceSelectorSearchParams = {
};
export const DEFAULT_CONTEXT: DefaultDataSourceSelectorContext = {
selection: AllDatasetSelection.create(),
selection: DEFAULT_ALL_SELECTION,
allSelection: DEFAULT_ALL_SELECTION,
searchCache: new HashedCache(),
panelId: INTEGRATIONS_PANEL_ID,
tabId: INTEGRATIONS_TAB_ID,

View file

@ -7,7 +7,6 @@
import { actions, assign, createMachine, raise } from 'xstate';
import {
AllDatasetSelection,
DataViewSelection,
isAllDatasetSelection,
isDataViewSelection,
@ -233,7 +232,7 @@ export const createPureDataSourceSelectorStateMachine = (
return {};
}),
storeAllSelection: assign((_context) => ({
selection: AllDatasetSelection.create(),
selection: _context.allSelection,
})),
storeSingleSelection: assign((_context, event) =>
event.type === 'SELECT_DATASET'

View file

@ -7,6 +7,7 @@
import { DataViewDescriptor } from '../../../../common/data_views/models/data_view_descriptor';
import { FilterDataViews, SearchDataViews } from '../../../hooks/use_data_views';
import {
AllDatasetSelection,
DataSourceSelection,
DataSourceSelectionChangeHandler,
} from '../../../../common/data_source_selection';
@ -23,6 +24,7 @@ import { DataViewsFilterParams } from '../../../state_machines/data_views';
export interface DefaultDataSourceSelectorContext {
selection: DataSourceSelection;
allSelection: AllDatasetSelection;
tabId: TabId;
panelId: PanelId;
searchCache: IHashedCache<PanelId | TabId, DataSourceSelectorSearchParams>;

View file

@ -15,6 +15,7 @@ import {
EuiFlexGroupProps,
} from '@elastic/eui';
import { getRouterLinkProps } from '@kbn/router-utils';
import { AllDatasetSelection } from '../../../../common';
import { DiscoverEsqlUrlProps } from '../../../hooks/use_esql';
import { createAllLogsItem } from '../utils';
import { showAllLogsLabel, tryEsql } from '../constants';
@ -22,6 +23,7 @@ import { showAllLogsLabel, tryEsql } from '../constants';
interface ShowAllLogsProps {
isSelected: boolean;
onClick(): void;
allSelection: AllDatasetSelection;
}
export const SelectorFooter = (props: EuiFlexGroupProps) => {
@ -32,8 +34,8 @@ export const SelectorFooter = (props: EuiFlexGroupProps) => {
);
};
export const ShowAllLogsButton = ({ isSelected, onClick }: ShowAllLogsProps) => {
const allLogs = createAllLogsItem();
export const ShowAllLogsButton = ({ isSelected, onClick, allSelection }: ShowAllLogsProps) => {
const allLogs = createAllLogsItem(allSelection);
return (
<EuiFlexItem grow={false}>

View file

@ -9,6 +9,7 @@ import { EuiContextMenuPanelId } from '@elastic/eui/src/components/context_menu/
import type {
DataSourceSelectionChangeHandler,
DataSourceSelection,
AllDatasetSelection,
} from '../../../common/data_source_selection';
import { SortOrder } from '../../../common/latest';
import { Dataset, Integration, IntegrationId } from '../../../common/datasets';
@ -39,6 +40,8 @@ import { DataViewsFilterParams } from '../../state_machines/data_views';
export interface DataSourceSelectorProps {
/* The generic data stream list */
datasets: Dataset[] | null;
/* Class to represent the current "All logs" selection */
allSelection: AllDatasetSelection;
/* Any error occurred to show when the user preview the generic data streams */
datasetsError: Error | null;
/* The current selection instance */

View file

@ -8,7 +8,8 @@
import React, { RefCallback } from 'react';
import { EuiContextMenuPanelDescriptor, EuiContextMenuPanelItemDescriptor } from '@elastic/eui';
import { PackageIcon } from '@kbn/fleet-plugin/public';
import { Dataset, Integration } from '../../../common/datasets';
import { AllDatasetSelection } from '../../../common';
import { Integration } from '../../../common/datasets';
import {
DATA_SOURCE_SELECTOR_WIDTH,
noDatasetsDescriptionLabel,
@ -78,12 +79,11 @@ export const buildIntegrationsTree = ({
);
};
export const createAllLogsItem = () => {
const allLogs = Dataset.createAllLogsDataset();
export const createAllLogsItem = (allSelection: AllDatasetSelection) => {
return {
'data-test-subj': 'dataSourceSelectorShowAllLogs',
iconType: allLogs.iconType,
name: allLogs.title,
iconType: allSelection.selection.dataset.iconType,
name: allSelection.selection.dataset.title,
};
};

View file

@ -10,8 +10,12 @@ import { getDevToolsOptions } from '@kbn/xstate-utils';
import equal from 'fast-deep-equal';
import { distinctUntilChanged, from, map, shareReplay, Subject } from 'rxjs';
import { interpret } from 'xstate';
import { AllDatasetSelection } from '../../common';
import { DatasetsService } from '../services/datasets';
import { createLogsExplorerControllerStateMachine } from '../state_machines/logs_explorer_controller';
import {
createLogsExplorerControllerStateMachine,
DEFAULT_CONTEXT,
} from '../state_machines/logs_explorer_controller';
import { LogsExplorerStartDeps } from '../types';
import { LogsExplorerCustomizations } from '../customizations/types';
import { createDataServiceProxy } from './custom_data_service';
@ -33,7 +37,7 @@ interface Dependencies {
plugins: LogsExplorerStartDeps;
}
type InitialState = LogsExplorerPublicStateUpdate;
type InitialState = LogsExplorerPublicStateUpdate & { allSelection?: AllDatasetSelection };
export const createLogsExplorerControllerFactory =
({ core, plugins }: Dependencies) =>
@ -66,15 +70,19 @@ export const createLogsExplorerControllerFactory =
timefilter: customData.query.timefilter.timefilter,
urlStateStorage: customMemoryUrlStateStorage,
};
const allSelection = initialState?.allSelection ?? DEFAULT_CONTEXT.allSelection;
const initialContext = getContextFromPublicState(initialState ?? {});
const initialContext = getContextFromPublicState(initialState ?? {}, allSelection);
const publicEvents$ = new Subject<LogsExplorerPublicEvent>();
const machine = createLogsExplorerControllerStateMachine({
datasetsClient,
dataViews,
events: customizations.events,
initialContext,
initialContext: {
...initialContext,
allSelection,
},
query: discoverServices.data.query,
toasts: core.notifications.toasts,
uiSettings: customUiSettings,

View file

@ -6,6 +6,7 @@
*/
import {
AllDatasetSelection,
availableControlsPanels,
controlPanelConfigs,
ControlPanels,
@ -37,7 +38,8 @@ export const getPublicStateFromContext = (
};
export const getContextFromPublicState = (
publicState: LogsExplorerPublicStateUpdate
publicState: LogsExplorerPublicStateUpdate,
allSelection: AllDatasetSelection
): LogsExplorerControllerContext => ({
...DEFAULT_CONTEXT,
chart: {
@ -47,7 +49,7 @@ export const getContextFromPublicState = (
controlPanels: getControlPanelsFromPublicControlsState(publicState.controls),
dataSourceSelection:
publicState.dataSourceSelection != null
? hydrateDataSourceSelection(publicState.dataSourceSelection)
? hydrateDataSourceSelection(publicState.dataSourceSelection, allSelection)
: DEFAULT_CONTEXT.dataSourceSelection,
grid: {
...DEFAULT_CONTEXT.grid,

View file

@ -23,9 +23,8 @@ interface CustomDataSourceSelectorProps {
}
export const CustomDataSourceSelector = withProviders(({ logsExplorerControllerStateService }) => {
const { dataSourceSelection, handleDataSourceSelectionChange } = useDataSourceSelection(
logsExplorerControllerStateService
);
const { dataSourceSelection, handleDataSourceSelectionChange, allSelection } =
useDataSourceSelection(logsExplorerControllerStateService);
const {
error: integrationsError,
@ -70,6 +69,7 @@ export const CustomDataSourceSelector = withProviders(({ logsExplorerControllerS
<DataSourceSelector
datasets={datasets}
dataSourceSelection={dataSourceSelection}
allSelection={allSelection}
datasetsError={datasetsError}
dataViews={dataViews}
dataViewCount={dataViewCount}

View file

@ -16,6 +16,9 @@ export const useDataSourceSelection = (
const dataSourceSelection = useSelector(logsExplorerControllerStateService, (state) => {
return state.context.dataSourceSelection;
});
const allSelection = useSelector(logsExplorerControllerStateService, (state) => {
return state.context.allSelection;
});
const handleDataSourceSelectionChange: DataSourceSelectionChangeHandler = useCallback(
(data) => {
@ -24,5 +27,5 @@ export const useDataSourceSelection = (
[logsExplorerControllerStateService]
);
return { dataSourceSelection, handleDataSourceSelectionChange };
return { dataSourceSelection, allSelection, handleDataSourceSelectionChange };
};

View file

@ -20,6 +20,7 @@ export type {
LogsExplorerCustomizationEvents,
} from './customizations/types';
export type { LogsExplorerControllerContext } from './state_machines/logs_explorer_controller';
export { DEFAULT_ALL_SELECTION } from './state_machines/logs_explorer_controller/src/default_all_selection';
export type { LogsExplorerPluginSetup, LogsExplorerPluginStart } from './types';
export {
getDiscoverColumnsFromDisplayOptions,

View file

@ -0,0 +1,10 @@
/*
* 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 { AllDatasetSelection } from '../../../../common';
export const DEFAULT_ALL_SELECTION = AllDatasetSelection.create({ indices: 'logs-*-*' });

View file

@ -11,11 +11,12 @@ import {
DEFAULT_ROWS_PER_PAGE,
LOG_LEVEL_FIELD,
} from '../../../../common/constants';
import { AllDatasetSelection } from '../../../../common/data_source_selection';
import { DefaultLogsExplorerControllerState } from './types';
import { DEFAULT_ALL_SELECTION } from './default_all_selection';
export const DEFAULT_CONTEXT: DefaultLogsExplorerControllerState = {
dataSourceSelection: AllDatasetSelection.create(),
dataSourceSelection: DEFAULT_ALL_SELECTION,
allSelection: DEFAULT_ALL_SELECTION,
grid: {
columns: DEFAULT_COLUMNS,
rows: {

View file

@ -6,5 +6,6 @@
*/
export * from './defaults';
export * from './default_all_selection';
export * from './state_machine';
export * from './types';

View file

@ -14,7 +14,6 @@ import { OBSERVABILITY_LOGS_EXPLORER_ALLOWED_DATA_VIEWS_ID } from '@kbn/manageme
import type { LogsExplorerCustomizations, LogsExplorerPublicEvent } from '../../../controller';
import { ControlPanelRT } from '../../../../common/control_panels';
import {
AllDatasetSelection,
isDataSourceSelection,
isDataViewSelection,
} from '../../../../common/data_source_selection';
@ -271,7 +270,7 @@ export const createPureLogsExplorerControllerStateMachine = (
{
actions: {
storeDefaultSelection: actions.assign((_context) => ({
dataSourceSelection: AllDatasetSelection.create(),
dataSourceSelection: _context.allSelection,
})),
storeDataSourceSelection: actions.assign((_context, event) =>
'data' in event && isDataSourceSelection(event.data)

View file

@ -16,6 +16,7 @@ import { DoneInvokeEvent } from 'xstate';
import type { DataTableRecord } from '@kbn/discover-utils/src/types';
import { ControlPanels, DisplayOptions } from '../../../../common';
import type {
AllDatasetSelection,
DatasetSelection,
DataSourceSelection,
DataViewSelection,
@ -25,6 +26,9 @@ export interface WithDataSourceSelection {
dataSourceSelection: DataSourceSelection;
}
export interface WithAllSelection {
allSelection: AllDatasetSelection;
}
export interface WithControlPanelGroupAPI {
controlGroupAPI: ControlGroupAPI;
}
@ -46,6 +50,7 @@ export interface WithDataTableRecord {
}
export type DefaultLogsExplorerControllerState = WithDataSourceSelection &
WithAllSelection &
WithQueryState &
WithDisplayOptions &
WithDataTableRecord;
@ -53,11 +58,16 @@ export type DefaultLogsExplorerControllerState = WithDataSourceSelection &
export type LogsExplorerControllerTypeState =
| {
value: 'uninitialized';
context: WithDataSourceSelection & WithControlPanels & WithQueryState & WithDisplayOptions;
context: WithDataSourceSelection &
WithAllSelection &
WithControlPanels &
WithQueryState &
WithDisplayOptions;
}
| {
value: 'initializingSelection';
context: WithDataSourceSelection &
WithAllSelection &
WithControlPanels &
WithQueryState &
WithDisplayOptions &
@ -67,6 +77,7 @@ export type LogsExplorerControllerTypeState =
| {
value: 'initializingDataset';
context: WithDataSourceSelection &
WithAllSelection &
WithControlPanels &
WithQueryState &
WithDisplayOptions &
@ -75,6 +86,7 @@ export type LogsExplorerControllerTypeState =
| {
value: 'initializingDataView';
context: WithDataSourceSelection &
WithAllSelection &
WithControlPanels &
WithQueryState &
WithDisplayOptions &
@ -83,6 +95,7 @@ export type LogsExplorerControllerTypeState =
| {
value: 'initializingControlPanels';
context: WithDataSourceSelection &
WithAllSelection &
WithControlPanels &
WithQueryState &
WithDisplayOptions &
@ -91,6 +104,7 @@ export type LogsExplorerControllerTypeState =
| {
value: 'initialized';
context: WithDataSourceSelection &
WithAllSelection &
WithControlPanels &
WithQueryState &
WithDisplayOptions &
@ -100,6 +114,7 @@ export type LogsExplorerControllerTypeState =
| {
value: 'initialized.dataSourceSelection.idle';
context: WithDataSourceSelection &
WithAllSelection &
WithControlPanels &
WithQueryState &
WithDisplayOptions &
@ -109,6 +124,7 @@ export type LogsExplorerControllerTypeState =
| {
value: 'initialized.dataSourceSelection.changingDataView';
context: WithDataSourceSelection &
WithAllSelection &
WithControlPanels &
WithQueryState &
WithDisplayOptions &
@ -118,6 +134,7 @@ export type LogsExplorerControllerTypeState =
| {
value: 'initialized.dataSourceSelection.creatingAdHocDataView';
context: WithDataSourceSelection &
WithAllSelection &
WithControlPanels &
WithQueryState &
WithDisplayOptions &
@ -127,6 +144,7 @@ export type LogsExplorerControllerTypeState =
| {
value: 'initialized.controlGroups.uninitialized';
context: WithDataSourceSelection &
WithAllSelection &
WithControlPanels &
WithQueryState &
WithDisplayOptions &
@ -136,6 +154,7 @@ export type LogsExplorerControllerTypeState =
| {
value: 'initialized.controlGroups.idle';
context: WithDataSourceSelection &
WithAllSelection &
WithControlPanelGroupAPI &
WithControlPanels &
WithQueryState &
@ -146,6 +165,7 @@ export type LogsExplorerControllerTypeState =
| {
value: 'initialized.controlGroups.updatingControlPanels';
context: WithDataSourceSelection &
WithAllSelection &
WithControlPanelGroupAPI &
WithControlPanels &
WithQueryState &

View file

@ -6,11 +6,11 @@
*/
import type { LocatorDefinition, LocatorPublic } from '@kbn/share-plugin/public';
import { AllDatasetSelection } from '@kbn/logs-explorer-plugin/common';
import {
AllDatasetsLocatorParams,
ALL_DATASETS_LOCATOR_ID,
} from '@kbn/deeplinks-observability/locators';
import { AllDatasetSelection } from '@kbn/logs-explorer-plugin/common';
import { ObsLogsExplorerLocatorDependencies } from './types';
import { constructLocatorPath } from './utils';
@ -25,7 +25,7 @@ export class AllDatasetsLocatorDefinition implements LocatorDefinition<AllDatase
const { useHash } = this.deps;
return constructLocatorPath({
dataSourceSelection: AllDatasetSelection.create().toPlainSelection(),
dataSourceSelection: AllDatasetSelection.getLocatorPlainSelection(),
locatorParams: params,
useHash,
});

View file

@ -20,7 +20,8 @@
"slo",
"share",
"kibanaUtils",
"dataQuality"
"dataQuality",
"logsDataAccess"
],
"optionalPlugins": [
"serverless",

View file

@ -63,7 +63,8 @@ export const AlertsPopover = () => {
) {
const { logsExplorerState } = pageState.context;
const index = hydrateDataSourceSelection(
logsExplorerState.dataSourceSelection
logsExplorerState.dataSourceSelection,
pageState.context.allSelection
).toDataviewSpec();
return triggersActionsUi.getAddRuleFlyout<ThresholdRuleTypeParams>({
@ -92,7 +93,8 @@ export const AlertsPopover = () => {
if (isCreateSLOFlyoutOpen && pageState.matches({ initialized: 'validLogsExplorerState' })) {
const { logsExplorerState } = pageState.context;
const dataView = hydrateDataSourceSelection(
logsExplorerState.dataSourceSelection
logsExplorerState.dataSourceSelection,
pageState.context.allSelection
).toDataviewSpec();
const query =
logsExplorerState?.query && 'query' in logsExplorerState.query

View file

@ -30,7 +30,6 @@ export const ConnectedDiscoverLink = React.memo(() => {
} = useKibanaContextForPlugin();
const [pageState] = useActor(useObservabilityLogsExplorerPageStateContext());
if (pageState.matches({ initialized: 'validLogsExplorerState' })) {
return <DiscoverLinkForValidState discover={discover} pageState={pageState} />;
} else {
@ -47,7 +46,7 @@ export const DiscoverLinkForValidState = React.memo(
({
discover,
pageState: {
context: { logsExplorerState },
context: { logsExplorerState, allSelection },
},
}: {
discover: DiscoverStart;
@ -55,7 +54,8 @@ export const DiscoverLinkForValidState = React.memo(
}) => {
const discoverLinkParams = useMemo<DiscoverAppLocatorParams>(() => {
const index = hydrateDataSourceSelection(
logsExplorerState.dataSourceSelection
logsExplorerState.dataSourceSelection,
allSelection
).toDataviewSpec();
return {
breakdownField: logsExplorerState.chart.breakdownField ?? undefined,
@ -70,7 +70,7 @@ export const DiscoverLinkForValidState = React.memo(
timeRange: logsExplorerState.time,
dataViewSpec: index,
};
}, [logsExplorerState]);
}, [allSelection, logsExplorerState]);
return <DiscoverLink discover={discover} discoverLinkParams={discoverLinkParams} />;
}

View file

@ -27,8 +27,17 @@ import { useKibanaContextForPlugin } from '../../utils/use_kibana';
export const ObservabilityLogsExplorerMainRoute = () => {
const { services } = useKibanaContextForPlugin();
const { logsExplorer, serverless, chrome, notifications, appParams, analytics, i18n, theme } =
services;
const {
logsExplorer,
serverless,
chrome,
notifications,
appParams,
analytics,
i18n,
theme,
logsDataAccess,
} = services;
const { history } = appParams;
useBreadcrumbs(noBreadcrumbs, chrome, serverless);
@ -51,6 +60,7 @@ export const ObservabilityLogsExplorerMainRoute = () => {
urlStateStorageContainer={urlStateStorageContainer}
timeFilterService={services.data.query.timefilter.timefilter}
analytics={services.analytics}
logSourcesService={logsDataAccess.services.logSourcesService}
>
<LogsExplorerTopNavMenu />
<LazyOriginInterpreter

View file

@ -0,0 +1,23 @@
/*
* 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 { AllDatasetSelection } from '@kbn/logs-explorer-plugin/common';
import type { LogSourcesService } from '@kbn/logs-data-access-plugin/common/types';
import { InvokeCreator } from 'xstate';
import type { ObservabilityLogsExplorerContext, ObservabilityLogsExplorerEvent } from './types';
export const initializeAllSelection =
({
logSourcesService,
}: {
logSourcesService: LogSourcesService;
}): InvokeCreator<ObservabilityLogsExplorerContext, ObservabilityLogsExplorerEvent> =>
async (context) => {
const logSources = await logSourcesService.getLogSources();
const indices = logSources.map((logSource) => logSource.indexPattern).join(',');
return AllDatasetSelection.create({ indices });
};

View file

@ -19,7 +19,7 @@ export const createController =
(context, event) =>
(send) => {
createLogsExplorerController({
initialState: context.initialLogsExplorerState,
initialState: { ...context.initialLogsExplorerState, allSelection: context.allSelection },
}).then((controller) => {
send({
type: 'CONTROLLER_CREATED',

View file

@ -5,8 +5,10 @@
* 2.0.
*/
import { DEFAULT_ALL_SELECTION } from '@kbn/logs-explorer-plugin/public';
import { CommonObservabilityLogsExplorerContext } from './types';
export const DEFAULT_CONTEXT: CommonObservabilityLogsExplorerContext = {
initialLogsExplorerState: {},
allSelection: DEFAULT_ALL_SELECTION,
};

View file

@ -11,6 +11,7 @@ import { CreateLogsExplorerController } from '@kbn/logs-explorer-plugin/public';
import { actions, createMachine, InterpreterFrom } from 'xstate';
import { TimefilterContract } from '@kbn/data-plugin/public';
import { AnalyticsServiceStart } from '@kbn/core-analytics-browser';
import { LogSourcesService } from '@kbn/logs-data-access-plugin/common/types';
import { DEFAULT_CONTEXT } from './defaults';
import {
ObservabilityLogsExplorerContext,
@ -25,6 +26,7 @@ import {
} from './controller_service';
import { initializeFromTimeFilterService } from './time_filter_service';
import { createDataReceivedTelemetryEventEmitter } from './telemetry_events';
import { initializeAllSelection } from './all_selection_service';
export const createPureObservabilityLogsExplorerStateMachine = (
initialContext: ObservabilityLogsExplorerContext
@ -42,7 +44,17 @@ export const createPureObservabilityLogsExplorerStateMachine = (
initial: 'uninitialized',
states: {
uninitialized: {
always: 'initializingFromTimeFilterService',
always: 'initializeAllSelection',
},
initializeAllSelection: {
invoke: {
src: 'initializeAllSelection',
onDone: {
target: 'initializingFromTimeFilterService',
actions: ['storeAllSelection'],
},
onError: 'initializingFromTimeFilterService',
},
},
initializingFromTimeFilterService: {
invoke: {
@ -119,6 +131,13 @@ export const createPureObservabilityLogsExplorerStateMachine = (
? { controller: event.controller }
: {};
}),
storeAllSelection: actions.assign((context, event) => {
return 'data' in event
? {
allSelection: event.data,
}
: {};
}),
storeInitialTimeFilter: actions.assign((context, event) => {
return 'time' in event &&
'refreshInterval' in event &&
@ -162,6 +181,7 @@ export interface ObservabilityLogsExplorerStateMachineDependencies {
toasts: IToasts;
urlStateStorageContainer: IKbnUrlStateStorage;
analytics: AnalyticsServiceStart;
logSourcesService: LogSourcesService;
}
export const createObservabilityLogsExplorerStateMachine = ({
@ -171,6 +191,7 @@ export const createObservabilityLogsExplorerStateMachine = ({
createLogsExplorerController,
timeFilterService,
analytics,
logSourcesService,
}: ObservabilityLogsExplorerStateMachineDependencies) =>
createPureObservabilityLogsExplorerStateMachine(initialContext).withConfig({
actions: {
@ -181,6 +202,7 @@ export const createObservabilityLogsExplorerStateMachine = ({
createController: createController({ createLogsExplorerController }),
initializeFromTimeFilterService: initializeFromTimeFilterService({ timeFilterService }),
initializeFromUrl: initializeFromUrl({ urlStateStorageContainer, toastsService: toasts }),
initializeAllSelection: initializeAllSelection({ logSourcesService }),
subscribeToLogsExplorerState,
subscribeToLogsExplorerPublicEvents,
},

View file

@ -6,16 +6,19 @@
*/
import { QueryState } from '@kbn/data-plugin/common';
import { AllDatasetSelection } from '@kbn/logs-explorer-plugin/common';
import {
LogsExplorerController,
LogsExplorerPublicState,
LogsExplorerPublicStateUpdate,
} from '@kbn/logs-explorer-plugin/public';
import { DoneInvokeEvent } from 'xstate';
export type ObservabilityLogsExplorerContext = ObservabilityLogsExplorerTypeState['context'];
export interface CommonObservabilityLogsExplorerContext {
initialLogsExplorerState: LogsExplorerPublicStateUpdate;
allSelection: AllDatasetSelection;
}
export interface WithLogsExplorerState {
@ -47,7 +50,8 @@ export type ObservabilityLogsExplorerEvent =
| {
type: 'LOGS_EXPLORER_DATA_RECEIVED';
rowCount: number;
};
}
| DoneInvokeEvent<AllDatasetSelection>;
export type ObservabilityLogsExplorerTypeState =
| {

View file

@ -26,6 +26,7 @@ import { DataViewsPublicPluginStart } from '@kbn/data-views-plugin/public';
import { DataViewEditorStart } from '@kbn/data-view-editor-plugin/public';
import { LensPublicStart } from '@kbn/lens-plugin/public';
import { SloPublicStart } from '@kbn/slo-plugin/public';
import { LogsDataAccessPluginStart } from '@kbn/logs-data-access-plugin/public';
import {
ObservabilityLogsExplorerLocators,
ObservabilityLogsExplorerLocationState,
@ -49,6 +50,7 @@ export interface ObservabilityLogsExplorerStartDeps {
discover: DiscoverStart;
logsExplorer: LogsExplorerPluginStart;
logsShared: LogsSharedClientStartExports;
logsDataAccess: LogsDataAccessPluginStart;
observabilityAIAssistant?: ObservabilityAIAssistantPublicStart;
observabilityShared: ObservabilitySharedPluginStart;
slo: SloPublicStart;

View file

@ -49,6 +49,7 @@
"@kbn/es-query",
"@kbn/core-analytics-browser",
"@kbn/react-hooks",
"@kbn/logs-data-access-plugin",
],
"exclude": [
"target/**/*"