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] Only show logs profiles for O11y solution view #199255

Merged
merged 19 commits into from
Nov 18, 2024
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
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
1 change: 1 addition & 0 deletions .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -1289,6 +1289,7 @@ x-pack/test_serverless/**/test_suites/observability/ai_assistant @elastic/obs-ai
/x-pack/test/functional/apps/dataset_quality @elastic/obs-ux-logs-team
/x-pack/test_serverless/functional/test_suites/observability/dataset_quality @elastic/obs-ux-logs-team
/x-pack/test_serverless/functional/test_suites/observability/ @elastic/obs-ux-logs-team
/x-pack/test_serverless/functional/test_suites/observability/discover @elastic/obs-ux-logs-team @elastic/kibana-data-discovery
/src/plugins/unified_doc_viewer/public/components/doc_viewer_logs_overview @elastic/obs-ux-logs-team
/x-pack/test/api_integration/apis/logs_shared @elastic/obs-ux-logs-team

Expand Down
12 changes: 3 additions & 9 deletions oas_docs/output/kibana.serverless.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16693,14 +16693,10 @@ paths:
type: object
properties:
active:
description: >-
When false, the enrollment API key is revoked and
cannot be used for enrolling Elastic Agents.
description: When false, the enrollment API key is revoked and cannot be used for enrolling Elastic Agents.
jughosta marked this conversation as resolved.
Show resolved Hide resolved
type: boolean
api_key:
description: >-
The enrollment API key (token) used for enrolling
Elastic Agents.
description: The enrollment API key (token) used for enrolling Elastic Agents.
type: string
api_key_id:
description: The ID of the API key in the Security API.
Expand All @@ -16713,9 +16709,7 @@ paths:
description: The name of the enrollment API key.
type: string
policy_id:
description: >-
The ID of the agent policy the Elastic Agent will be
enrolled in.
description: The ID of the agent policy the Elastic Agent will be enrolled in.
type: string
required:
- id
Expand Down
12 changes: 3 additions & 9 deletions oas_docs/output/kibana.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19477,14 +19477,10 @@ paths:
type: object
properties:
active:
description: >-
When false, the enrollment API key is revoked and
cannot be used for enrolling Elastic Agents.
description: When false, the enrollment API key is revoked and cannot be used for enrolling Elastic Agents.
type: boolean
api_key:
description: >-
The enrollment API key (token) used for enrolling
Elastic Agents.
description: The enrollment API key (token) used for enrolling Elastic Agents.
type: string
api_key_id:
description: The ID of the API key in the Security API.
Expand All @@ -19497,9 +19493,7 @@ paths:
description: The name of the enrollment API key.
type: string
policy_id:
description: >-
The ID of the agent policy the Elastic Agent will be
enrolled in.
description: The ID of the agent policy the Elastic Agent will be enrolled in.
type: string
required:
- id
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@
* License v3.0 only", or the "Server Side Public License, v 1".
*/

export { createLogDocumentProfileProvider } from './profile';
export { createObservabilityLogDocumentProfileProvider } from './profile';
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,19 @@ import { DocViewsRegistry } from '@kbn/unified-doc-viewer';
import {
DataSourceCategory,
DataSourceContext,
DocumentProfileProviderParams,
DocumentType,
RootContext,
SolutionType,
} from '../../../profiles';
import { createContextAwarenessMocks } from '../../../__mocks__';
import { createLogDocumentProfileProvider } from './profile';
import { createObservabilityLogDocumentProfileProvider } from './profile';

const mockServices = createContextAwarenessMocks().profileProviderServices;

