diff --git a/x-pack/plugins/enterprise_search/kibana.jsonc b/x-pack/plugins/enterprise_search/kibana.jsonc index 0dc2562ff2fe3..91221ef0ed95e 100644 --- a/x-pack/plugins/enterprise_search/kibana.jsonc +++ b/x-pack/plugins/enterprise_search/kibana.jsonc @@ -15,6 +15,7 @@ "features", "licensing", "logsShared", + "logsDataAccess", "esUiShared", "navigation", ], diff --git a/x-pack/plugins/fleet/kibana.jsonc b/x-pack/plugins/fleet/kibana.jsonc index 54b4a4928594c..dded2caf4c7e2 100644 --- a/x-pack/plugins/fleet/kibana.jsonc +++ b/x-pack/plugins/fleet/kibana.jsonc @@ -24,7 +24,8 @@ "files", "uiActions", "dashboard", - "fieldsMetadata" + "fieldsMetadata", + "logsDataAccess" ], "optionalPlugins": [ "features", diff --git a/x-pack/plugins/observability_solution/infra/common/source_configuration/defaults.ts b/x-pack/plugins/observability_solution/infra/common/source_configuration/defaults.ts index ac3724c80d70a..05988909e3f36 100644 --- a/x-pack/plugins/observability_solution/infra/common/source_configuration/defaults.ts +++ b/x-pack/plugins/observability_solution/infra/common/source_configuration/defaults.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { LOGS_INDEX_PATTERN, METRICS_INDEX_PATTERN } from '../constants'; +import { METRICS_INDEX_PATTERN } from '../constants'; import { InfraSourceConfiguration } from './source_configuration'; export const defaultSourceConfiguration: InfraSourceConfiguration = { @@ -13,8 +13,7 @@ export const defaultSourceConfiguration: InfraSourceConfiguration = { description: '', metricAlias: METRICS_INDEX_PATTERN, logIndices: { - type: 'index_name', - indexName: LOGS_INDEX_PATTERN, + type: 'kibana_advanced_setting', }, inventoryDefaultView: '0', metricsExplorerDefaultView: '0', diff --git a/x-pack/plugins/observability_solution/infra/common/source_configuration/source_configuration.ts b/x-pack/plugins/observability_solution/infra/common/source_configuration/source_configuration.ts index 116c30d8274e3..e9779c192788d 100644 --- a/x-pack/plugins/observability_solution/infra/common/source_configuration/source_configuration.ts +++ b/x-pack/plugins/observability_solution/infra/common/source_configuration/source_configuration.ts @@ -80,7 +80,16 @@ export const logIndexNameReferenceRT = rt.type({ }); export type LogIndexNameReference = rt.TypeOf; -export const logIndexReferenceRT = rt.union([logIndexPatternReferenceRT, logIndexNameReferenceRT]); +// Kibana advanced setting +export const logSourcesKibanaAdvancedSettingRT = rt.type({ + type: rt.literal('kibana_advanced_setting'), +}); + +export const logIndexReferenceRT = rt.union([ + logIndexPatternReferenceRT, + logIndexNameReferenceRT, + logSourcesKibanaAdvancedSettingRT, +]); export type LogIndexReference = rt.TypeOf; export const SourceConfigurationRT = rt.type({ diff --git a/x-pack/plugins/observability_solution/infra/kibana.jsonc b/x-pack/plugins/observability_solution/infra/kibana.jsonc index 973acf3e75d55..cf73b1636d93e 100644 --- a/x-pack/plugins/observability_solution/infra/kibana.jsonc +++ b/x-pack/plugins/observability_solution/infra/kibana.jsonc @@ -34,7 +34,8 @@ "unifiedSearch", "usageCollection", "visTypeTimeseries", - "apmDataAccess" + "apmDataAccess", + "logsDataAccess" ], "optionalPlugins": [ "spaces", diff --git a/x-pack/plugins/observability_solution/infra/public/pages/logs/settings/indices_configuration_form_state.ts b/x-pack/plugins/observability_solution/infra/public/pages/logs/settings/indices_configuration_form_state.ts index 46b5ce97ee4ca..581d8d3011cd6 100644 --- a/x-pack/plugins/observability_solution/infra/public/pages/logs/settings/indices_configuration_form_state.ts +++ b/x-pack/plugins/observability_solution/infra/public/pages/logs/settings/indices_configuration_form_state.ts @@ -12,6 +12,8 @@ import { LogDataViewReference, LogIndexNameReference, logIndexNameReferenceRT, + LogSourcesKibanaAdvancedSettingReference, + logSourcesKibanaAdvancedSettingRT, } from '@kbn/logs-shared-plugin/common'; import { useKibanaIndexPatternService } from '../../../hooks/use_kibana_index_patterns'; import { useFormElement } from './form_elements'; @@ -22,7 +24,11 @@ import { validateStringNoSpaces, } from './validation_errors'; -export type LogIndicesFormState = LogIndexNameReference | LogDataViewReference | undefined; +export type LogIndicesFormState = + | LogIndexNameReference + | LogDataViewReference + | LogSourcesKibanaAdvancedSettingReference + | undefined; export const useLogIndicesFormElement = (initialValue: LogIndicesFormState) => { const indexPatternService = useKibanaIndexPatternService(); @@ -35,6 +41,8 @@ export const useLogIndicesFormElement = (initialValue: LogIndicesFormState) => { () => async (logIndices) => { if (logIndices == null) { return validateStringNotEmpty('log data view', ''); + } else if (logSourcesKibanaAdvancedSettingRT.is(logIndices)) { + return []; } else if (logIndexNameReferenceRT.is(logIndices)) { return [ ...validateStringNotEmpty('log indices', logIndices.indexName), diff --git a/x-pack/plugins/observability_solution/infra/public/pages/logs/settings/indices_configuration_panel.tsx b/x-pack/plugins/observability_solution/infra/public/pages/logs/settings/indices_configuration_panel.tsx index bcde2cf84bb4a..0aad03315c8e1 100644 --- a/x-pack/plugins/observability_solution/infra/public/pages/logs/settings/indices_configuration_panel.tsx +++ b/x-pack/plugins/observability_solution/infra/public/pages/logs/settings/indices_configuration_panel.tsx @@ -14,6 +14,7 @@ import { LogDataViewReference, logDataViewReferenceRT, LogIndexReference, + logSourcesKibanaAdvancedSettingRT, } from '@kbn/logs-shared-plugin/common'; import { EuiCallOut } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; @@ -27,6 +28,7 @@ import { FormElement, isFormElementForType } from './form_elements'; import { IndexNamesConfigurationPanel } from './index_names_configuration_panel'; import { IndexPatternConfigurationPanel } from './index_pattern_configuration_panel'; import { FormValidationError } from './validation_errors'; +import { KibanaAdvancedSettingConfigurationPanel } from './kibana_advanced_setting_configuration_panel'; export const IndicesConfigurationPanel = React.memo<{ isLoading: boolean; @@ -75,6 +77,17 @@ export const IndicesConfigurationPanel = React.memo<{ }); }, [indicesFormElement, trackChangeIndexSourceType]); + const changeToKibanaAdvancedSettingType = useCallback(() => { + // This is always a readonly value, synced with the setting, we just reset back to the correct type. + indicesFormElement.updateValue(() => ({ + type: 'kibana_advanced_setting', + })); + + trackChangeIndexSourceType({ + metric: 'configuration_switch_to_kibana_advanced_setting_reference', + }); + }, [indicesFormElement, trackChangeIndexSourceType]); + useEffect(() => { const getNumberOfInfraRules = async () => { if (http) { @@ -107,6 +120,34 @@ export const IndicesConfigurationPanel = React.memo<{ ), }} > + {' '} + +

+ +

+ + } + name="kibanaAdvancedSetting" + value="kibanaAdvancedSetting" + checked={isKibanaAdvancedSettingFormElement(indicesFormElement)} + onChange={changeToKibanaAdvancedSettingType} + disabled={isReadOnly} + > + {isKibanaAdvancedSettingFormElement(indicesFormElement) && ( + + )} +
+ @@ -134,15 +175,14 @@ export const IndicesConfigurationPanel = React.memo<{ )} -

@@ -152,6 +192,7 @@ export const IndicesConfigurationPanel = React.memo<{ checked={isIndexNamesFormElement(indicesFormElement)} onChange={changeToIndexNameType} disabled={isReadOnly} + data-test-subj="logIndicesCheckableCard" > {isIndexNamesFormElement(indicesFormElement) && ( ; +}> = ({ isLoading, isReadOnly, advancedSettingFormElement }) => { + const { + services: { application, logsDataAccess }, + } = useKibanaContextForPlugin(); + + useTrackPageview({ app: 'infra_logs', path: 'log_source_configuration_kibana_advanced_setting' }); + useTrackPageview({ + app: 'infra_logs', + path: 'log_source_configuration_kibana_advanced_setting', + delay: 15000, + }); + + const advancedSettingsHref = useMemo( + () => getKibanaAdvancedSettingsHref(application), + [application] + ); + + const [logSourcesSettingValue, setLogSourcesSettingValue] = useState( + undefined + ); + + const [getLogSourcesRequest, getLogSources] = useTrackedPromise( + { + cancelPreviousOn: 'resolution', + createPromise: async () => { + return await logsDataAccess.services.logSourcesService.getLogSources(); + }, + onResolve: (response) => { + setLogSourcesSettingValue(response.map((logSource) => logSource.indexPattern).join(',')); + }, + }, + [] + ); + + const isLoadingLogSourcesSetting = useMemo( + () => getLogSourcesRequest.state === 'pending', + [getLogSourcesRequest.state] + ); + + useEffect(() => { + getLogSources(); + }, [getLogSources]); + + return ( + <> + + + + } + description={ + + + + ), + }} + /> + } + > + + } + label={ + + } + {...getFormRowProps(advancedSettingFormElement)} + > + + + + + ); +}; diff --git a/x-pack/plugins/observability_solution/infra/public/pages/logs/settings/source_configuration_form_state.tsx b/x-pack/plugins/observability_solution/infra/public/pages/logs/settings/source_configuration_form_state.tsx index 5ea244e5e0a52..01035f8259a0f 100644 --- a/x-pack/plugins/observability_solution/infra/public/pages/logs/settings/source_configuration_form_state.tsx +++ b/x-pack/plugins/observability_solution/infra/public/pages/logs/settings/source_configuration_form_state.tsx @@ -19,8 +19,7 @@ export const useLogSourceConfigurationFormState = (logViewAttributes?: LogViewAt useMemo( () => logViewAttributes?.logIndices ?? { - type: 'index_name', - indexName: '', + type: 'kibana_advanced_setting', }, [logViewAttributes] ) diff --git a/x-pack/plugins/observability_solution/infra/public/types.ts b/x-pack/plugins/observability_solution/infra/public/types.ts index 982f191941ab4..d7a7d339f41be 100644 --- a/x-pack/plugins/observability_solution/infra/public/types.ts +++ b/x-pack/plugins/observability_solution/infra/public/types.ts @@ -49,6 +49,7 @@ import type { CloudSetup } from '@kbn/cloud-plugin/public'; import type { LicenseManagementUIPluginSetup } from '@kbn/license-management-plugin/public'; import type { ServerlessPluginStart } from '@kbn/serverless/public'; import type { DashboardStart } from '@kbn/dashboard-plugin/public'; +import { LogsDataAccessPluginStart } from '@kbn/logs-data-access-plugin/public'; import type { UnwrapPromise } from '../common/utility_types'; import { InventoryViewsServiceStart } from './services/inventory_views'; import { MetricsExplorerViewsServiceStart } from './services/metrics_explorer_views'; @@ -95,6 +96,7 @@ export interface InfraClientStartDeps { embeddable?: EmbeddableStart; lens: LensPublicStart; logsShared: LogsSharedClientStartExports; + logsDataAccess: LogsDataAccessPluginStart; ml?: MlPluginStart; observability: ObservabilityPublicStart; observabilityShared: ObservabilitySharedPluginStart; diff --git a/x-pack/plugins/observability_solution/infra/server/lib/adapters/framework/adapter_types.ts b/x-pack/plugins/observability_solution/infra/server/lib/adapters/framework/adapter_types.ts index 8fe4101d7ebca..7b068424a7cc8 100644 --- a/x-pack/plugins/observability_solution/infra/server/lib/adapters/framework/adapter_types.ts +++ b/x-pack/plugins/observability_solution/infra/server/lib/adapters/framework/adapter_types.ts @@ -38,6 +38,7 @@ import { ApmDataAccessPluginSetup, ApmDataAccessPluginStart, } from '@kbn/apm-data-access-plugin/server'; +import { LogsDataAccessPluginStart } from '@kbn/logs-data-access-plugin/server'; export interface InfraServerPluginSetupDeps { alerting: AlertingPluginContract; @@ -64,6 +65,7 @@ export interface InfraServerPluginStartDeps { profilingDataAccess?: ProfilingDataAccessPluginStart; ruleRegistry: RuleRegistryPluginStartContract; apmDataAccess: ApmDataAccessPluginStart; + logsDataAccess: LogsDataAccessPluginStart; } export interface CallWithRequestParams extends estypes.RequestBase { diff --git a/x-pack/plugins/observability_solution/infra/server/lib/alerting/inventory_metric_threshold/inventory_metric_threshold_executor.test.ts b/x-pack/plugins/observability_solution/infra/server/lib/alerting/inventory_metric_threshold/inventory_metric_threshold_executor.test.ts index d109669aa90f0..f76a6e82e67d5 100644 --- a/x-pack/plugins/observability_solution/infra/server/lib/alerting/inventory_metric_threshold/inventory_metric_threshold_executor.test.ts +++ b/x-pack/plugins/observability_solution/infra/server/lib/alerting/inventory_metric_threshold/inventory_metric_threshold_executor.test.ts @@ -22,6 +22,7 @@ import { ConditionResult } from './evaluate_condition'; import { InfraBackendLibs } from '../../infra_types'; import { infraPluginMock } from '../../../mocks'; import { logsSharedPluginMock } from '@kbn/logs-shared-plugin/server/mocks'; +import { createLogSourcesServiceMock } from '@kbn/logs-data-access-plugin/common/services/log_sources_service/log_sources_service.mocks'; jest.mock('./evaluate_condition', () => ({ evaluateCondition: jest.fn() })); @@ -115,7 +116,16 @@ const mockLibs = { }, getStartServices: () => [ null, - { logsShared: logsSharedPluginMock.createStartContract() }, + { + logsShared: logsSharedPluginMock.createStartContract(), + logsDataAccess: { + services: { + logSourcesServiceFactory: { + getLogSourcesService: () => createLogSourcesServiceMock(), + }, + }, + }, + }, infraPluginMock.createStartContract(), ], configuration: createMockStaticConfiguration({}), diff --git a/x-pack/plugins/observability_solution/infra/server/lib/alerting/inventory_metric_threshold/inventory_metric_threshold_executor.ts b/x-pack/plugins/observability_solution/infra/server/lib/alerting/inventory_metric_threshold/inventory_metric_threshold_executor.ts index e6ed1750eea3a..80da1034df5ac 100644 --- a/x-pack/plugins/observability_solution/infra/server/lib/alerting/inventory_metric_threshold/inventory_metric_threshold_executor.ts +++ b/x-pack/plugins/observability_solution/infra/server/lib/alerting/inventory_metric_threshold/inventory_metric_threshold_executor.ts @@ -165,9 +165,13 @@ export const createInventoryMetricThresholdExecutor = } const source = await libs.sources.getSourceConfiguration(savedObjectsClient, sourceId); - const [, { logsShared }] = await libs.getStartServices(); + const [, { logsShared, logsDataAccess }] = await libs.getStartServices(); + + const logSourcesService = + logsDataAccess.services.logSourcesServiceFactory.getLogSourcesService(savedObjectsClient); + const logQueryFields: LogQueryFields | undefined = await logsShared.logViews - .getClient(savedObjectsClient, esClient) + .getClient(savedObjectsClient, esClient, logSourcesService) .getResolvedLogView({ type: 'log-view-reference', logViewId: sourceId, diff --git a/x-pack/plugins/observability_solution/infra/server/lib/alerting/log_threshold/log_threshold_executor.ts b/x-pack/plugins/observability_solution/infra/server/lib/alerting/log_threshold/log_threshold_executor.ts index c757f374f8855..0ac06618a3ba2 100644 --- a/x-pack/plugins/observability_solution/infra/server/lib/alerting/log_threshold/log_threshold_executor.ts +++ b/x-pack/plugins/observability_solution/infra/server/lib/alerting/log_threshold/log_threshold_executor.ts @@ -203,13 +203,16 @@ export const createLogThresholdExecutor = } }; - const [, { logsShared }] = await libs.getStartServices(); + const [, { logsShared, logsDataAccess }] = await libs.getStartServices(); try { const validatedParams = decodeOrThrow(ruleParamsRT)(params); + const logSourcesService = + logsDataAccess.services.logSourcesServiceFactory.getLogSourcesService(savedObjectsClient); + const { indices, timestampField, runtimeMappings } = await logsShared.logViews - .getClient(savedObjectsClient, scopedClusterClient.asCurrentUser) + .getClient(savedObjectsClient, scopedClusterClient.asCurrentUser, logSourcesService) .getResolvedLogView(validatedParams.logView); if (!isRatioRuleParams(validatedParams)) { diff --git a/x-pack/plugins/observability_solution/infra/server/lib/sources/types.ts b/x-pack/plugins/observability_solution/infra/server/lib/sources/types.ts index 22cc5108c35c9..9d32269548632 100644 --- a/x-pack/plugins/observability_solution/infra/server/lib/sources/types.ts +++ b/x-pack/plugins/observability_solution/infra/server/lib/sources/types.ts @@ -61,9 +61,14 @@ export const logIndexNameSavedObjectReferenceRT = rt.type({ indexName: rt.string, }); +export const kibanaAdvancedSettingSavedObjectReferenceRT = rt.type({ + type: rt.literal('kibana_advanced_setting'), +}); + export const logIndexSavedObjectReferenceRT = rt.union([ logIndexPatternSavedObjectReferenceRT, logIndexNameSavedObjectReferenceRT, + kibanaAdvancedSettingSavedObjectReferenceRT, ]); export const SourceConfigurationSavedObjectAttributesRT = rt.type({ diff --git a/x-pack/plugins/observability_solution/infra/tsconfig.json b/x-pack/plugins/observability_solution/infra/tsconfig.json index 82f125911abef..e0e6750550fbb 100644 --- a/x-pack/plugins/observability_solution/infra/tsconfig.json +++ b/x-pack/plugins/observability_solution/infra/tsconfig.json @@ -106,8 +106,10 @@ "@kbn/presentation-containers", "@kbn/deeplinks-observability", "@kbn/event-annotation-common", + "@kbn/logs-data-access-plugin", "@kbn/core-analytics-browser", "@kbn/observability-alerting-rule-utils", + "@kbn/core-application-browser", "@kbn/shared-ux-page-no-data-types" ], "exclude": ["target/**/*"] diff --git a/x-pack/plugins/observability_solution/logs_data_access/common/constants.ts b/x-pack/plugins/observability_solution/logs_data_access/common/constants.ts index 83acb8bcfff15..c0caaa846f56e 100644 --- a/x-pack/plugins/observability_solution/logs_data_access/common/constants.ts +++ b/x-pack/plugins/observability_solution/logs_data_access/common/constants.ts @@ -5,4 +5,4 @@ * 2.0. */ -export const DEFAULT_LOG_SOURCES = ['logs-*-*']; +export const DEFAULT_LOG_SOURCES = ['logs-*-*,logs-*,filebeat-*,kibana_sample_data_logs*']; diff --git a/x-pack/plugins/observability_solution/logs_data_access/common/services/log_sources_service/log_sources_service.mocks.ts b/x-pack/plugins/observability_solution/logs_data_access/common/services/log_sources_service/log_sources_service.mocks.ts new file mode 100644 index 0000000000000..3f1f8b9db5979 --- /dev/null +++ b/x-pack/plugins/observability_solution/logs_data_access/common/services/log_sources_service/log_sources_service.mocks.ts @@ -0,0 +1,24 @@ +/* + * 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 { LogSource, LogSourcesService } from './types'; + +const LOG_SOURCES: LogSource[] = [{ indexPattern: 'logs-*-*' }]; +export const createLogSourcesServiceMock = ( + logSources: LogSource[] = LOG_SOURCES +): LogSourcesService => { + let sources = logSources; + return { + async getLogSources() { + return Promise.resolve(sources); + }, + async setLogSources(nextLogSources: LogSource[]) { + sources = nextLogSources; + return Promise.resolve(); + }, + }; +}; diff --git a/x-pack/plugins/observability_solution/logs_data_access/common/services/log_sources_service/types.ts b/x-pack/plugins/observability_solution/logs_data_access/common/services/log_sources_service/types.ts new file mode 100644 index 0000000000000..0d4cb51051237 --- /dev/null +++ b/x-pack/plugins/observability_solution/logs_data_access/common/services/log_sources_service/types.ts @@ -0,0 +1,15 @@ +/* + * 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 interface LogSource { + indexPattern: string; +} + +export interface LogSourcesService { + getLogSources: () => Promise; + setLogSources: (sources: LogSource[]) => Promise; +} diff --git a/x-pack/plugins/observability_solution/logs_data_access/common/types.ts b/x-pack/plugins/observability_solution/logs_data_access/common/types.ts index d021617f294ae..0600b162e1b3d 100644 --- a/x-pack/plugins/observability_solution/logs_data_access/common/types.ts +++ b/x-pack/plugins/observability_solution/logs_data_access/common/types.ts @@ -5,6 +5,4 @@ * 2.0. */ -export interface LogSource { - indexPattern: string; -} +export * from './services/log_sources_service/types'; diff --git a/x-pack/plugins/observability_solution/logs_data_access/common/ui_settings.ts b/x-pack/plugins/observability_solution/logs_data_access/common/ui_settings.ts index 500011231ee38..97259784971c1 100644 --- a/x-pack/plugins/observability_solution/logs_data_access/common/ui_settings.ts +++ b/x-pack/plugins/observability_solution/logs_data_access/common/ui_settings.ts @@ -23,7 +23,7 @@ export const uiSettings: Record = { value: DEFAULT_LOG_SOURCES, description: i18n.translate('xpack.logsDataAccess.logSourcesDescription', { defaultMessage: - 'Sources to be used for logs data. If the data contained in these indices is not logs data, you may experience degraded functionality.', + 'Sources to be used for logs data. If the data contained in these indices is not logs data, you may experience degraded functionality. Changes to this setting can potentially impact the sources queried in Log Threshold rules.', }), type: 'array', schema: schema.arrayOf(schema.string()), diff --git a/x-pack/plugins/observability_solution/logs_data_access/public/index.ts b/x-pack/plugins/observability_solution/logs_data_access/public/index.ts index ed4a2be8a1b09..bdb45d3d0a490 100644 --- a/x-pack/plugins/observability_solution/logs_data_access/public/index.ts +++ b/x-pack/plugins/observability_solution/logs_data_access/public/index.ts @@ -11,6 +11,9 @@ import { LogsDataAccessPluginSetup, LogsDataAccessPluginStart, } from './plugin'; + +export type { LogsDataAccessPluginSetup, LogsDataAccessPluginStart }; + import { LogsDataAccessPluginSetupDeps, LogsDataAccessPluginStartDeps } from './types'; export const plugin: PluginInitializer< diff --git a/x-pack/plugins/observability_solution/logs_data_access/public/services/log_sources_service/index.ts b/x-pack/plugins/observability_solution/logs_data_access/public/services/log_sources_service/index.ts index 3fd4674ea5509..a75bbd65c26e3 100644 --- a/x-pack/plugins/observability_solution/logs_data_access/public/services/log_sources_service/index.ts +++ b/x-pack/plugins/observability_solution/logs_data_access/public/services/log_sources_service/index.ts @@ -6,23 +6,24 @@ */ import { OBSERVABILITY_LOGS_DATA_ACCESS_LOG_SOURCES_ID } from '@kbn/management-settings-ids'; -import { LogSource } from '../../../common/types'; +import { LogSource, LogSourcesService } from '../../../common/services/log_sources_service/types'; import { RegisterServicesParams } from '../register_services'; -export function createLogSourcesService(params: RegisterServicesParams) { +export function createLogSourcesService(params: RegisterServicesParams): LogSourcesService { const { uiSettings } = params.deps; return { - getLogSources: (): LogSource[] => { + getLogSources: async () => { const logSources = uiSettings.get(OBSERVABILITY_LOGS_DATA_ACCESS_LOG_SOURCES_ID); return logSources.map((logSource) => ({ indexPattern: logSource, })); }, setLogSources: async (sources: LogSource[]) => { - return await uiSettings.set( + await uiSettings.set( OBSERVABILITY_LOGS_DATA_ACCESS_LOG_SOURCES_ID, sources.map((source) => source.indexPattern) ); + return; }, }; } diff --git a/x-pack/plugins/observability_solution/logs_data_access/server/services/get_logs_error_rate_timeseries/get_logs_error_rate_timeseries.ts b/x-pack/plugins/observability_solution/logs_data_access/server/services/get_logs_error_rate_timeseries/get_logs_error_rate_timeseries.ts index 1d80171e7d0b0..ab8ae16ba4455 100644 --- a/x-pack/plugins/observability_solution/logs_data_access/server/services/get_logs_error_rate_timeseries/get_logs_error_rate_timeseries.ts +++ b/x-pack/plugins/observability_solution/logs_data_access/server/services/get_logs_error_rate_timeseries/get_logs_error_rate_timeseries.ts @@ -7,10 +7,10 @@ import { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/types'; import type { AggregationOptionsByType, AggregationResultOf } from '@kbn/es-types'; import { ElasticsearchClient } from '@kbn/core/server'; -import { existsQuery, kqlQuery } from '@kbn/observability-plugin/server'; import { estypes } from '@elastic/elasticsearch'; import { getBucketSizeFromTimeRangeAndBucketCount, getLogErrorRate } from '../../utils'; import { LOG_LEVEL } from '../../es_fields'; +import { existsQuery, kqlQuery } from '../../utils/es_queries'; export interface LogsErrorRateTimeseries { esClient: ElasticsearchClient; diff --git a/x-pack/plugins/observability_solution/logs_data_access/server/services/get_logs_rate_timeseries/get_logs_rate_timeseries.ts b/x-pack/plugins/observability_solution/logs_data_access/server/services/get_logs_rate_timeseries/get_logs_rate_timeseries.ts index 49b2d9cb578fb..3341170832a39 100644 --- a/x-pack/plugins/observability_solution/logs_data_access/server/services/get_logs_rate_timeseries/get_logs_rate_timeseries.ts +++ b/x-pack/plugins/observability_solution/logs_data_access/server/services/get_logs_rate_timeseries/get_logs_rate_timeseries.ts @@ -7,10 +7,10 @@ import { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/types'; import type { AggregationOptionsByType, AggregationResultOf } from '@kbn/es-types'; import { ElasticsearchClient } from '@kbn/core/server'; -import { existsQuery, kqlQuery } from '@kbn/observability-plugin/server'; import { estypes } from '@elastic/elasticsearch'; import { getBucketSizeFromTimeRangeAndBucketCount } from '../../utils'; import { LOG_LEVEL } from '../../es_fields'; +import { existsQuery, kqlQuery } from '../../utils/es_queries'; export interface LogsRateTimeseries { esClient: ElasticsearchClient; diff --git a/x-pack/plugins/observability_solution/logs_data_access/server/services/log_sources_service/index.ts b/x-pack/plugins/observability_solution/logs_data_access/server/services/log_sources_service/index.ts index c6075d1d20834..e8907d7537932 100644 --- a/x-pack/plugins/observability_solution/logs_data_access/server/services/log_sources_service/index.ts +++ b/x-pack/plugins/observability_solution/logs_data_access/server/services/log_sources_service/index.ts @@ -5,31 +5,40 @@ * 2.0. */ -import { KibanaRequest } from '@kbn/core-http-server'; +import type { KibanaRequest } from '@kbn/core-http-server'; +import type { SavedObjectsClientContract } from '@kbn/core-saved-objects-api-server'; import { OBSERVABILITY_LOGS_DATA_ACCESS_LOG_SOURCES_ID } from '@kbn/management-settings-ids'; -import { LogSource } from '../../../common/types'; +import { LogSource, LogSourcesService } from '../../../common/services/log_sources_service/types'; import { RegisterServicesParams } from '../register_services'; -export function createGetLogSourcesService(params: RegisterServicesParams) { - return async (request: KibanaRequest) => { - const { savedObjects, uiSettings } = params.deps; - const soClient = savedObjects.getScopedClient(request); - const uiSettingsClient = uiSettings.asScopedToClient(soClient); - return { - getLogSources: async (): Promise => { - const logSources = await uiSettingsClient.get( - OBSERVABILITY_LOGS_DATA_ACCESS_LOG_SOURCES_ID - ); - return logSources.map((logSource) => ({ - indexPattern: logSource, - })); - }, - setLogSources: async (sources: LogSource[]) => { - return await uiSettingsClient.set( - OBSERVABILITY_LOGS_DATA_ACCESS_LOG_SOURCES_ID, - sources.map((source) => source.indexPattern) - ); - }, - }; +export function createLogSourcesServiceFactory(params: RegisterServicesParams) { + return { + async getLogSourcesService( + savedObjectsClient: SavedObjectsClientContract + ): Promise { + const { uiSettings } = params.deps; + const uiSettingsClient = uiSettings.asScopedToClient(savedObjectsClient); + return { + getLogSources: async () => { + const logSources = await uiSettingsClient.get( + OBSERVABILITY_LOGS_DATA_ACCESS_LOG_SOURCES_ID + ); + return logSources.map((logSource) => ({ + indexPattern: logSource, + })); + }, + setLogSources: async (sources: LogSource[]) => { + return await uiSettingsClient.set( + OBSERVABILITY_LOGS_DATA_ACCESS_LOG_SOURCES_ID, + sources.map((source) => source.indexPattern) + ); + }, + }; + }, + async getScopedLogSourcesService(request: KibanaRequest): Promise { + const { savedObjects } = params.deps; + const soClient = savedObjects.getScopedClient(request); + return this.getLogSourcesService(soClient); + }, }; } diff --git a/x-pack/plugins/observability_solution/logs_data_access/server/services/register_services.ts b/x-pack/plugins/observability_solution/logs_data_access/server/services/register_services.ts index 4756bb17f25b1..98c0c95530672 100644 --- a/x-pack/plugins/observability_solution/logs_data_access/server/services/register_services.ts +++ b/x-pack/plugins/observability_solution/logs_data_access/server/services/register_services.ts @@ -11,7 +11,7 @@ import { Logger } from '@kbn/logging'; import { createGetLogsRateTimeseries } from './get_logs_rate_timeseries/get_logs_rate_timeseries'; import { createGetLogErrorRateTimeseries } from './get_logs_error_rate_timeseries/get_logs_error_rate_timeseries'; import { createGetLogsRatesService } from './get_logs_rates_service'; -import { createGetLogSourcesService } from './log_sources_service'; +import { createLogSourcesServiceFactory } from './log_sources_service'; export interface RegisterServicesParams { logger: Logger; @@ -26,6 +26,6 @@ export function registerServices(params: RegisterServicesParams) { getLogsRatesService: createGetLogsRatesService(), getLogsRateTimeseries: createGetLogsRateTimeseries(), getLogsErrorRateTimeseries: createGetLogErrorRateTimeseries(), - getLogSourcesService: createGetLogSourcesService(params), + logSourcesServiceFactory: createLogSourcesServiceFactory(params), }; } diff --git a/x-pack/plugins/observability_solution/logs_data_access/server/utils/es_queries.ts b/x-pack/plugins/observability_solution/logs_data_access/server/utils/es_queries.ts new file mode 100644 index 0000000000000..282b21af495c9 --- /dev/null +++ b/x-pack/plugins/observability_solution/logs_data_access/server/utils/es_queries.ts @@ -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 { estypes } from '@elastic/elasticsearch'; +import { QueryDslQueryContainer } from '@kbn/data-views-plugin/common/types'; +import { fromKueryExpression, toElasticsearchQuery } from '@kbn/es-query'; + +export function existsQuery(field: string): QueryDslQueryContainer[] { + return [{ exists: { field } }]; +} + +export function kqlQuery(kql?: string): estypes.QueryDslQueryContainer[] { + if (!kql) { + return []; + } + + const ast = fromKueryExpression(kql); + return [toElasticsearchQuery(ast)]; +} diff --git a/x-pack/plugins/observability_solution/logs_data_access/tsconfig.json b/x-pack/plugins/observability_solution/logs_data_access/tsconfig.json index 09a57dea36e49..45c96d862d9ff 100644 --- a/x-pack/plugins/observability_solution/logs_data_access/tsconfig.json +++ b/x-pack/plugins/observability_solution/logs_data_access/tsconfig.json @@ -9,7 +9,6 @@ "@kbn/core", "@kbn/data-plugin", "@kbn/data-views-plugin", - "@kbn/observability-plugin", "@kbn/calculate-auto", "@kbn/es-types", "@kbn/core-http-server", @@ -20,6 +19,8 @@ "@kbn/core-saved-objects-server", "@kbn/core-ui-settings-server", "@kbn/core-ui-settings-browser", - "@kbn/logging" + "@kbn/logging", + "@kbn/core-saved-objects-api-server", + "@kbn/es-query" ] } diff --git a/x-pack/plugins/observability_solution/logs_shared/common/index.ts b/x-pack/plugins/observability_solution/logs_shared/common/index.ts index f6b1e9ea27e43..104b68ce2fddf 100644 --- a/x-pack/plugins/observability_solution/logs_shared/common/index.ts +++ b/x-pack/plugins/observability_solution/logs_shared/common/index.ts @@ -17,12 +17,14 @@ export { logViewReferenceRT, persistedLogViewReferenceRT, defaultLogViewAttributes, + logSourcesKibanaAdvancedSettingRT, } from './log_views'; // LogView types export type { LogDataViewReference, LogIndexNameReference, + LogSourcesKibanaAdvancedSettingReference, LogIndexReference, LogView, LogViewAttributes, diff --git a/x-pack/plugins/observability_solution/logs_shared/common/log_views/resolved_log_view.mock.ts b/x-pack/plugins/observability_solution/logs_shared/common/log_views/resolved_log_view.mock.ts index 8c09f16e3b53e..568a25ecef1d7 100644 --- a/x-pack/plugins/observability_solution/logs_shared/common/log_views/resolved_log_view.mock.ts +++ b/x-pack/plugins/observability_solution/logs_shared/common/log_views/resolved_log_view.mock.ts @@ -11,6 +11,7 @@ import { defaultLogViewsStaticConfig } from './defaults'; import { ResolvedLogView, resolveLogView } from './resolved_log_view'; import { LogViewAttributes } from './types'; import { DataViewSpec } from '@kbn/data-views-plugin/common'; +import { createLogSourcesServiceMock } from '@kbn/logs-data-access-plugin/common/services/log_sources_service/log_sources_service.mocks'; export const createResolvedLogViewMock = ( resolvedLogViewOverrides: Partial = {} @@ -63,5 +64,6 @@ export const createResolvedLogViewMockFromAttributes = (logViewAttributes: LogVi spec, }), } as unknown as DataViewsContract, + createLogSourcesServiceMock(), defaultLogViewsStaticConfig ); diff --git a/x-pack/plugins/observability_solution/logs_shared/common/log_views/resolved_log_view.ts b/x-pack/plugins/observability_solution/logs_shared/common/log_views/resolved_log_view.ts index b9419fbd51f22..1521aa67e3d92 100644 --- a/x-pack/plugins/observability_solution/logs_shared/common/log_views/resolved_log_view.ts +++ b/x-pack/plugins/observability_solution/logs_shared/common/log_views/resolved_log_view.ts @@ -7,6 +7,7 @@ import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { DataView, DataViewsContract, FieldSpec } from '@kbn/data-views-plugin/common'; +import { LogSourcesService } from '@kbn/logs-data-access-plugin/common/services/log_sources_service/types'; import { TIEBREAKER_FIELD, TIMESTAMP_FIELD } from '../constants'; import { defaultLogViewsStaticConfig } from './defaults'; import { ResolveLogViewError } from './errors'; @@ -31,12 +32,20 @@ export const resolveLogView = ( logViewId: string, logViewAttributes: LogViewAttributes, dataViewsService: DataViewsContract, + logSourcesService: LogSourcesService, config: LogViewsStaticConfig ): Promise => { if (logViewAttributes.logIndices.type === 'index_name') { return resolveLegacyReference(logViewId, logViewAttributes, dataViewsService, config); - } else { + } else if (logViewAttributes.logIndices.type === 'data_view') { return resolveDataViewReference(logViewAttributes, dataViewsService); + } else { + return resolveKibanaAdvancedSettingReference( + logViewId, + logViewAttributes, + dataViewsService, + logSourcesService + ); } }; @@ -110,6 +119,52 @@ const resolveDataViewReference = async ( }; }; +const resolveKibanaAdvancedSettingReference = async ( + logViewId: string, + logViewAttributes: LogViewAttributes, + dataViewsService: DataViewsContract, + logSourcesService: LogSourcesService +): Promise => { + if (logViewAttributes.logIndices.type !== 'kibana_advanced_setting') { + throw new Error( + 'This function can only resolve references to the Log Sources Kibana advanced setting' + ); + } + + const indices = (await logSourcesService.getLogSources()) + .map((logSource) => logSource.indexPattern) + .join(','); + + const dataViewReference = await dataViewsService + .create( + { + id: `log-view-${logViewId}`, + name: logViewAttributes.name, + title: indices, + timeFieldName: TIMESTAMP_FIELD, + allowNoIndex: true, + }, + false, + false + ) + .catch((error) => { + throw new ResolveLogViewError(`Failed to create Data View reference: ${error}`, error); + }); + + return { + indices, + timestampField: TIMESTAMP_FIELD, + tiebreakerField: TIEBREAKER_FIELD, + messageField: ['message'], + fields: dataViewReference.fields, + runtimeMappings: {}, + columns: logViewAttributes.logColumns, + name: logViewAttributes.name, + description: logViewAttributes.description, + dataViewReference, + }; +}; + // this might take other sources of runtime fields into account in the future const resolveRuntimeMappings = (dataView: DataView): estypes.MappingRuntimeFields => { return dataView.getRuntimeMappings(); diff --git a/x-pack/plugins/observability_solution/logs_shared/common/log_views/types.ts b/x-pack/plugins/observability_solution/logs_shared/common/log_views/types.ts index f94601f9e0f84..6cc8d60191a34 100644 --- a/x-pack/plugins/observability_solution/logs_shared/common/log_views/types.ts +++ b/x-pack/plugins/observability_solution/logs_shared/common/log_views/types.ts @@ -38,7 +38,20 @@ export const logIndexNameReferenceRT = rt.type({ }); export type LogIndexNameReference = rt.TypeOf; -export const logIndexReferenceRT = rt.union([logDataViewReferenceRT, logIndexNameReferenceRT]); +// Kibana advanced setting +export const logSourcesKibanaAdvancedSettingRT = rt.type({ + type: rt.literal('kibana_advanced_setting'), +}); + +export type LogSourcesKibanaAdvancedSettingReference = rt.TypeOf< + typeof logSourcesKibanaAdvancedSettingRT +>; + +export const logIndexReferenceRT = rt.union([ + logDataViewReferenceRT, + logIndexNameReferenceRT, + logSourcesKibanaAdvancedSettingRT, +]); export type LogIndexReference = rt.TypeOf; const logViewCommonColumnConfigurationRT = rt.strict({ diff --git a/x-pack/plugins/observability_solution/logs_shared/kibana.jsonc b/x-pack/plugins/observability_solution/logs_shared/kibana.jsonc index 7e79614b56e5a..ea93fd326dac7 100644 --- a/x-pack/plugins/observability_solution/logs_shared/kibana.jsonc +++ b/x-pack/plugins/observability_solution/logs_shared/kibana.jsonc @@ -14,7 +14,8 @@ "discoverShared", "usageCollection", "observabilityShared", - "share" + "share", + "logsDataAccess" ], "optionalPlugins": [ "observabilityAIAssistant", diff --git a/x-pack/plugins/observability_solution/logs_shared/public/components/log_stream/log_stream.tsx b/x-pack/plugins/observability_solution/logs_shared/public/components/log_stream/log_stream.tsx index 5ba062912d8f3..f0c9c411249a9 100644 --- a/x-pack/plugins/observability_solution/logs_shared/public/components/log_stream/log_stream.tsx +++ b/x-pack/plugins/observability_solution/logs_shared/public/components/log_stream/log_stream.tsx @@ -15,6 +15,7 @@ import { JsonValue } from '@kbn/utility-types'; import { noop } from 'lodash'; import React, { useCallback, useEffect, useMemo } from 'react'; import usePrevious from 'react-use/lib/usePrevious'; +import type { LogsDataAccessPluginStart } from '@kbn/logs-data-access-plugin/public'; import { LogEntryCursor } from '../../../common/log_entry'; import { defaultLogViewsStaticConfig, LogViewReference } from '../../../common/log_views'; import { BuiltEsQuery, useLogStream } from '../../containers/logs/log_stream'; @@ -28,6 +29,7 @@ import { LogStreamErrorBoundary } from './log_stream_error_boundary'; interface LogStreamPluginDeps { data: DataPublicPluginStart; + logsDataAccess: LogsDataAccessPluginStart; http: HttpStart; share: SharePluginStart; } @@ -113,9 +115,9 @@ export const LogStreamContent = ({ ); const { - services: { http, data, share }, + services: { http, data, share, logsDataAccess }, } = useKibana(); - if (http == null || data == null || share == null) { + if (http == null || data == null || share == null || logsDataAccess == null) { throw new Error( ` cannot access kibana core services. @@ -130,8 +132,15 @@ Read more at https://github.com/elastic/kibana/blob/main/src/plugins/kibana_reac const kibanaQuerySettings = useKibanaQuerySettings(); const logViews = useMemo( - () => new LogViewsClient(data.dataViews, http, data.search.search, defaultLogViewsStaticConfig), - [data.dataViews, data.search.search, http] + () => + new LogViewsClient( + data.dataViews, + logsDataAccess.services.logSourcesService, + http, + data.search.search, + defaultLogViewsStaticConfig + ), + [data.dataViews, data.search.search, http, logsDataAccess.services.logSourcesService] ); const { diff --git a/x-pack/plugins/observability_solution/logs_shared/public/plugin.ts b/x-pack/plugins/observability_solution/logs_shared/public/plugin.ts index 4655a7a62f087..d6f4ac81fe266 100644 --- a/x-pack/plugins/observability_solution/logs_shared/public/plugin.ts +++ b/x-pack/plugins/observability_solution/logs_shared/public/plugin.ts @@ -52,11 +52,12 @@ export class LogsSharedPlugin implements LogsSharedClientPluginClass { public start(core: CoreStart, plugins: LogsSharedClientStartDeps) { const { http } = core; - const { data, dataViews, discoverShared, observabilityAIAssistant } = plugins; + const { data, dataViews, discoverShared, observabilityAIAssistant, logsDataAccess } = plugins; const logViews = this.logViews.start({ http, dataViews, + logSourcesService: logsDataAccess.services.logSourcesService, search: data.search, }); diff --git a/x-pack/plugins/observability_solution/logs_shared/public/services/log_views/log_views_client.ts b/x-pack/plugins/observability_solution/logs_shared/public/services/log_views/log_views_client.ts index a53ac542c5f03..b1a71cea73cb1 100644 --- a/x-pack/plugins/observability_solution/logs_shared/public/services/log_views/log_views_client.ts +++ b/x-pack/plugins/observability_solution/logs_shared/public/services/log_views/log_views_client.ts @@ -10,6 +10,7 @@ import { HttpStart } from '@kbn/core/public'; import type { ISearchGeneric } from '@kbn/search-types'; import { DataViewsContract } from '@kbn/data-views-plugin/public'; import { lastValueFrom } from 'rxjs'; +import { LogSourcesService } from '@kbn/logs-data-access-plugin/common/types'; import { getLogViewResponsePayloadRT, putLogViewRequestPayloadRT } from '../../../common/http_api'; import { getLogViewUrl } from '../../../common/http_api/log_views'; import { @@ -31,6 +32,7 @@ import { ILogViewsClient } from './types'; export class LogViewsClient implements ILogViewsClient { constructor( private readonly dataViews: DataViewsContract, + private readonly logSourcesService: LogSourcesService, private readonly http: HttpStart, private readonly search: ISearchGeneric, private readonly config: LogViewsStaticConfig @@ -152,7 +154,13 @@ export class LogViewsClient implements ILogViewsClient { logViewId: string, logViewAttributes: LogViewAttributes ): Promise { - return await resolveLogView(logViewId, logViewAttributes, this.dataViews, this.config); + return await resolveLogView( + logViewId, + logViewAttributes, + this.dataViews, + this.logSourcesService, + this.config + ); } } diff --git a/x-pack/plugins/observability_solution/logs_shared/public/services/log_views/log_views_service.ts b/x-pack/plugins/observability_solution/logs_shared/public/services/log_views/log_views_service.ts index 712196c95205c..66ddfde911176 100644 --- a/x-pack/plugins/observability_solution/logs_shared/public/services/log_views/log_views_service.ts +++ b/x-pack/plugins/observability_solution/logs_shared/public/services/log_views/log_views_service.ts @@ -20,8 +20,19 @@ export class LogViewsService { }; } - public start({ dataViews, http, search }: LogViewsServiceStartDeps): LogViewsServiceStart { - const client = new LogViewsClient(dataViews, http, search.search, this.logViewsStaticConfig); + public start({ + dataViews, + http, + search, + logSourcesService, + }: LogViewsServiceStartDeps): LogViewsServiceStart { + const client = new LogViewsClient( + dataViews, + logSourcesService, + http, + search.search, + this.logViewsStaticConfig + ); return { client, diff --git a/x-pack/plugins/observability_solution/logs_shared/public/services/log_views/types.ts b/x-pack/plugins/observability_solution/logs_shared/public/services/log_views/types.ts index 58a504be789bc..a6d516f00669d 100644 --- a/x-pack/plugins/observability_solution/logs_shared/public/services/log_views/types.ts +++ b/x-pack/plugins/observability_solution/logs_shared/public/services/log_views/types.ts @@ -8,6 +8,7 @@ import { HttpStart } from '@kbn/core/public'; import { ISearchStart } from '@kbn/data-plugin/public'; import { DataViewsContract } from '@kbn/data-views-plugin/public'; +import { LogSourcesService } from '@kbn/logs-data-access-plugin/common/types'; import { LogView, LogViewAttributes, @@ -29,6 +30,7 @@ export interface LogViewsServiceStartDeps { dataViews: DataViewsContract; http: HttpStart; search: ISearchStart; + logSourcesService: LogSourcesService; } export interface ILogViewsClient { diff --git a/x-pack/plugins/observability_solution/logs_shared/public/types.ts b/x-pack/plugins/observability_solution/logs_shared/public/types.ts index 9f0d344294880..58b180ee8b6ef 100644 --- a/x-pack/plugins/observability_solution/logs_shared/public/types.ts +++ b/x-pack/plugins/observability_solution/logs_shared/public/types.ts @@ -9,6 +9,7 @@ import type { CoreSetup, CoreStart, Plugin as PluginClass } from '@kbn/core/publ import type { DataPublicPluginStart } from '@kbn/data-plugin/public'; import type { DataViewsPublicPluginStart } from '@kbn/data-views-plugin/public'; import type { DiscoverSharedPublicStart } from '@kbn/discover-shared-plugin/public'; +import { LogsDataAccessPluginStart } from '@kbn/logs-data-access-plugin/public'; import type { ObservabilityAIAssistantPublicStart } from '@kbn/observability-ai-assistant-plugin/public'; import type { SharePluginSetup, SharePluginStart } from '@kbn/share-plugin/public'; import type { UiActionsStart } from '@kbn/ui-actions-plugin/public'; @@ -37,6 +38,7 @@ export interface LogsSharedClientStartDeps { data: DataPublicPluginStart; dataViews: DataViewsPublicPluginStart; discoverShared: DiscoverSharedPublicStart; + logsDataAccess: LogsDataAccessPluginStart; observabilityAIAssistant?: ObservabilityAIAssistantPublicStart; share: SharePluginStart; uiActions: UiActionsStart; diff --git a/x-pack/plugins/observability_solution/logs_shared/server/lib/domains/log_entries_domain/log_entries_domain.ts b/x-pack/plugins/observability_solution/logs_shared/server/lib/domains/log_entries_domain/log_entries_domain.ts index 2601167f2d988..f3cbfb57b09c4 100644 --- a/x-pack/plugins/observability_solution/logs_shared/server/lib/domains/log_entries_domain/log_entries_domain.ts +++ b/x-pack/plugins/observability_solution/logs_shared/server/lib/domains/log_entries_domain/log_entries_domain.ts @@ -172,10 +172,13 @@ export class LogsSharedLogEntriesDomain implements ILogsSharedLogEntriesDomain { params: LogEntriesParams, columnOverrides?: LogViewColumnConfiguration[] ): Promise<{ entries: LogEntry[]; hasMoreBefore?: boolean; hasMoreAfter?: boolean }> { - const [, , { logViews }] = await this.libs.getStartServices(); + const [, { logsDataAccess }, { logViews }] = await this.libs.getStartServices(); const { savedObjects, elasticsearch } = await requestContext.core; + const logSourcesService = logsDataAccess.services.logSourcesServiceFactory.getLogSourcesService( + savedObjects.client + ); const resolvedLogView = await logViews - .getClient(savedObjects.client, elasticsearch.client.asCurrentUser) + .getClient(savedObjects.client, elasticsearch.client.asCurrentUser, logSourcesService) .getResolvedLogView(logView); const columnDefinitions = columnOverrides ?? resolvedLogView.columns; @@ -232,11 +235,15 @@ export class LogsSharedLogEntriesDomain implements ILogsSharedLogEntriesDomain { bucketSize: number, filterQuery?: LogEntryQuery ): Promise { - const [, , { logViews }] = await this.libs.getStartServices(); + const [, { logsDataAccess }, { logViews }] = await this.libs.getStartServices(); const { savedObjects, elasticsearch } = await requestContext.core; + const logSourcesService = logsDataAccess.services.logSourcesServiceFactory.getLogSourcesService( + savedObjects.client + ); const resolvedLogView = await logViews - .getClient(savedObjects.client, elasticsearch.client.asCurrentUser) + .getClient(savedObjects.client, elasticsearch.client.asCurrentUser, logSourcesService) .getResolvedLogView(logView); + const dateRangeBuckets = await this.adapter.getContainedLogSummaryBuckets( requestContext, resolvedLogView, @@ -257,11 +264,16 @@ export class LogsSharedLogEntriesDomain implements ILogsSharedLogEntriesDomain { highlightQueries: string[], filterQuery?: LogEntryQuery ): Promise { - const [, , { logViews }] = await this.libs.getStartServices(); + const [, { logsDataAccess }, { logViews }] = await this.libs.getStartServices(); const { savedObjects, elasticsearch } = await requestContext.core; + const logSourcesService = logsDataAccess.services.logSourcesServiceFactory.getLogSourcesService( + savedObjects.client + ); + const resolvedLogView = await logViews - .getClient(savedObjects.client, elasticsearch.client.asCurrentUser) + .getClient(savedObjects.client, elasticsearch.client.asCurrentUser, logSourcesService) .getResolvedLogView(logView); + const messageFormattingRules = compileFormattingRules( getBuiltinRules(resolvedLogView.messageField) ); diff --git a/x-pack/plugins/observability_solution/logs_shared/server/plugin.ts b/x-pack/plugins/observability_solution/logs_shared/server/plugin.ts index 7e3fad84e4c30..6bc9560764a7b 100644 --- a/x-pack/plugins/observability_solution/logs_shared/server/plugin.ts +++ b/x-pack/plugins/observability_solution/logs_shared/server/plugin.ts @@ -97,6 +97,7 @@ export class LogsSharedPlugin const logViews = this.logViews.start({ savedObjects: core.savedObjects, dataViews: plugins.dataViews, + logsDataAccess: plugins.logsDataAccess, elasticsearch: core.elasticsearch, }); diff --git a/x-pack/plugins/observability_solution/logs_shared/server/saved_objects/log_view/types.ts b/x-pack/plugins/observability_solution/logs_shared/server/saved_objects/log_view/types.ts index fb8bf49781a2d..341e9bbed608b 100644 --- a/x-pack/plugins/observability_solution/logs_shared/server/saved_objects/log_view/types.ts +++ b/x-pack/plugins/observability_solution/logs_shared/server/saved_objects/log_view/types.ts @@ -19,9 +19,14 @@ export const logIndexNameSavedObjectReferenceRT = rt.type({ indexName: rt.string, }); +export const logSourcesKibanaAdvancedSettingSavedObjectRT = rt.type({ + type: rt.literal('kibana_advanced_setting'), +}); + export const logIndexSavedObjectReferenceRT = rt.union([ logDataViewSavedObjectReferenceRT, logIndexNameSavedObjectReferenceRT, + logSourcesKibanaAdvancedSettingSavedObjectRT, ]); const logViewSavedObjectCommonColumnConfigurationRT = rt.strict({ diff --git a/x-pack/plugins/observability_solution/logs_shared/server/services/log_views/log_views_client.test.ts b/x-pack/plugins/observability_solution/logs_shared/server/services/log_views/log_views_client.test.ts index a1175432a4ac7..f6df48b22ba7e 100644 --- a/x-pack/plugins/observability_solution/logs_shared/server/services/log_views/log_views_client.test.ts +++ b/x-pack/plugins/observability_solution/logs_shared/server/services/log_views/log_views_client.test.ts @@ -22,6 +22,7 @@ import { logViewSavedObjectName, } from '../../saved_objects/log_view'; import { LogViewsClient } from './log_views_client'; +import { createLogSourcesServiceMock } from '@kbn/logs-data-access-plugin/common/services/log_sources_service/log_sources_service.mocks'; describe('LogViewsClient class', () => { it('getLogView resolves the default id to a real saved object id if it exists', async () => { @@ -341,6 +342,7 @@ describe('LogViewsClient class', () => { const createLogViewsClient = () => { const logger = loggerMock.create(); const dataViews = dataViewsServiceMock; + const logSourcesService = createLogSourcesServiceMock(); const savedObjectsClient = savedObjectsClientMock.create(); const logViewFallbackHandler = jest.fn(); const internalLogViews = new Map(); @@ -351,6 +353,7 @@ const createLogViewsClient = () => { const logViewsClient = new LogViewsClient( logger, Promise.resolve(dataViews), + Promise.resolve(logSourcesService), savedObjectsClient, logViewFallbackHandler, internalLogViews, diff --git a/x-pack/plugins/observability_solution/logs_shared/server/services/log_views/log_views_client.ts b/x-pack/plugins/observability_solution/logs_shared/server/services/log_views/log_views_client.ts index 0b9bfe9febf4a..cea43f02b358d 100644 --- a/x-pack/plugins/observability_solution/logs_shared/server/services/log_views/log_views_client.ts +++ b/x-pack/plugins/observability_solution/logs_shared/server/services/log_views/log_views_client.ts @@ -13,6 +13,7 @@ import { SavedObjectsUtils, SavedObjectsErrorHelpers, } from '@kbn/core/server'; +import { LogSourcesService } from '@kbn/logs-data-access-plugin/common/types'; import { defaultLogViewAttributes, defaultLogViewId, @@ -44,6 +45,7 @@ export class LogViewsClient implements ILogViewsClient { constructor( private readonly logger: Logger, private readonly dataViews: DataViewsService, + private readonly logSourcesService: Promise, private readonly savedObjectsClient: SavedObjectsClientContract, private readonly logViewFallbackHandler: LogViewFallbackHandler, private readonly internalLogViews: Map, @@ -117,7 +119,13 @@ export class LogViewsClient implements ILogViewsClient { logViewId: string, logViewAttributes: LogViewAttributes ): Promise { - return await resolveLogView(logViewId, logViewAttributes, await this.dataViews, this.config); + return await resolveLogView( + logViewId, + logViewAttributes, + await this.dataViews, + await this.logSourcesService, + this.config + ); } private async getSavedLogView(logViewId: string): Promise { diff --git a/x-pack/plugins/observability_solution/logs_shared/server/services/log_views/log_views_service.mock.ts b/x-pack/plugins/observability_solution/logs_shared/server/services/log_views/log_views_service.mock.ts index 295b1fd77452f..11fbe43a6b9cb 100644 --- a/x-pack/plugins/observability_solution/logs_shared/server/services/log_views/log_views_service.mock.ts +++ b/x-pack/plugins/observability_solution/logs_shared/server/services/log_views/log_views_service.mock.ts @@ -15,8 +15,9 @@ export const createLogViewsServiceSetupMock = (): jest.Mocked => ({ - getClient: jest.fn((_savedObjectsClient: any, _elasticsearchClient: any) => - createLogViewsClientMock() + getClient: jest.fn( + (_savedObjectsClient: any, _elasticsearchClient: any, _logSourcesService: any) => + createLogViewsClientMock() ), getScopedClient: jest.fn((_request: any) => createLogViewsClientMock()), }); diff --git a/x-pack/plugins/observability_solution/logs_shared/server/services/log_views/log_views_service.ts b/x-pack/plugins/observability_solution/logs_shared/server/services/log_views/log_views_service.ts index 5479c16dff411..2f429dc7612ff 100644 --- a/x-pack/plugins/observability_solution/logs_shared/server/services/log_views/log_views_service.ts +++ b/x-pack/plugins/observability_solution/logs_shared/server/services/log_views/log_views_service.ts @@ -11,6 +11,7 @@ import { Logger, SavedObjectsClientContract, } from '@kbn/core/server'; +import { LogSourcesService } from '@kbn/logs-data-access-plugin/common/types'; import { defaultLogViewAttributes, defaultLogViewsStaticConfig, @@ -56,6 +57,7 @@ export class LogViewsService { public start({ dataViews, + logsDataAccess, elasticsearch, savedObjects, }: LogViewsServiceStartDeps): LogViewsServiceStart { @@ -65,11 +67,13 @@ export class LogViewsService { getClient( savedObjectsClient: SavedObjectsClientContract, elasticsearchClient: ElasticsearchClient, + logSourcesService: Promise, request?: KibanaRequest ) { return new LogViewsClient( logger, dataViews.dataViewsServiceFactory(savedObjectsClient, elasticsearchClient, request), + logSourcesService, savedObjectsClient, logViewFallbackHandler, internalLogViews, @@ -79,8 +83,9 @@ export class LogViewsService { getScopedClient(request: KibanaRequest) { const savedObjectsClient = savedObjects.getScopedClient(request); const elasticsearchClient = elasticsearch.client.asScoped(request).asCurrentUser; - - return this.getClient(savedObjectsClient, elasticsearchClient, request); + const logSourcesService = + logsDataAccess.services.logSourcesServiceFactory.getScopedLogSourcesService(request); + return this.getClient(savedObjectsClient, elasticsearchClient, logSourcesService, request); }, }; } diff --git a/x-pack/plugins/observability_solution/logs_shared/server/services/log_views/types.ts b/x-pack/plugins/observability_solution/logs_shared/server/services/log_views/types.ts index b0aa2784e4cd2..becf32881acf8 100644 --- a/x-pack/plugins/observability_solution/logs_shared/server/services/log_views/types.ts +++ b/x-pack/plugins/observability_solution/logs_shared/server/services/log_views/types.ts @@ -13,6 +13,8 @@ import { SavedObjectsServiceStart, } from '@kbn/core/server'; import { PluginStart as DataViewsServerPluginStart } from '@kbn/data-views-plugin/server'; +import { LogSourcesService } from '@kbn/logs-data-access-plugin/common/types'; +import { LogsDataAccessPluginStart } from '@kbn/logs-data-access-plugin/server'; import { LogView, LogViewAttributes, @@ -23,6 +25,7 @@ import { export interface LogViewsServiceStartDeps { dataViews: DataViewsServerPluginStart; + logsDataAccess: LogsDataAccessPluginStart; elasticsearch: ElasticsearchServiceStart; savedObjects: SavedObjectsServiceStart; } @@ -45,6 +48,7 @@ export interface LogViewsServiceStart { getClient( savedObjectsClient: SavedObjectsClientContract, elasticsearchClient: ElasticsearchClient, + logSourcesService: Promise, request?: KibanaRequest ): ILogViewsClient; getScopedClient(request: KibanaRequest): ILogViewsClient; diff --git a/x-pack/plugins/observability_solution/logs_shared/server/types.ts b/x-pack/plugins/observability_solution/logs_shared/server/types.ts index 2e922eceeb183..73365ece21a14 100644 --- a/x-pack/plugins/observability_solution/logs_shared/server/types.ts +++ b/x-pack/plugins/observability_solution/logs_shared/server/types.ts @@ -11,6 +11,7 @@ import { PluginStart as DataPluginStart, } from '@kbn/data-plugin/server'; import { PluginStart as DataViewsPluginStart } from '@kbn/data-views-plugin/server'; +import { LogsDataAccessPluginStart } from '@kbn/logs-data-access-plugin/server'; import { LogsSharedDomainLibs } from './lib/logs_shared_types'; import { LogViewsServiceSetup, LogViewsServiceStart } from './services/log_views/types'; @@ -36,6 +37,7 @@ export interface LogsSharedServerPluginSetupDeps { export interface LogsSharedServerPluginStartDeps { data: DataPluginStart; dataViews: DataViewsPluginStart; + logsDataAccess: LogsDataAccessPluginStart; } export interface UsageCollector { diff --git a/x-pack/plugins/observability_solution/logs_shared/tsconfig.json b/x-pack/plugins/observability_solution/logs_shared/tsconfig.json index d826cd78618c5..f1bb2527f9311 100644 --- a/x-pack/plugins/observability_solution/logs_shared/tsconfig.json +++ b/x-pack/plugins/observability_solution/logs_shared/tsconfig.json @@ -41,5 +41,6 @@ "@kbn/react-kibana-context-theme", "@kbn/test-jest-helpers", "@kbn/router-utils", + "@kbn/logs-data-access-plugin", ] } diff --git a/x-pack/test/functional/apps/infra/logs/logs_source_configuration.ts b/x-pack/test/functional/apps/infra/logs/logs_source_configuration.ts index 358095e4350b8..22ed2bd035ee1 100644 --- a/x-pack/test/functional/apps/infra/logs/logs_source_configuration.ts +++ b/x-pack/test/functional/apps/infra/logs/logs_source_configuration.ts @@ -76,6 +76,8 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { await pageObjects.header.waitUntilLoadingHasFinished(); + await infraSourceConfigurationForm.selectIndicesPanel(); + const nameInput = await infraSourceConfigurationForm.getNameInput(); await nameInput.clearValueWithKeyboard({ charByChar: true }); await nameInput.type('Modified Source'); diff --git a/x-pack/test/functional/services/infra_source_configuration_form.ts b/x-pack/test/functional/services/infra_source_configuration_form.ts index da39347c36389..c8d28e0e3656b 100644 --- a/x-pack/test/functional/services/infra_source_configuration_form.ts +++ b/x-pack/test/functional/services/infra_source_configuration_form.ts @@ -30,7 +30,9 @@ export function InfraSourceConfigurationFormProvider({ async getMetricIndicesInput(): Promise { return await testSubjects.findDescendant('~metricIndicesInput', await this.getForm()); }, - + async selectIndicesPanel(): Promise { + return await testSubjects.click('logIndicesCheckableCard'); + }, /** * Logs */