[Log threshold] Use dataViewLazy during rule execution (#215306)

## Summary

In this PR, we use dataViewLazy, which avoids calling _field_caps API
(this logic was introduced in this
[PR](https://github.com/elastic/kibana/pull/183694)).

#### Questions
1. Do we need to call _field_caps API in the log threshold rule
executor? If yes, in which scenario?
    No, we don't need to call _field_caps API in rule execution.
2. How to fix the type issues since DataViewLazy misses some fields that
exist in the DataView type.
We decided to use DataViewLazy everywhere on the server side but convert
it to an actual DataView on the client side due to the need for the
fields.


||Screenshot|
|---|---|

|Create|![image](https://github.com/user-attachments/assets/2c3e3e87-a3f6-4cf3-bc9a-620b501558d0)|

|createDataViewLazy|![image](https://github.com/user-attachments/assets/ea63ca5a-b68c-4e41-acd3-a18be823eefa)|

### 🧪 How to test
- Enable APM locally
```
elastic.apm.active: true
elastic.apm.transactionSampleRate: 1.0
elastic.apm.environment: username
```
- Create a log threshold rule and check its execution in
[traces](https://kibana-cloud-apm.elastic.dev/app/apm/traces?rangeFrom=now-15m&rangeTo=now)
filtered for your `username` as the environment. There should be one
with your rule name:

![image](https://github.com/user-attachments/assets/bb3b6eae-474b-4d2e-a428-15f71e671250)
    
The timing for `_field_caps` would be more if you replace the
`createDataViewLazy` with the `create` function.

---------

Co-authored-by: Faisal Kanout <faisal.kanout@elastic.co>
This commit is contained in:
Maryam Saeidi 2025-04-09 16:30:45 +02:00 committed by GitHub
parent 77523f7b15
commit 1b10f35b3d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
20 changed files with 156 additions and 90 deletions

View file

@ -103,7 +103,7 @@ export class DataViewLazy extends AbstractDataView {
runtimeResult = this.getRuntimeFields({ fieldName });
}
const fieldMap = { ...mappedResult, ...scriptedResult, ...runtimeResult };
const fieldMap: DataViewFieldMap = { ...mappedResult, ...scriptedResult, ...runtimeResult };
let fieldMapSorted = {};
let hasBeenSorted = false;

View file

@ -9,3 +9,4 @@
export * from './field.stub';
export * from './data_views/data_view.stub';
export * from './data_views/data_view_lazy.stub';

View file

@ -5,7 +5,7 @@
* 2.0.
*/
import { DataView } from '@kbn/data-views-plugin/common';
import type { DataView } from '@kbn/data-views-plugin/common';
import { apiPublishesDataViews, EmbeddableApiContext } from '@kbn/presentation-publishing';
export const getDataViews = (embeddable: EmbeddableApiContext['embeddable']): string[] => {

View file

@ -11,7 +11,7 @@ import { buildPhrasesFilter, PhrasesFilter } from '@kbn/es-query';
import { FormattedMessage } from '@kbn/i18n-react';
import { METRIC_TYPE } from '@kbn/analytics';
import { EuiLink, EuiSpacer, EuiText } from '@elastic/eui';
import { DataView } from '@kbn/data-views-plugin/common';
import type { DataView } from '@kbn/data-views-plugin/common';
import {
APPS_WITH_DEPRECATION_LOGS,
DEPRECATION_LOGS_ORIGIN_FIELD,

View file

@ -11,7 +11,7 @@ import React from 'react';
import { faker } from '@faker-js/faker';
import { Query, Filter, AggregateQuery, TimeRange } from '@kbn/es-query';
import { initializeTitleManager, PhaseEvent, ViewMode } from '@kbn/presentation-publishing';
import { DataView } from '@kbn/data-views-plugin/common';
import type { DataView } from '@kbn/data-views-plugin/common';
import { Adapters } from '@kbn/inspector-plugin/common';
import { coreMock } from '@kbn/core/public/mocks';
import { visualizationsPluginMock } from '@kbn/visualizations-plugin/public/mocks';

View file

@ -5,8 +5,8 @@
* 2.0.
*/
import { DataViewsContract, fieldList } from '@kbn/data-views-plugin/common';
import { createStubDataView } from '@kbn/data-views-plugin/common/stubs';
import type { DataView, DataViewsContract } from '@kbn/data-views-plugin/common';
import { createStubDataView, createStubDataViewLazy } from '@kbn/data-views-plugin/common/stubs';
import { defaultLogViewsStaticConfig } from './defaults';
import { ResolvedLogView, resolveLogView } from './resolved_log_view';
import { LogViewAttributes } from './types';
@ -14,15 +14,14 @@ 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<ResolvedLogView> = {}
): ResolvedLogView => ({
resolvedLogViewOverrides: Partial<ResolvedLogView<DataView>> = {}
): ResolvedLogView<DataView> => ({
name: 'LOG VIEW',
description: 'LOG VIEW DESCRIPTION',
indices: 'log-indices-*',
timestampField: 'TIMESTAMP_FIELD',
tiebreakerField: 'TIEBREAKER_FIELD',
messageField: ['MESSAGE_FIELD'],
fields: fieldList(),
runtimeMappings: {
runtime_field: {
type: 'keyword',
@ -52,15 +51,53 @@ export const createResolvedLogViewMock = (
...resolvedLogViewOverrides,
});
export const createResolvedLogViewLazyMock = (
resolvedLogViewOverrides: Partial<ResolvedLogView> = {}
): ResolvedLogView => ({
name: 'LOG VIEW',
description: 'LOG VIEW DESCRIPTION',
indices: 'log-indices-*',
timestampField: 'TIMESTAMP_FIELD',
tiebreakerField: 'TIEBREAKER_FIELD',
messageField: ['MESSAGE_FIELD'],
runtimeMappings: {
runtime_field: {
type: 'keyword',
script: {
source: 'emit("runtime value")',
},
},
},
columns: [
{ timestampColumn: { id: 'TIMESTAMP_COLUMN_ID' } },
{
fieldColumn: {
id: 'DATASET_COLUMN_ID',
field: 'event.dataset',
},
},
{
messageColumn: { id: 'MESSAGE_COLUMN_ID' },
},
],
dataViewReference: createStubDataViewLazy({
spec: {
id: 'log-view-data-view-mock',
title: 'log-indices-*',
},
}),
...resolvedLogViewOverrides,
});
export const createResolvedLogViewMockFromAttributes = (logViewAttributes: LogViewAttributes) =>
resolveLogView(
'log-view-id',
logViewAttributes,
{
get: async () => createStubDataView({ spec: {} }),
get: async () => createStubDataViewLazy({ spec: {} }),
getFieldsForWildcard: async () => [],
create: async (spec: DataViewSpec) =>
createStubDataView({
createStubDataViewLazy({
spec,
}),
} as unknown as DataViewsContract,

View file

@ -6,7 +6,12 @@
*/
import type { estypes } from '@elastic/elasticsearch';
import { DataView, DataViewsContract, FieldSpec } from '@kbn/data-views-plugin/common';
import type {
DataView,
DataViewLazy,
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';
@ -15,17 +20,16 @@ import { LogViewAttributes, LogViewColumnConfiguration, LogViewsStaticConfig } f
export type ResolvedLogViewField = FieldSpec;
export interface ResolvedLogView {
export interface ResolvedLogView<DataViewReference = DataViewLazy> {
name: string;
description: string;
indices: string;
timestampField: string;
tiebreakerField: string;
messageField: string[];
fields: ResolvedLogViewField[];
runtimeMappings: estypes.MappingRuntimeFields;
columns: LogViewColumnConfiguration[];
dataViewReference: DataView;
dataViewReference: DataViewReference;
}
export const resolveLogView = (
@ -60,19 +64,14 @@ const resolveLegacyReference = async (
}
const indices = logViewAttributes.logIndices.indexName;
const dataViewReference = await dataViewsService
.create(
{
id: `log-view-${logViewId}`,
name: logViewAttributes.name,
title: indices,
timeFieldName: TIMESTAMP_FIELD,
allowNoIndex: true,
},
false,
false
)
.createDataViewLazy({
id: `log-view-${logViewId}`,
name: logViewAttributes.name,
title: indices,
timeFieldName: TIMESTAMP_FIELD,
allowNoIndex: true,
})
.catch((error) => {
throw new ResolveLogViewError(`Failed to create Data View reference: ${error}`, error);
});
@ -82,7 +81,6 @@ const resolveLegacyReference = async (
timestampField: TIMESTAMP_FIELD,
tiebreakerField: TIEBREAKER_FIELD,
messageField: config.messageFields ?? defaultLogViewsStaticConfig.messageFields,
fields: dataViewReference.fields,
runtimeMappings: {},
columns: logViewAttributes.logColumns,
name: logViewAttributes.name,
@ -101,21 +99,20 @@ const resolveDataViewReference = async (
const { dataViewId } = logViewAttributes.logIndices;
const dataView = await dataViewsService.get(dataViewId).catch((error) => {
const dataViewLazy = await dataViewsService.getDataViewLazy(dataViewId).catch((error) => {
throw new ResolveLogViewError(`Failed to fetch data view "${dataViewId}": ${error}`, error);
});
return {
indices: dataView.getIndexPattern(),
timestampField: dataView.timeFieldName ?? TIMESTAMP_FIELD,
indices: dataViewLazy.getIndexPattern(),
timestampField: dataViewLazy.timeFieldName ?? TIMESTAMP_FIELD,
tiebreakerField: TIEBREAKER_FIELD,
messageField: ['message'],
fields: dataView.fields,
runtimeMappings: resolveRuntimeMappings(dataView),
runtimeMappings: resolveRuntimeMappings(dataViewLazy),
columns: logViewAttributes.logColumns,
name: logViewAttributes.name,
description: logViewAttributes.description,
dataViewReference: dataView,
dataViewReference: dataViewLazy,
};
};
@ -134,19 +131,14 @@ const resolveKibanaAdvancedSettingReference = async (
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
)
.createDataViewLazy({
id: `log-view-${logViewId}`,
name: logViewAttributes.name,
title: indices,
timeFieldName: TIMESTAMP_FIELD,
allowNoIndex: true,
})
.catch((error) => {
throw new ResolveLogViewError(`Failed to create Data View reference: ${error}`, error);
});
@ -156,7 +148,6 @@ const resolveKibanaAdvancedSettingReference = async (
timestampField: TIMESTAMP_FIELD,
tiebreakerField: TIEBREAKER_FIELD,
messageField: ['message'],
fields: dataViewReference.fields,
runtimeMappings: {},
columns: logViewAttributes.logColumns,
name: logViewAttributes.name,
@ -166,6 +157,8 @@ const resolveKibanaAdvancedSettingReference = async (
};
// this might take other sources of runtime fields into account in the future
const resolveRuntimeMappings = (dataView: DataView): estypes.MappingRuntimeFields => {
return dataView.getRuntimeMappings();
const resolveRuntimeMappings = (
dataViewLazy: DataView | DataViewLazy
): estypes.MappingRuntimeFields => {
return dataViewLazy.getRuntimeMappings();
};

View file

@ -5,4 +5,7 @@
* 2.0.
*/
export { createResolvedLogViewMock } from './log_views/resolved_log_view.mock';
export {
createResolvedLogViewMock,
createResolvedLogViewLazyMock,
} from './log_views/resolved_log_view.mock';

View file

@ -5,6 +5,7 @@
* 2.0.
*/
import type { DataView } from '@kbn/data-views-plugin/public';
import { LogViewReference, LogViewStatus, ResolvedLogView } from '../../../../common/log_views';
import { createNotificationChannel } from '../../xstate_helpers';
import { LogViewContext, LogViewEvent } from './types';
@ -16,7 +17,7 @@ export type LogViewNotificationEvent =
}
| {
type: 'LOADING_LOG_VIEW_SUCCEEDED';
resolvedLogView: ResolvedLogView;
resolvedLogView: ResolvedLogView<DataView>;
status: LogViewStatus;
}
| {

View file

@ -6,6 +6,7 @@
*/
import type { ActorRef } from 'xstate';
import type { DataView } from '@kbn/data-views-plugin/common';
import type {
LogView,
LogViewAttributes,
@ -25,7 +26,7 @@ export interface LogViewContextWithLogView {
}
export interface LogViewContextWithResolvedLogView {
resolvedLogView: ResolvedLogView;
resolvedLogView: ResolvedLogView<DataView>;
}
export interface LogViewContextWithStatus {
@ -113,7 +114,7 @@ export type LogViewEvent =
}
| {
type: 'RESOLUTION_SUCCEEDED';
resolvedLogView: ResolvedLogView;
resolvedLogView: ResolvedLogView<DataView>;
}
| {
type: 'UPDATE';

View file

@ -13,4 +13,5 @@ export const createLogViewsClientMock = (): jest.Mocked<ILogViewsClient> => ({
getResolvedLogViewStatus: jest.fn(),
putLogView: jest.fn(),
resolveLogView: jest.fn(),
unwrapDataViewLazy: jest.fn(),
});

View file

@ -8,7 +8,8 @@
import * as rt from 'io-ts';
import { HttpStart } from '@kbn/core/public';
import type { ISearchGeneric } from '@kbn/search-types';
import { DataViewsContract } from '@kbn/data-views-plugin/public';
import type { DataViewsContract } from '@kbn/data-views-plugin/public';
import type { DataView, DataViewLazy } from '@kbn/data-views-plugin/common';
import { lastValueFrom } from 'rxjs';
import { LogSourcesService } from '@kbn/logs-data-access-plugin/common/types';
import { getLogViewResponsePayloadRT, putLogViewRequestPayloadRT } from '../../../common/http_api';
@ -62,13 +63,29 @@ export class LogViewsClient implements ILogViewsClient {
return data;
}
public async getResolvedLogView(logViewReference: LogViewReference): Promise<ResolvedLogView> {
public async getResolvedLogView(
logViewReference: LogViewReference
): Promise<ResolvedLogView<DataView>> {
const logView = await this.getLogView(logViewReference);
const resolvedLogView = await this.resolveLogView(logView.id, logView.attributes);
return resolvedLogView;
}
public async getResolvedLogViewStatus(resolvedLogView: ResolvedLogView): Promise<LogViewStatus> {
public async unwrapDataViewLazy(
resolvedLogViewLazy: ResolvedLogView<DataViewLazy>
): Promise<ResolvedLogView<DataView>> {
const dataViewReference = await this.dataViews.toDataView(
resolvedLogViewLazy.dataViewReference
);
return {
...resolvedLogViewLazy,
dataViewReference,
};
}
public async getResolvedLogViewStatus(
resolvedLogView: ResolvedLogView<DataView>
): Promise<LogViewStatus> {
const indexStatus = await lastValueFrom(
this.search({
params: {
@ -153,14 +170,16 @@ export class LogViewsClient implements ILogViewsClient {
public async resolveLogView(
logViewId: string,
logViewAttributes: LogViewAttributes
): Promise<ResolvedLogView> {
return await resolveLogView(
): Promise<ResolvedLogView<DataView>> {
const resolvedDataViewLazy = await resolveLogView(
logViewId,
logViewAttributes,
this.dataViews,
this.logSourcesService,
this.config
);
return this.unwrapDataViewLazy(resolvedDataViewLazy);
}
}

View file

@ -9,6 +9,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 type { DataView, DataViewLazy } from '@kbn/data-views-plugin/common';
import {
LogView,
LogViewAttributes,
@ -35,11 +36,17 @@ export interface LogViewsServiceStartDeps {
export interface ILogViewsClient {
getLogView(logViewReference: LogViewReference): Promise<LogView>;
getResolvedLogViewStatus(resolvedLogView: ResolvedLogView): Promise<LogViewStatus>;
getResolvedLogView(logViewReference: LogViewReference): Promise<ResolvedLogView>;
getResolvedLogViewStatus(resolvedLogView: ResolvedLogView<DataView>): Promise<LogViewStatus>;
getResolvedLogView(logViewReference: LogViewReference): Promise<ResolvedLogView<DataView>>;
putLogView(
logViewReference: LogViewReference,
logViewAttributes: Partial<LogViewAttributes>
): Promise<LogView>;
resolveLogView(logViewId: string, logViewAttributes: LogViewAttributes): Promise<ResolvedLogView>;
resolveLogView(
logViewId: string,
logViewAttributes: LogViewAttributes
): Promise<ResolvedLogView<DataView>>;
unwrapDataViewLazy(
logViewLazy: ResolvedLogView<DataViewLazy>
): Promise<ResolvedLogView<DataView>>;
}

View file

@ -16,7 +16,7 @@ import {
import type { IEsSearchRequest, IEsSearchResponse } from '@kbn/search-types';
import { ISearchStrategy, SearchStrategyDependencies } from '@kbn/data-plugin/server';
import { createSearchSessionsClientMock } from '@kbn/data-plugin/server/search/mocks';
import { createResolvedLogViewMock } from '../../../common/log_views/resolved_log_view.mock';
import { createResolvedLogViewLazyMock } from '../../../common/log_views/resolved_log_view.mock';
import { createLogViewsClientMock } from '../log_views/log_views_client.mock';
import { createLogViewsServiceStartMock } from '../log_views/log_views_service.mock';
import {
@ -39,7 +39,7 @@ describe('LogEntries search strategy', () => {
const dataMock = createDataPluginMock(esSearchStrategyMock);
const logViewsClientMock = createLogViewsClientMock();
logViewsClientMock.getResolvedLogView.mockResolvedValue(createResolvedLogViewMock());
logViewsClientMock.getResolvedLogView.mockResolvedValue(createResolvedLogViewLazyMock());
const logViewsMock = createLogViewsServiceStartMock();
logViewsMock.getScopedClient.mockReturnValue(logViewsClientMock);
const mockDependencies = createSearchStrategyDependenciesMock();
@ -120,7 +120,7 @@ describe('LogEntries search strategy', () => {
});
const dataMock = createDataPluginMock(esSearchStrategyMock);
const logViewsClientMock = createLogViewsClientMock();
logViewsClientMock.getResolvedLogView.mockResolvedValue(createResolvedLogViewMock());
logViewsClientMock.getResolvedLogView.mockResolvedValue(createResolvedLogViewLazyMock());
const logViewsMock = createLogViewsServiceStartMock();
logViewsMock.getScopedClient.mockReturnValue(logViewsClientMock);
const mockDependencies = createSearchStrategyDependenciesMock();
@ -204,7 +204,7 @@ describe('LogEntries search strategy', () => {
});
const dataMock = createDataPluginMock(esSearchStrategyMock);
const logViewsClientMock = createLogViewsClientMock();
logViewsClientMock.getResolvedLogView.mockResolvedValue(createResolvedLogViewMock());
logViewsClientMock.getResolvedLogView.mockResolvedValue(createResolvedLogViewLazyMock());
const logViewsMock = createLogViewsServiceStartMock();
logViewsMock.getScopedClient.mockReturnValue(logViewsClientMock);
const mockDependencies = createSearchStrategyDependenciesMock();
@ -244,7 +244,7 @@ describe('LogEntries search strategy', () => {
});
const dataMock = createDataPluginMock(esSearchStrategyMock);
const logViewsClientMock = createLogViewsClientMock();
logViewsClientMock.getResolvedLogView.mockResolvedValue(createResolvedLogViewMock());
logViewsClientMock.getResolvedLogView.mockResolvedValue(createResolvedLogViewLazyMock());
const logViewsMock = createLogViewsServiceStartMock();
logViewsMock.getScopedClient.mockReturnValue(logViewsClientMock);

View file

@ -20,7 +20,7 @@ import { createSearchSessionsClientMock } from '@kbn/data-plugin/server/search/m
import { KbnSearchError } from '@kbn/data-plugin/server/search/report_search_error';
import { loggerMock } from '@kbn/logging-mocks';
import { EMPTY, lastValueFrom } from 'rxjs';
import { createResolvedLogViewMock } from '../../../common/log_views/resolved_log_view.mock';
import { createResolvedLogViewLazyMock } from '../../../common/log_views/resolved_log_view.mock';
import { createLogViewsClientMock } from '../log_views/log_views_client.mock';
import { createLogViewsServiceStartMock } from '../log_views/log_views_service.mock';
import {
@ -59,7 +59,7 @@ describe('LogEntry search strategy', () => {
const dataMock = createDataPluginMock(esSearchStrategy);
const logViewsClientMock = createLogViewsClientMock();
logViewsClientMock.getResolvedLogView.mockResolvedValue(createResolvedLogViewMock());
logViewsClientMock.getResolvedLogView.mockResolvedValue(createResolvedLogViewLazyMock());
const logViewsMock = createLogViewsServiceStartMock();
logViewsMock.getScopedClient.mockReturnValue(logViewsClientMock);
@ -162,7 +162,7 @@ describe('LogEntry search strategy', () => {
const dataMock = createDataPluginMock(esSearchStrategy);
const logViewsClientMock = createLogViewsClientMock();
logViewsClientMock.getResolvedLogView.mockResolvedValue(createResolvedLogViewMock());
logViewsClientMock.getResolvedLogView.mockResolvedValue(createResolvedLogViewLazyMock());
const logViewsMock = createLogViewsServiceStartMock();
logViewsMock.getScopedClient.mockReturnValue(logViewsClientMock);
@ -238,7 +238,7 @@ describe('LogEntry search strategy', () => {
const dataMock = createDataPluginMock(esSearchStrategy);
const logViewsClientMock = createLogViewsClientMock();
logViewsClientMock.getResolvedLogView.mockResolvedValue(createResolvedLogViewMock());
logViewsClientMock.getResolvedLogView.mockResolvedValue(createResolvedLogViewLazyMock());
const logViewsMock = createLogViewsServiceStartMock();
logViewsMock.getScopedClient.mockReturnValue(logViewsClientMock);
@ -274,7 +274,7 @@ describe('LogEntry search strategy', () => {
const dataMock = createDataPluginMock(esSearchStrategy);
const logViewsClientMock = createLogViewsClientMock();
logViewsClientMock.getResolvedLogView.mockResolvedValue(createResolvedLogViewMock());
logViewsClientMock.getResolvedLogView.mockResolvedValue(createResolvedLogViewLazyMock());
const logViewsMock = createLogViewsServiceStartMock();
logViewsMock.getScopedClient.mockReturnValue(logViewsClientMock);

View file

@ -6,14 +6,14 @@
*/
import type { LogViewReference } from '../../../common/log_views';
import { createResolvedLogViewMock } from '../../../common/log_views/resolved_log_view.mock';
import { createResolvedLogViewLazyMock } from '../../../common/log_views/resolved_log_view.mock';
import type { ILogViewsClient } from './types';
export const createLogViewsClientMock = (): jest.Mocked<ILogViewsClient> => ({
getLogView: jest.fn(),
getInternalLogView: jest.fn(),
getResolvedLogView: jest.fn((logViewReference: LogViewReference) =>
Promise.resolve(createResolvedLogViewMock())
Promise.resolve(createResolvedLogViewLazyMock())
),
putLogView: jest.fn(),
resolveLogView: jest.fn(),

View file

@ -8,7 +8,7 @@
import { loggerMock } from '@kbn/logging-mocks';
import { SavedObject, SavedObjectsUtils } from '@kbn/core/server';
import { savedObjectsClientMock } from '@kbn/core/server/mocks';
import { createStubDataView } from '@kbn/data-views-plugin/common/stubs';
import { createStubDataViewLazy } from '@kbn/data-views-plugin/common/stubs';
import { dataViewsService as dataViewsServiceMock } from '@kbn/data-views-plugin/server/mocks';
import {
defaultLogViewId,
@ -190,8 +190,8 @@ describe('LogViewsClient class', () => {
it('resolveLogView method resolves given LogViewAttributes with DataView reference', async () => {
const { logViewsClient, dataViews } = createLogViewsClient();
dataViews.get.mockResolvedValue(
createStubDataView({
dataViews.getDataViewLazy.mockResolvedValue(
createStubDataViewLazy({
spec: {
id: 'LOG_DATA_VIEW',
title: 'log-indices-*',
@ -249,13 +249,16 @@ describe('LogViewsClient class', () => {
},
},
],
"dataViewReference": DataView {
"dataViewReference": DataViewLazy {
"allowHidden": false,
"allowNoIndex": false,
"apiClient": Object {
"getFieldsForWildcard": [MockFunction],
},
"deleteFieldFormat": [Function],
"deleteScriptedFieldInternal": [Function],
"etag": undefined,
"fieldAttrs": Map {},
"fieldCache": Map {},
"fieldFormatMap": Object {},
"fieldFormats": Object {
"deserialize": [MockFunction],
@ -275,15 +278,16 @@ describe('LogViewsClient class', () => {
"parseDefaultTypeMap": [MockFunction],
"register": [MockFunction],
},
"fields": FldList [],
"flattenHit": [Function],
"getAllowHidden": [Function],
"getEtag": [Function],
"getFieldAttrs": [Function],
"getIndexPattern": [Function],
"getName": [Function],
"getOriginalSavedObjectBody": [Function],
"getRuntimeFieldSpecMap": [Function],
"getRuntimeFields": [Function],
"getTimeField": [Function],
"id": "LOG_DATA_VIEW",
"isTimeBased": [Function],
"matchedIndices": Array [],
"metaFields": Array [
"_id",
@ -302,9 +306,9 @@ describe('LogViewsClient class', () => {
"type": "keyword",
},
},
"scriptedFieldsEnabled": true,
"scriptedFieldsMap": Object {},
"setAllowHidden": [Function],
"setEtag": [Function],
"setFieldFormat": [Function],
"setIndexPattern": [Function],
"shortDotsEnable": false,
@ -313,12 +317,10 @@ describe('LogViewsClient class', () => {
"title": "log-indices-*",
"type": undefined,
"typeMeta": undefined,
"upsertScriptedField": [Function],
"upsertScriptedFieldInternal": [Function],
"version": "1",
},
"description": "LOG VIEW DESCRIPTION",
"fields": FldList [],
"indices": "log-indices-*",
"messageField": Array [
"message",

View file

@ -6,7 +6,7 @@
*/
import React, { useMemo } from 'react';
import { DataView } from '@kbn/data-views-plugin/common';
import type { DataView } from '@kbn/data-views-plugin/common';
import { fromKueryExpression, KueryNode, Query } from '@kbn/es-query';
import useAsync from 'react-use/lib/useAsync';

View file

@ -186,8 +186,8 @@ export const Editor: React.FC<RuleTypeParamsExpressionProps<PartialRuleParams, L
} = useMemo(() => decodeOrThrow(errorsRT)(errors), [errors]);
const supportedFields = useMemo(() => {
if (resolvedLogView?.fields) {
return resolvedLogView.fields.filter((field) => {
if (resolvedLogView?.dataViewReference.fields) {
return resolvedLogView.dataViewReference.fields.filter((field) => {
return (field.type === 'string' || field.type === 'number') && field.searchable;
});
} else {
@ -196,8 +196,8 @@ export const Editor: React.FC<RuleTypeParamsExpressionProps<PartialRuleParams, L
}, [resolvedLogView]);
const groupByFields = useMemo(() => {
if (resolvedLogView?.fields) {
return resolvedLogView.fields.filter((field) => {
if (resolvedLogView?.dataViewReference.fields) {
return resolvedLogView.dataViewReference.fields.filter((field) => {
return field.type === 'string' && field.aggregatable;
});
} else {

View file

@ -8,6 +8,7 @@
import React from 'react';
import { i18n } from '@kbn/i18n';
import { EuiFlexItem, EuiFlexGroup, EuiExpression, EuiToolTip } from '@elastic/eui';
import type { DataView } from '@kbn/data-views-plugin/common';
import type { ResolvedLogView } from '@kbn/logs-shared-plugin/common';
const description = i18n.translate('xpack.infra.logs.alertFlyout.logViewDescription', {
@ -15,7 +16,7 @@ const description = i18n.translate('xpack.infra.logs.alertFlyout.logViewDescript
});
interface LogViewSwitcherProps {
logView: ResolvedLogView;
logView: ResolvedLogView<DataView>;
}
/**