Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Discover] Add logs source and document contexts #184601

Merged
merged 67 commits into from
Jun 18, 2024
Merged
Show file tree
Hide file tree
Changes from 55 commits
Commits
Show all changes
67 commits
Select commit Hold shift + click to select a range
9e823b9
Initial pass at context provider services
davismcphee May 13, 2024
12e56b1
Initial context awareness implementation
davismcphee May 14, 2024
83f0696
Add profile service
davismcphee May 15, 2024
0a44de8
Add use_profile_accessor
davismcphee May 15, 2024
226cdd7
Add custom cell renderers and grid flyout
davismcphee May 15, 2024
4ca0e67
Attach document profiles to data table records
davismcphee May 16, 2024
f64aef3
Make root profile service async and add profiles provider
davismcphee May 16, 2024
ae19e34
Make data source profile service async and set it via profiles provider
davismcphee May 16, 2024
cbf6601
Move example profiles to separate file
davismcphee May 16, 2024
926ad4a
Improve example profiles
davismcphee May 17, 2024
d8fbdb7
Add default columns extension
davismcphee May 17, 2024
3afc77e
Don't display message field in cell renderer
davismcphee May 18, 2024
defad74
Add ProfilesManager
davismcphee May 19, 2024
efa94d1
Use ProfilesManager for accessing and setting profiles
davismcphee May 19, 2024
0115332
Change tsx files to ts
davismcphee May 21, 2024
fbf856b
Handle ProfilesManager abort controllers internally
davismcphee May 21, 2024
9c1b031
Rename ProfilesManager methods
davismcphee May 21, 2024
ff8aaeb
Remove static profile services and instead instantiate them in plugin…
davismcphee May 22, 2024
0964db1
Don't export useProfiles
davismcphee May 22, 2024
35f58a1
Retrieve ProfilesManager from services
davismcphee May 22, 2024
6a871aa
Remove show_confirm_panel since it's no longer used
davismcphee May 22, 2024
2e0b76e
Rename contextCollector to proflesCollector
davismcphee May 22, 2024
2db3ecc
Revert discover_data_state_container change
davismcphee May 22, 2024
2ea64d1
Fix broken types, Jest tests, and translations
davismcphee May 22, 2024
7e93b69
Simplify useProfileAccessor
davismcphee May 27, 2024
53ffd34
Attach context with profile ID to data table records
davismcphee May 28, 2024
19eba4c
Don't retrigger useProfiles on init
davismcphee May 28, 2024
4321c75
Move data source resolution before data fetching
davismcphee May 28, 2024
faa68c2
Log and fallback to default on context resolution failure
davismcphee May 30, 2024
e953b41
Remove profile provider ordering
davismcphee May 30, 2024
a5f2de8
Add profiles support to saved search embeddable
davismcphee May 30, 2024
fcc8ebc
Add Jest tests
davismcphee May 31, 2024
3d8ff5a
Clean up ProfilesManager
davismcphee May 31, 2024
15ea447
Add skeleton of logs profile providers
weltenwort May 31, 2024
3ce74dd
Set codeowners for the logs providers
weltenwort May 31, 2024
45b618b
feat(kbn-data-view-utils): add createRegExpPatternFrom util
May 31, 2024
c05c675
feat(kbn-data-view-utils): update createRegExpPatternFrom to support …
Jun 3, 2024
bb7d439
feat(kbn-data-view-utils): add testPatternAgainstAllowedList utils
Jun 3, 2024
314b033
refactor(logs_explorer): replace logs pattern matching utilities
Jun 3, 2024
5ecc0dd
implement actual log document resolution logic
weltenwort Jun 3, 2024
516e996
feat(discover): add initial logs data source resolution
Jun 4, 2024
e443c32
refactor(discover): extract types to resolve cyclic imports
Jun 4, 2024
c2ebbde
refactor(discover): update logs data source provider to factory function
Jun 4, 2024
5905c46
refactor(discover): move logs context utils into kbn-discover-utils
Jun 4, 2024
69d655d
refactor(discover): update logs document profile to use logs context …
Jun 4, 2024
2f68870
refactor(discover): update profiles imports/exports
Jun 5, 2024
28a5d2f
refactor(discover): update type predicates
Jun 6, 2024
08db9ae
Merge branch 'main' into one-discover-logs-contexts
tonyghiani Jun 11, 2024
5a32251
refactor(discover): update duplicate code
Jun 11, 2024
f657706
refactor(discover): revert changes missed in rebase
Jun 11, 2024
8ef60f2
refactor(discover): revert changes missed in rebase
Jun 11, 2024
7283f3c
refactor(discover): revert changes missed in rebase
Jun 11, 2024
9d09a4d
refactor(discover): fix linting issues
Jun 11, 2024
c3c9f61
Merge branch 'main' into one-discover-logs-contexts
tonyghiani Jun 11, 2024
4b925c9
[CI] Auto-commit changed files from 'node scripts/lint_ts_projects --…
kibanamachine Jun 11, 2024
326ac11
[CI] Auto-commit changed files from 'node scripts/generate codeowners'
kibanamachine Jun 11, 2024
07a6ecc
Merge branch 'main' into one-discover-logs-contexts
tonyghiani Jun 11, 2024
6957b86
refactor(logs-explorer): fix usage of logs criteria
Jun 11, 2024
23ad7d3
refactor(logs-explorer): update broken imports and tests
Jun 11, 2024
aab6cb6
Merge branch 'main' into one-discover-logs-contexts
tonyghiani Jun 11, 2024
baf9613
refactor(logs-explorer): revert test change
Jun 11, 2024
db98177
refactor(discover): update regexp to match potential _ in word bounda…
Jun 13, 2024
9ecedd5
Merge branch 'main' into one-discover-logs-contexts
tonyghiani Jun 13, 2024
f2f5462
Update packages/kbn-data-view-utils/src/utils/create_regexp_pattern_f…
tonyghiani Jun 13, 2024
f55015f
Merge branch 'main' into one-discover-logs-contexts
tonyghiani Jun 17, 2024
d7c7f55
Merge branch 'main' into one-discover-logs-contexts
tonyghiani Jun 17, 2024
35a32ce
Merge branch 'main' into one-discover-logs-contexts
davismcphee Jun 17, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,8 @@ examples/developer_examples @elastic/appex-sharedux
examples/discover_customization_examples @elastic/kibana-data-discovery
x-pack/plugins/discover_enhanced @elastic/kibana-data-discovery
src/plugins/discover @elastic/kibana-data-discovery
src/plugins/discover/public/context_awareness/profile_providers/log_document_profile @elastic/kibana-data-discovery @elastic/obs-ux-logs-team
Copy link
Contributor