describe('logDocumentProfileProvider', () => {
const logDocumentProfileProvider = createLogDocumentProfileProvider(mockServices);
const ROOT_CONTEXT: RootContext = { solutionType: SolutionType.Default };
const logDocumentProfileProvider = createObservabilityLogDocumentProfileProvider(mockServices);
const ROOT_CONTEXT: RootContext = { solutionType: SolutionType.Observability };
const DATA_SOURCE_CONTEXT: DataSourceContext = { category: DataSourceCategory.Logs };
const RESOLUTION_MATCH = {
isMatch: true,
Expand Down Expand Up @@ -99,6 +100,39 @@ describe('logDocumentProfileProvider', () => {
).toEqual(RESOLUTION_MISMATCH);
});

it('does not match records when solution type is not Observability', () => {
const params: Omit<DocumentProfileProviderParams, 'rootContext'> = {
dataSourceContext: DATA_SOURCE_CONTEXT,
record: buildMockRecord('another-index', {
'data_stream.type': ['logs'],
}),
};
expect(
logDocumentProfileProvider.resolve({
...params,
rootContext: ROOT_CONTEXT,
})
).toEqual(RESOLUTION_MATCH);
expect(
logDocumentProfileProvider.resolve({
...params,
rootContext: { solutionType: SolutionType.Default },
})
).toEqual(RESOLUTION_MISMATCH);
expect(
logDocumentProfileProvider.resolve({
...params,
rootContext: { solutionType: SolutionType.Search },
})
).toEqual(RESOLUTION_MISMATCH);
expect(
logDocumentProfileProvider.resolve({
...params,
rootContext: { solutionType: SolutionType.Security },
})
).toEqual(RESOLUTION_MISMATCH);
});

describe('getDocViewer', () => {
it('adds a log overview doc view to the registry', () => {
const getDocViewer = logDocumentProfileProvider.profile.getDocViewer!(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,22 @@
*/

import { DataTableRecord } from '@kbn/discover-utils';
import { DocumentProfileProvider, DocumentType } from '../../../profiles';
import { DocumentProfileProvider, DocumentType, SolutionType } from '../../../profiles';
import { ProfileProviderServices } from '../../profile_provider_services';
import { getDocViewer } from './accessors';

export const createLogDocumentProfileProvider = (
export const createObservabilityLogDocumentProfileProvider = (
services: ProfileProviderServices
): DocumentProfileProvider => ({
profileId: 'log-document-profile',
profileId: 'observability-log-document-profile',
profile: {
getDocViewer,
},
resolve: ({ record }) => {
resolve: ({ record, rootContext }) => {
if (rootContext.solutionType !== SolutionType.Observability) {
return { isMatch: false };
}

const isLogRecord = getIsLogRecord(record, services.logsContextService.isLogsIndexPattern);

if (!isLogRecord) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ import {
createWindowsLogsDataSourceProfileProvider,
} from './sub_profiles';

export const createLogsDataSourceProfileProviders = (providerServices: ProfileProviderServices) => {
export const createObservabilityLogsDataSourceProfileProviders = (
providerServices: ProfileProviderServices
) => {
const logsDataSourceProfileProvider = createLogsDataSourceProfileProvider(providerServices);

return [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@
* License v3.0 only", or the "Server Side Public License, v 1".
*/

export { createLogsDataSourceProfileProviders } from './create_profile_providers';
export { createObservabilityLogsDataSourceProfileProviders } from './create_profile_providers';
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,12 @@ import { buildDataTableRecord } from '@kbn/discover-utils';
import type { EuiThemeComputed } from '@elastic/eui';
import { createStubIndexPattern } from '@kbn/data-views-plugin/common/data_view.stub';
import { createDataViewDataSource, createEsqlDataSource } from '../../../../../common/data_sources';
import { DataSourceCategory, RootContext, SolutionType } from '../../../profiles';
import {
DataSourceCategory,
DataSourceProfileProviderParams,
RootContext,
SolutionType,
} from '../../../profiles';
import { createContextAwarenessMocks } from '../../../__mocks__';
import { createLogsDataSourceProfileProvider } from './profile';
import { DataGridDensity } from '@kbn/unified-data-table';
Expand All @@ -24,7 +29,7 @@ describe('logsDataSourceProfileProvider', () => {
const VALID_INDEX_PATTERN = 'logs-nginx.access-*';
const MIXED_INDEX_PATTERN = 'logs-nginx.access-*,metrics-*';
const INVALID_INDEX_PATTERN = 'my_source-access-*';
const ROOT_CONTEXT: RootContext = { solutionType: SolutionType.Default };
const ROOT_CONTEXT: RootContext = { solutionType: SolutionType.Observability };
const RESOLUTION_MATCH = {
isMatch: true,
context: { category: DataSourceCategory.Logs },
Expand Down Expand Up @@ -87,6 +92,34 @@ describe('logsDataSourceProfileProvider', () => {
).toEqual(RESOLUTION_MISMATCH);
});

it('does NOT match data view sources when solution type is not Observability', () => {
const params: Omit<DataSourceProfileProviderParams, 'rootContext'> = {
dataSource: createEsqlDataSource(),
query: { esql: `from ${VALID_INDEX_PATTERN}` },
};
expect(logsDataSourceProfileProvider.resolve({ ...params, rootContext: ROOT_CONTEXT })).toEqual(
RESOLUTION_MATCH
);
expect(
logsDataSourceProfileProvider.resolve({
...params,
rootContext: { solutionType: SolutionType.Default },
})
).toEqual(RESOLUTION_MISMATCH);
expect(
logsDataSourceProfileProvider.resolve({
...params,
rootContext: { solutionType: SolutionType.Search },
})
).toEqual(RESOLUTION_MISMATCH);
expect(
logsDataSourceProfileProvider.resolve({
...params,
rootContext: { solutionType: SolutionType.Security },
})
).toEqual(RESOLUTION_MISMATCH);
});

const dataViewWithLogLevel = createStubIndexPattern({
spec: {
title: VALID_INDEX_PATTERN,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* License v3.0 only", or the "Server Side Public License, v 1".
*/

import { DataSourceCategory, DataSourceProfileProvider } from '../../../profiles';
import { DataSourceCategory, DataSourceProfileProvider, SolutionType } from '../../../profiles';
import { ProfileProviderServices } from '../../profile_provider_services';
import {
getCellRenderers,
Expand All @@ -19,13 +19,17 @@ import { extractIndexPatternFrom } from '../../extract_index_pattern_from';
export const createLogsDataSourceProfileProvider = (
services: ProfileProviderServices
): DataSourceProfileProvider => ({
profileId: 'logs-data-source-profile',
profileId: 'observability-logs-data-source-profile',
profile: {
getCellRenderers,
getRowIndicatorProvider,
getRowAdditionalLeadingControls,
},
resolve: (params) => {
if (params.rootContext.solutionType !== SolutionType.Observability) {
return { isMatch: false };
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Tip

Non-blocking suggestion, as this would work perfectly 👌

This condition should probably reflect how we resolve the O11y root profile, which means this needs to change and be aligned every time we update the logic for the O11y root profile resolution.

I don't expect that to change often, but we might miss some corner cases if we forget to update the logic also here and anywhere else this is implemented in this PR.

Have you considered to use the root profile resolve declaration to keep the resolution logic centralized and inherit it here?

resolve: async (params) => {
  const observabilityRootProfile = await createObservabilityRootProfileProvider(services).resolve(
    { solutionNavId: params.rootContext.solutionType }
  );

  if (!observabilityRootProfile.isMatch) {
    return { isMatch: false };
  }
  
  // ...
},

Copy link
Contributor Author

Choose a reason for hiding this comment

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

As we discussed offline, while we can't re-execute the root profile resolution logic (since it's async while document profile resolution is sync), I've updated the rootContext checks to look at profileId instead of solutionType, which has the same effect of protecting against future changes: a41d43e.


const indexPattern = extractIndexPatternFrom(params);

if (!services.logsContextService.isLogsIndexPattern(indexPattern)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { createContextAwarenessMocks } from '../../../../__mocks__';
import { createLogsDataSourceProfileProvider } from '../profile';
import { createApacheErrorLogsDataSourceProfileProvider } from './apache_error_logs';

const ROOT_CONTEXT: RootContext = { solutionType: SolutionType.Default };
const ROOT_CONTEXT: RootContext = { solutionType: SolutionType.Observability };
const { profileProviderServices } = createContextAwarenessMocks();
const logsDataSourceProfileProvider = createLogsDataSourceProfileProvider(profileProviderServices);
const dataSourceProfileProvider = createApacheErrorLogsDataSourceProfileProvider(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export const createApacheErrorLogsDataSourceProfileProvider = (
logsDataSourceProfileProvider: DataSourceProfileProvider
): DataSourceProfileProvider =>
extendProfileProvider(logsDataSourceProfileProvider, {
profileId: 'apache-error-logs-data-source',
profileId: 'observability-apache-error-logs-data-source-profile',
profile: {
getDefaultAppState: createGetDefaultAppState({
defaultColumns: [LOG_LEVEL_COLUMN, CLIENT_IP_COLUMN, MESSAGE_COLUMN],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { createContextAwarenessMocks } from '../../../../__mocks__';
import { createLogsDataSourceProfileProvider } from '../profile';
import { createAwsS3accessLogsDataSourceProfileProvider } from './aws_s3access_logs';

const ROOT_CONTEXT: RootContext = { solutionType: SolutionType.Default };
const ROOT_CONTEXT: RootContext = { solutionType: SolutionType.Observability };
const { profileProviderServices } = createContextAwarenessMocks();
const logsDataSourceProfileProvider = createLogsDataSourceProfileProvider(profileProviderServices);
const dataSourceProfileProvider = createAwsS3accessLogsDataSourceProfileProvider(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export const createAwsS3accessLogsDataSourceProfileProvider = (
logsDataSourceProfileProvider: DataSourceProfileProvider
): DataSourceProfileProvider =>
extendProfileProvider(logsDataSourceProfileProvider, {
profileId: 'aws-s3access-logs-data-source',
profileId: 'observability-aws-s3access-logs-data-source-profile',
profile: {
getDefaultAppState: createGetDefaultAppState({
defaultColumns: [
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/*
* 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", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/

import { createEsqlDataSource } from '../../../../../../common/data_sources';
import {
DataSourceCategory,
DataSourceProfileProviderParams,
RootContext,
SolutionType,
} from '../../../../profiles';
import { createResolve } from './create_resolve';

describe('createResolve', () => {
const VALID_INDEX_PATTERN = 'valid';
const INVALID_INDEX_PATTERN = 'invalid';
const ROOT_CONTEXT: RootContext = { solutionType: SolutionType.Observability };
const RESOLUTION_MATCH = {
isMatch: true,
context: { category: DataSourceCategory.Logs },
};
const RESOLUTION_MISMATCH = {
isMatch: false,
};
const resolve = createResolve(VALID_INDEX_PATTERN);

it('should match a valid index pattern', () => {
const result = resolve({
rootContext: ROOT_CONTEXT,
dataSource: createEsqlDataSource(),
query: { esql: `FROM ${VALID_INDEX_PATTERN}` },
});
expect(result).toEqual(RESOLUTION_MATCH);
});

it('should not match an invalid index pattern', () => {
const result = resolve({
rootContext: ROOT_CONTEXT,
dataSource: createEsqlDataSource(),
query: { esql: `FROM ${INVALID_INDEX_PATTERN}` },
});
expect(result).toEqual(RESOLUTION_MISMATCH);
});

it('should not match when the solution type is not Observability', () => {
const params: Omit<DataSourceProfileProviderParams, 'rootContext'> = {
dataSource: createEsqlDataSource(),
query: { esql: `FROM ${VALID_INDEX_PATTERN}` },
};
expect(
resolve({
...params,
rootContext: ROOT_CONTEXT,
})
).toEqual(RESOLUTION_MATCH);
expect(
resolve({
...params,
rootContext: { solutionType: SolutionType.Default },
})
).toEqual(RESOLUTION_MISMATCH);
expect(
resolve({
...params,
rootContext: { solutionType: SolutionType.Search },
})
).toEqual(RESOLUTION_MISMATCH);
expect(
resolve({
...params,
rootContext: { solutionType: SolutionType.Security },
})
).toEqual(RESOLUTION_MISMATCH);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
*/

import { createRegExpPatternFrom, testPatternAgainstAllowedList } from '@kbn/data-view-utils';
import { DataSourceCategory, DataSourceProfileProvider } from '../../../../profiles';
import { DataSourceCategory, DataSourceProfileProvider, SolutionType } from '../../../../profiles';
import { extractIndexPatternFrom } from '../../../extract_index_pattern_from';

export const createResolve = (baseIndexPattern: string): DataSourceProfileProvider['resolve'] => {
Expand All @@ -17,6 +17,10 @@ export const createResolve = (baseIndexPattern: string): DataSourceProfileProvid
]);

return (params) => {
if (params.rootContext.solutionType !== SolutionType.Observability) {
return { isMatch: false };
}

const indexPattern = extractIndexPatternFrom(params);

if (!indexPattern || !testIndexPattern(indexPattern)) {
Expand Down
Loading