@logeekal logeekal Jun 5, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @weltenwort , I remember there was a discussion regarding the code ownership.

Thinking about that doesn't it make sense to have olly profile providers in a separate package without having any impact on Discover's code.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To my knowledge the state of discussions was to keep everything in a unified directory structure for now so it's easily discoverable. @davismcphee have there been any further conversations on this topic?

Copy link
Contributor

@logeekal logeekal Jun 5, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay..got it. I remember @davismcphee's comment regarding keeping registeration inside Discover's directory structure but was not sure about the complete profile customization code. Sorry if i did not have full context.

The reason I ask this is I am also working on plan for security solution on similar lines and would be soon working on security related profiles providers.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I definitely have a preference for keeping the registrations inside Discover, but I'm a bit more flexible on where the provider code actually lives if solution teams have strong preferences here. The main thing is that Data Discovery is expected to be responsible for the overall experience in Discover and aware of when things change, so wherever the code lives, we should share ownership in CODEOWNERS.

The organization in this PR makes sense to me because we only need to update CODEOWNERS for a single folder, but I'm open to discuss it if Security has strong opinions otherwise.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I definitely have a preference for keeping the registrations inside Discover

Makes sense. I agree.

but I'm a bit more flexible on where the provider code actually lives if solution teams have strong preferences here

I do not have any strong opinions as I am still trying to understand and weigh in options.

Regarding the provider code, I am thinking it should not be too coupled of with discover's code. Provider code will be dependent on both solution specific utils(for example, o11y is separating out its utils in kbn-data-view-utils ) and discover code as well.

Imo, If code remains separate, we will take care to extract discover's code in discover-utils package, otherwise it is very easy for provider code be dependent on discover's core code and later when it grows big, it will be difficult to take it out.

May be you all have already talked about it but I am just thinking out loud here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Regarding the provider code, I am thinking it should not be too coupled of with discover's code

I think this is a reasonable goal πŸ‘

Imo, If code remains separate, we will take care to extract discover's code in discover-utils package, otherwise it is very easy for provider code be dependent on discover's core code

This is a fair concern, but I also wonder how far we can get with just being disciplined about what goes into the providers. In general I also don't think providers should have much dependence on Discover's core codebase (e.g. they shouldn't have access to internal state), and should mainly just depend on types and some utility functions, which typically should be fairly easy to pull out into packages as needed (a lot of our types and utilities already live in packages like kbn-discover-utils and kbn-data-view-utils).

src/plugins/discover/public/context_awareness/profile_providers/logs_data_source_profile @elastic/kibana-data-discovery @elastic/obs-ux-logs-team
src/plugins/discover_shared @elastic/kibana-data-discovery @elastic/obs-ux-logs-team
packages/kbn-discover-utils @elastic/kibana-data-discovery
packages/kbn-doc-links @elastic/docs
Expand Down
3 changes: 3 additions & 0 deletions packages/kbn-data-view-utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,6 @@
*/

export * from './src/constants';

export { createRegExpPatternFrom } from './src/utils/create_regexp_pattern_from';
export { testPatternAgainstAllowedList } from './src/utils/test_pattern_against_allowed_list';
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
* 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 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

import { createRegExpPatternFrom } from './create_regexp_pattern_from';

describe('createRegExpPatternFrom should create a regular expression starting from a string that', () => {
const regExpPattern = createRegExpPatternFrom('logs');

it('tests positive for single index patterns starting with the passed base pattern', () => {
expect('logs*').toMatch(regExpPattern);
expect('logs-*').toMatch(regExpPattern);
expect('logs-*-*').toMatch(regExpPattern);
expect('logs-system.syslog-*').toMatch(regExpPattern);

expect('logss*').not.toMatch(regExpPattern);
expect('logss-*').not.toMatch(regExpPattern);
expect('metrics*').not.toMatch(regExpPattern);
expect('metrics-*').not.toMatch(regExpPattern);
});

it('tests positive for single index patterns containing the passed base pattern', () => {
expect('foo-logs*').toMatch(regExpPattern);
expect('foo-logs-*').toMatch(regExpPattern);
expect('foo-logs-*-*').toMatch(regExpPattern);
expect('foo-logs-system.syslog-*').toMatch(regExpPattern);

expect('foo-logss*').not.toMatch(regExpPattern);
expect('foo-logss-*').not.toMatch(regExpPattern);
expect('foo-metrics*').not.toMatch(regExpPattern);
expect('foo-metrics-*').not.toMatch(regExpPattern);
});

it('tests positive for single index patterns with CCS prefixes', () => {
expect('cluster1:logs-*').toMatch(regExpPattern);
expect('cluster1:logs-*-*').toMatch(regExpPattern);
expect('cluster1:logs-system.syslog-*').toMatch(regExpPattern);
expect('cluster1:logs-system.syslog-default').toMatch(regExpPattern);

expect('cluster1:logss*').not.toMatch(regExpPattern);
expect('cluster1:logss-*').not.toMatch(regExpPattern);
expect('cluster1:metrics*').not.toMatch(regExpPattern);
expect('cluster1:metrics-*').not.toMatch(regExpPattern);
});

it('tests positive for multiple index patterns comma-separated if all of them individually match the criteria', () => {
expect('logs-*,cluster1:logs-*').toMatch(regExpPattern);
expect('cluster1:logs-*,cluster2:logs-*').toMatch(regExpPattern);
expect('*:logs-system.syslog-*,*:logs-system.errors-*').toMatch(regExpPattern);

expect('*:metrics-system.syslog-*,logs-system.errors-*').not.toMatch(regExpPattern);
});

it('tests positive for patterns with trialing commas', () => {
tonyghiani marked this conversation as resolved.
Show resolved Hide resolved
expect('logs-*,').toMatch(regExpPattern);
expect('cluster1:logs-*,logs-*,').toMatch(regExpPattern);
});

it('tests negative for patterns with spaces and unexpected commas', () => {
expect('cluster1:logs-*,clust,er2:logs-*').not.toMatch(regExpPattern);
expect('cluster1:logs-*, cluster2:logs-*').not.toMatch(regExpPattern);
});
});
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
/*
* 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.
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

export const buildIndexPatternRegExp = (basePatterns: string[]) => {
export const createRegExpPatternFrom = (basePatterns: string | string[]) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note

This utility function creates a regexp based on base pattern keywords.
The returned regexp allows to strictly test against complex indices, handling potential CCS patterns or comma-separated ones.

const patterns = Array.isArray(basePatterns) ? basePatterns : [basePatterns];
// Create the base patterns union with strict boundaries
const basePatternGroup = `\\b(${basePatterns.join('|')})\\b([^,\\s]+)?`;
const basePatternGroup = `[^,\\s]*\\b(${patterns.join('|')})\\b([^,\\s]*)?`;
// Apply base patterns union for local and remote clusters
const localAndRemotePatternGroup = `((${basePatternGroup})|([^:,\\s]+:${basePatternGroup}))`;
const localAndRemotePatternGroup = `((${basePatternGroup})|([^:,\\s]*:${basePatternGroup}))`;
// Handle trailing comma and multiple pattern concatenation
return new RegExp(`^${localAndRemotePatternGroup}(,${localAndRemotePatternGroup})*(,$|$)`, 'i');
};
Original file line number Diff line number Diff line change
@@ -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 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

import { testPatternAgainstAllowedList } from './test_pattern_against_allowed_list';

describe('testPatternAgainstAllowedList', () => {
const allowedList = ['foo-logs-bar', /^\b(logs)\b([^,\s]*)/i];

it('should return true if the passed input matches any string or regexp of the passed list', () => {
expect(testPatternAgainstAllowedList(allowedList)('logs-*')).toBeTruthy();
expect(testPatternAgainstAllowedList(allowedList)('logs-*-*')).toBeTruthy();
expect(testPatternAgainstAllowedList(allowedList)('logs-system.syslog-*')).toBeTruthy();
expect(testPatternAgainstAllowedList(allowedList)('foo-logs-bar')).toBeTruthy();

expect(testPatternAgainstAllowedList(allowedList)('logss-*')).toBeFalsy();
expect(testPatternAgainstAllowedList(allowedList)('metrics*')).toBeFalsy();
expect(testPatternAgainstAllowedList(allowedList)('metrics-*')).toBeFalsy();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
* 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 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

export const testPatternAgainstAllowedList =
(allowedList: Array<string | RegExp>) => (value: string) => {
for (const allowedItem of allowedList) {
const isMatchingString = typeof allowedItem === 'string' && value === allowedItem;
const isMatchingRegExp = allowedItem instanceof RegExp && allowedItem.test(value);

if (isMatchingString || isMatchingRegExp) {
return true;
}
}

// If no match is found in the allowedList, return false
return false;
};
3 changes: 3 additions & 0 deletions packages/kbn-discover-utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export {
IgnoredReason,
buildDataTableRecord,
buildDataTableRecordList,
createLogsContextService,
fieldConstants,
formatFieldValue,
formatHit,
Expand All @@ -43,4 +44,6 @@ export {
usePager,
} from './src';

export type { LogsContextService } from './src';

export * from './src/types';
2 changes: 2 additions & 0 deletions packages/kbn-discover-utils/src/data_types/logs/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,5 @@

export * from './types';
export * from './utils';

export * from './logs_context_service';
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* 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 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

import { createRegExpPatternFrom, testPatternAgainstAllowedList } from '@kbn/data-view-utils';

export interface LogsContextService {
isLogsIndexPattern(indexPattern: unknown): boolean;
}

// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface LogsContextServiceDeps {
// We will probably soon add uiSettings as a dependency
// to consume user configured indices
}

export const createLogsContextService = (_deps: LogsContextServiceDeps = {}) => {
// This is initially an hard-coded set of well-known base patterns,
// we can extend this allowed list with any setting coming from uiSettings
Comment on lines +31 to +32
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note

For additional context on the upcoming setting, check https://github.com/elastic/observability-dev/issues/3498

const ALLOWED_LOGS_DATA_SOURCES = [
createRegExpPatternFrom(['log', 'logs', 'logstash', 'auditbeat', 'filebeat', 'winlogbeat']),
];

const isLogsIndexPattern = (indexPattern: unknown) => {
return (
typeof indexPattern === 'string' &&
testPatternAgainstAllowedList(ALLOWED_LOGS_DATA_SOURCES)(indexPattern)
);
};

return {
isLogsIndexPattern,
};
};
1 change: 1 addition & 0 deletions packages/kbn-discover-utils/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
"kbn_references": [
"@kbn/data-service",
"@kbn/data-views-plugin",
"@kbn/data-view-utils",
"@kbn/es-query",
"@kbn/field-formats-plugin",
"@kbn/field-types",
Expand Down
8 changes: 8 additions & 0 deletions src/plugins/discover/common/data_sources/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,11 @@ export const isDataSourceType = <T extends DataSourceType>(
dataSource: DiscoverDataSource | undefined,
type: T
): dataSource is Extract<DiscoverDataSource, { type: T }> => dataSource?.type === type;

export const isDataViewSource = (
dataSource: DiscoverDataSource | undefined
): dataSource is DataViewDataSource => isDataSourceType(dataSource, DataSourceType.DataView);

export const isEsqlSource = (
dataSource: DiscoverDataSource | undefined
): dataSource is EsqlDataSource => isDataSourceType(dataSource, DataSourceType.Esql);
2 changes: 1 addition & 1 deletion src/plugins/discover/public/build_services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ import { memoize, noop } from 'lodash';
import type { NoDataPagePluginStart } from '@kbn/no-data-page-plugin/public';
import type { AiopsPluginStart } from '@kbn/aiops-plugin/public';
import type { DataVisualizerPluginStart } from '@kbn/data-visualizer-plugin/public';
import type { DiscoverStartPlugins } from './plugin';
import type { DiscoverStartPlugins } from './types';
import type { DiscoverContextAppLocator } from './application/context/services/locator';
import type { DiscoverSingleDocLocator } from './application/doc/locator';
import type { DiscoverAppLocator } from '../common';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
RootProfileService,
SolutionType,
} from '../profiles';
import { createProfileProviderServices } from '../profiles/profile_provider_services';
import { ProfilesManager } from '../profiles_manager';

export const createContextAwarenessMocks = () => {
Expand Down Expand Up @@ -89,12 +90,15 @@ export const createContextAwarenessMocks = () => {
documentProfileServiceMock
);

const profileProviderServices = createProfileProviderServices();

return {
rootProfileProviderMock,
dataSourceProfileProviderMock,
documentProfileProviderMock,
contextRecordMock,
contextRecordMock2,
profilesManagerMock,
profileProviderServices,
};
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/*
* 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 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

export { createLogDocumentProfileProvider } from './profile';
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*
* 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 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

import { buildDataTableRecord } from '@kbn/discover-utils';
import { DocumentType } from '../../profiles';
import { createContextAwarenessMocks } from '../../__mocks__';
import { createLogDocumentProfileProvider } from './profile';

const mockServices = createContextAwarenessMocks().profileProviderServices;

describe('logDocumentProfileProvider', () => {
const logDocumentProfileProvider = createLogDocumentProfileProvider(mockServices);
const RESOLUTION_MATCH = {
isMatch: true,
context: {
type: DocumentType.Log,
},
};
const RESOLUTION_MISMATCH = {
isMatch: false,
};

it('matches records with the correct data stream type', () => {
expect(
logDocumentProfileProvider.resolve({
record: buildMockRecord('logs-2000-01-01', {
'data_stream.type': ['logs'],
}),
})
).toEqual(RESOLUTION_MATCH);
});

it('matches records with fields prefixed with "log."', () => {
expect(
logDocumentProfileProvider.resolve({
record: buildMockRecord('logs-2000-01-01', {
'log.level': ['INFO'],
}),
})
).toEqual(RESOLUTION_MATCH);
});

it('matches records with indices matching the allowed pattern', () => {
expect(
logDocumentProfileProvider.resolve({
record: buildMockRecord('logs-2000-01-01'),
})
).toEqual(RESOLUTION_MATCH);
expect(
logDocumentProfileProvider.resolve({
record: buildMockRecord('remote_cluster:filebeat'),
})
).toEqual(RESOLUTION_MATCH);
});

it('does not match records with neither characteristic', () => {
expect(
logDocumentProfileProvider.resolve({
record: buildMockRecord('another-index'),
})
).toEqual(RESOLUTION_MISMATCH);
});
});

const buildMockRecord = (index: string, fields: Record<string, unknown[]> = {}) =>
buildDataTableRecord({
_id: '',
_index: index,
fields: {
_index: index,
...fields,
},
});
Loading