[Infra UI] Fix Open in Logs links in Infra and APM when in Serverless (#172137)

Fixes https://github.com/elastic/kibana/issues/171082

## Summary

The PR wraps the
[LogsLocator](f59ac2916d/x-pack/plugins/infra/common/locators/logs_locator.ts (L18C27-L18C27))
and
[NodeLogsLocator](f59ac2916d/x-pack/plugins/infra/common/locators/node_logs_locator.ts (L16))
of **infra** plugin inside corresponding locators in **logs_shared**
plugin while including the fallback logic to navigate to Logs Explorer
when Steam UI isn't available.

Previously, it was assumed that Steam UI will always be available as
long as Infra UI is available, but **infra** plugin introduced a new
feature flag `logsUIEnabled` which when `false` won't enable the
`/stream/` route in Serverless.

The added locators in **logs_shared** will now check whether locators
redirecting to `/steam/` are available, otherwise they'll redirect to
Logs Explorer, thus the new locators are abstracting this decision in
their definition. This abstraction was already being done in **apm**
plugin, which has also been refactored to use the newly added
**logs_shared** locators.

Links in Serverless:


16e5747a-546e-44b3-87e3-95428945cf63
This commit is contained in:
Abdul Wahab Zahid 2024-01-10 16:33:01 +01:00 committed by GitHub
parent 30ce43bea3
commit 2f2083b718
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
33 changed files with 441 additions and 319 deletions

View file

@ -19,10 +19,7 @@ import {
AllDatasetsLocatorParams,
ALL_DATASETS_LOCATOR_ID,
} from '@kbn/deeplinks-observability/locators';
import {
NODE_LOGS_LOCATOR_ID,
NodeLogsLocatorParams,
} from '@kbn/logs-shared-plugin/common';
import { getLogsLocatorsFromUrlService } from '@kbn/logs-shared-plugin/common';
import { isJavaAgentName } from '../../../../../../common/agent_name';
import { SERVICE_NODE_NAME } from '../../../../../../common/es_fields/apm';
import { useApmPluginContext } from '../../../../../context/apm_plugin/use_apm_plugin_context';
@ -63,8 +60,7 @@ export function InstanceActionsMenu({
const allDatasetsLocator = share.url.locators.get<AllDatasetsLocatorParams>(
ALL_DATASETS_LOCATOR_ID
)!;
const nodeLogsLocator =
share.url.locators.get<NodeLogsLocatorParams>(NODE_LOGS_LOCATOR_ID)!;
const { nodeLogsLocator } = getLogsLocatorsFromUrlService(share.url);
if (isPending(status)) {
return (

View file

@ -8,10 +8,10 @@
import { i18n } from '@kbn/i18n';
import { IBasePath } from '@kbn/core/public';
import moment from 'moment';
import type { LocatorPublic } from '@kbn/share-plugin/public';
import { AllDatasetsLocatorParams } from '@kbn/deeplinks-observability/locators';
import type { LocatorPublic } from '@kbn/share-plugin/public';
import { NodeLogsLocatorParams } from '@kbn/logs-shared-plugin/common';
import { getNodeLogsHref } from '../../../../shared/links/observability_logs_link';
import { findInventoryFields } from '@kbn/metrics-data-access-plugin/common';
import { APIReturnType } from '../../../../../services/rest/create_call_apm_api';
import { getInfraHref } from '../../../../shared/links/infra_link';
import {
@ -58,20 +58,17 @@ export function getMenuSections({
: undefined;
const infraMetricsQuery = getInfraMetricsQuery(instanceDetails['@timestamp']);
const podLogsHref = getNodeLogsHref(
'pod',
podId!,
const podLogsHref = nodeLogsLocator.getRedirectUrl({
nodeField: findInventoryFields('pod').id,
nodeId: podId!,
time,
allDatasetsLocator,
nodeLogsLocator
);
const containerLogsHref = getNodeLogsHref(
'container',
containerId!,
});
const containerLogsHref = nodeLogsLocator.getRedirectUrl({
nodeField: findInventoryFields('container').id,
nodeId: containerId!,
time,
allDatasetsLocator,
nodeLogsLocator
);
});
const podActions: Action[] = [
{

View file

@ -1,89 +0,0 @@
/*
* 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 type {
LogsLocatorParams,
NodeLogsLocatorParams,
} from '@kbn/logs-shared-plugin/common';
import { AllDatasetsLocatorParams } from '@kbn/deeplinks-observability/locators';
import { LocatorPublic } from '@kbn/share-plugin/common';
import moment from 'moment';
import { DurationInputObject } from 'moment';
type NodeType = 'host' | 'pod' | 'container';
const NodeTypeMapping: Record<NodeType, string> = {
host: 'host.name',
container: 'container.id',
pod: 'kubernetes.pod.uid',
};
export const getNodeLogsHref = (
nodeType: NodeType,
id: string,
time: number | undefined,
allDatasetsLocator: LocatorPublic<AllDatasetsLocatorParams>,
infraNodeLocator?: LocatorPublic<NodeLogsLocatorParams>
): string => {
if (infraNodeLocator)
return infraNodeLocator?.getRedirectUrl({
nodeId: id!,
nodeType,
time,
});
return allDatasetsLocator.getRedirectUrl({
query: getNodeQuery(nodeType, id),
...(time
? {
timeRange: {
from: getTimeRangeStartFromTime(time),
to: getTimeRangeEndFromTime(time),
},
}
: {}),
});
};
export const getTraceLogsHref = (
traceId: string,
time: number | undefined,
allDatasetsLocator: LocatorPublic<AllDatasetsLocatorParams>,
infraLogsLocator: LocatorPublic<LogsLocatorParams>
): string => {
const query = `trace.id:"${traceId}" OR (not trace.id:* AND "${traceId}")`;
if (infraLogsLocator)
return infraLogsLocator.getRedirectUrl({
filter: query,
time,
});
return allDatasetsLocator.getRedirectUrl({
query: { language: 'kuery', query },
...(time
? {
timeRange: {
from: getTimeRangeStartFromTime(time),
to: getTimeRangeEndFromTime(time),
},
}
: {}),
});
};
const getNodeQuery = (type: NodeType, id: string) => {
return { language: 'kuery', query: `${NodeTypeMapping[type]}: ${id}` };
};
const defaultTimeRangeFromPositionOffset: DurationInputObject = { hours: 1 };
const getTimeRangeStartFromTime = (time: number): string =>
moment(time).subtract(defaultTimeRangeFromPositionOffset).toISOString();
const getTimeRangeEndFromTime = (time: number): string =>
moment(time).add(defaultTimeRangeFromPositionOffset).toISOString();

View file

@ -7,11 +7,6 @@
import { createMemoryHistory } from 'history';
import { IBasePath } from '@kbn/core/public';
import { LocatorPublic } from '@kbn/share-plugin/common';
import {
LogsLocatorParams,
NodeLogsLocatorParams,
} from '@kbn/logs-shared-plugin/common';
import { Transaction } from '../../../../typings/es_schemas/ui/transaction';
import { getSections } from './sections';
import {
@ -19,7 +14,7 @@ import {
ApmRouter,
} from '../../routing/apm_route_config';
import {
infraLocatorsMock,
logsLocatorsMock,
observabilityLogExplorerLocatorsMock,
} from '../../../context/apm_plugin/mock_apm_plugin_context';
@ -30,11 +25,11 @@ const apmRouter = {
} as ApmRouter;
const { allDatasetsLocator } = observabilityLogExplorerLocatorsMock;
const { nodeLogsLocator, logsLocator } = infraLocatorsMock;
const { nodeLogsLocator, traceLogsLocator } = logsLocatorsMock;
const expectInfraLocatorsToBeCalled = () => {
const expectLogsLocatorsToBeCalled = () => {
expect(nodeLogsLocator.getRedirectUrl).toBeCalledTimes(3);
expect(logsLocator.getRedirectUrl).toBeCalledTimes(1);
expect(traceLogsLocator.getRedirectUrl).toBeCalledTimes(1);
};
describe('Transaction action menu', () => {
@ -70,9 +65,7 @@ describe('Transaction action menu', () => {
location,
apmRouter,
allDatasetsLocator,
logsLocator: logsLocator as unknown as LocatorPublic<LogsLocatorParams>,
nodeLogsLocator:
nodeLogsLocator as unknown as LocatorPublic<NodeLogsLocatorParams>,
logsLocators: logsLocatorsMock,
infraLinksAvailable: false,
rangeFrom: 'now-24h',
rangeTo: 'now',
@ -121,7 +114,7 @@ describe('Transaction action menu', () => {
},
],
]);
expectInfraLocatorsToBeCalled();
expectLogsLocatorsToBeCalled();
});
it('shows pod and required sections only', () => {
@ -138,10 +131,8 @@ describe('Transaction action menu', () => {
basePath,
location,
apmRouter,
logsLocator: logsLocator as unknown as LocatorPublic<LogsLocatorParams>,
nodeLogsLocator:
nodeLogsLocator as unknown as LocatorPublic<NodeLogsLocatorParams>,
allDatasetsLocator,
logsLocators: logsLocatorsMock,
infraLinksAvailable: true,
rangeFrom: 'now-24h',
rangeTo: 'now',
@ -209,7 +200,7 @@ describe('Transaction action menu', () => {
},
],
]);
expectInfraLocatorsToBeCalled();
expectLogsLocatorsToBeCalled();
});
it('shows host and required sections only', () => {
@ -226,10 +217,8 @@ describe('Transaction action menu', () => {
basePath,
location,
apmRouter,
logsLocator: logsLocator as unknown as LocatorPublic<LogsLocatorParams>,
nodeLogsLocator:
nodeLogsLocator as unknown as LocatorPublic<NodeLogsLocatorParams>,
allDatasetsLocator,
logsLocators: logsLocatorsMock,
infraLinksAvailable: true,
rangeFrom: 'now-24h',
rangeTo: 'now',
@ -296,6 +285,6 @@ describe('Transaction action menu', () => {
},
],
]);
expectInfraLocatorsToBeCalled();
expectLogsLocatorsToBeCalled();
});
});

View file

@ -11,10 +11,8 @@ import { IBasePath } from '@kbn/core/public';
import { isEmpty, pickBy } from 'lodash';
import moment from 'moment';
import url from 'url';
import {
LogsLocatorParams,
NodeLogsLocatorParams,
} from '@kbn/logs-shared-plugin/common';
import type { getLogsLocatorsFromUrlService } from '@kbn/logs-shared-plugin/common';
import { findInventoryFields } from '@kbn/metrics-data-access-plugin/common';
import { LocatorPublic } from '@kbn/share-plugin/common';
import { AllDatasetsLocatorParams } from '@kbn/deeplinks-observability/locators';
import type { ProfilingLocators } from '@kbn/observability-shared-plugin/public';
@ -27,10 +25,6 @@ import { fromQuery } from '../links/url_helpers';
import { SectionRecord, getNonEmptySections, Action } from './sections_helper';
import { HOST_NAME, TRACE_ID } from '../../../../common/es_fields/apm';
import { ApmRouter } from '../../routing/apm_route_config';
import {
getNodeLogsHref,
getTraceLogsHref,
} from '../links/observability_logs_link';
function getInfraMetricsQuery(transaction: Transaction) {
const timestamp = new Date(transaction['@timestamp']).getTime();
@ -53,8 +47,7 @@ export const getSections = ({
rangeTo,
environment,
allDatasetsLocator,
logsLocator,
nodeLogsLocator,
logsLocators,
dataViewId,
}: {
transaction?: Transaction;
@ -67,8 +60,7 @@ export const getSections = ({
rangeTo: string;
environment: Environment;
allDatasetsLocator: LocatorPublic<AllDatasetsLocatorParams>;
logsLocator: LocatorPublic<LogsLocatorParams>;
nodeLogsLocator: LocatorPublic<NodeLogsLocatorParams>;
logsLocators: ReturnType<typeof getLogsLocatorsFromUrlService>;
dataViewId?: string;
}) => {
if (!transaction) return [];
@ -95,33 +87,26 @@ export const getSections = ({
});
// Logs hrefs
const podLogsHref = getNodeLogsHref(
'pod',
podId!,
const podLogsHref = logsLocators.nodeLogsLocator.getRedirectUrl({
nodeField: findInventoryFields('pod').id,
nodeId: podId!,
time,
allDatasetsLocator,
nodeLogsLocator
);
const containerLogsHref = getNodeLogsHref(
'container',
containerId!,
});
const containerLogsHref = logsLocators.nodeLogsLocator.getRedirectUrl({
nodeField: findInventoryFields('container').id,
nodeId: containerId!,
time,
allDatasetsLocator,
nodeLogsLocator
);
const hostLogsHref = getNodeLogsHref(
'host',
hostName!,
});
const hostLogsHref = logsLocators.nodeLogsLocator.getRedirectUrl({
nodeField: findInventoryFields('host').id,
nodeId: hostName!,
time,
allDatasetsLocator,
nodeLogsLocator
);
const traceLogsHref = getTraceLogsHref(
transaction.trace.id!,
});
const traceLogsHref = logsLocators.traceLogsLocator.getRedirectUrl({
traceId: transaction.trace.id!,
time,
allDatasetsLocator,
logsLocator
);
});
const podActions: Action[] = [
{

View file

@ -13,13 +13,14 @@ import { License } from '@kbn/licensing-plugin/common/license';
import {
LOGS_LOCATOR_ID,
NODE_LOGS_LOCATOR_ID,
TRACE_LOGS_LOCATOR_ID,
} from '@kbn/logs-shared-plugin/common';
import { Transaction } from '../../../../typings/es_schemas/ui/transaction';
import { ApmPluginContextValue } from '../../../context/apm_plugin/apm_plugin_context';
import {
mockApmPluginContextValue,
MockApmPluginContextWrapper,
infraLocatorsMock,
logsLocatorsMock,
} from '../../../context/apm_plugin/mock_apm_plugin_context';
import { LicenseContext } from '../../../context/license/license_context';
import * as hooks from '../../../hooks/use_fetcher';
@ -43,11 +44,15 @@ const apmContextMock = {
locators: {
get: (id: string) => {
if (id === LOGS_LOCATOR_ID) {
return infraLocatorsMock.logsLocator;
return logsLocatorsMock.logsLocator;
}
if (id === NODE_LOGS_LOCATOR_ID) {
return infraLocatorsMock.nodeLogsLocator;
return logsLocatorsMock.nodeLogsLocator;
}
if (id === TRACE_LOGS_LOCATOR_ID) {
return logsLocatorsMock.traceLogsLocator;
}
},
},
@ -102,9 +107,9 @@ const renderTransaction = async (transaction: Record<string, any>) => {
return rendered;
};
const expectInfraLocatorsToBeCalled = () => {
expect(infraLocatorsMock.nodeLogsLocator.getRedirectUrl).toBeCalled();
expect(infraLocatorsMock.logsLocator.getRedirectUrl).toBeCalled();
const expectLogsLocatorsToBeCalled = () => {
expect(logsLocatorsMock.nodeLogsLocator.getRedirectUrl).toBeCalled();
expect(logsLocatorsMock.traceLogsLocator.getRedirectUrl).toBeCalled();
};
let useAdHocApmDataViewSpy: jest.SpyInstance;
@ -144,10 +149,10 @@ describe('TransactionActionMenu ', () => {
expect(findByText('View transaction in Discover')).not.toBeNull();
});
it('should call infra locators getRedirectUrl function', async () => {
it('should call logs locators getRedirectUrl function', async () => {
await renderTransaction(Transactions.transactionWithMinimalData);
expectInfraLocatorsToBeCalled();
expectLogsLocatorsToBeCalled();
});
describe('when there is no pod id', () => {
@ -169,10 +174,10 @@ describe('TransactionActionMenu ', () => {
});
describe('when there is a pod id', () => {
it('should call infra locators getRedirectUrl function', async () => {
it('should call logs locators getRedirectUrl function', async () => {
await renderTransaction(Transactions.transactionWithKubernetesData);
expectInfraLocatorsToBeCalled();
expectLogsLocatorsToBeCalled();
});
it('renders the pod metrics link', async () => {
@ -206,11 +211,11 @@ describe('TransactionActionMenu ', () => {
});
});
describe('should call infra locators getRedirectUrl function', () => {
describe('should call logs locators getRedirectUrl function', () => {
it('renders the Container logs link', async () => {
await renderTransaction(Transactions.transactionWithContainerData);
expectInfraLocatorsToBeCalled();
expectLogsLocatorsToBeCalled();
});
it('renders the Container metrics link', async () => {
@ -245,10 +250,10 @@ describe('TransactionActionMenu ', () => {
});
describe('when there is a hostname', () => {
it('should call infra locators getRedirectUrl function', async () => {
it('should call logs locators getRedirectUrl function', async () => {
await renderTransaction(Transactions.transactionWithHostData);
expectInfraLocatorsToBeCalled();
expectLogsLocatorsToBeCalled();
});
it('renders the Host metrics link', async () => {

View file

@ -25,13 +25,8 @@ import {
AllDatasetsLocatorParams,
ALL_DATASETS_LOCATOR_ID,
} from '@kbn/deeplinks-observability/locators';
import {
LOGS_LOCATOR_ID,
LogsLocatorParams,
NODE_LOGS_LOCATOR_ID,
NodeLogsLocatorParams,
} from '@kbn/logs-shared-plugin/common';
import type { ProfilingLocators } from '@kbn/observability-shared-plugin/public';
import { getLogsLocatorsFromUrlService } from '@kbn/logs-shared-plugin/common';
import { useAnyOfApmParams } from '../../../hooks/use_apm_params';
import { ApmFeatureFlagName } from '../../../../common/apm_feature_flags';
import { Transaction } from '../../../../typings/es_schemas/ui/transaction';
@ -144,10 +139,7 @@ function ActionMenuSections({
const allDatasetsLocator = share.url.locators.get<AllDatasetsLocatorParams>(
ALL_DATASETS_LOCATOR_ID
)!;
const logsLocator =
share.url.locators.get<LogsLocatorParams>(LOGS_LOCATOR_ID)!;
const nodeLogsLocator =
share.url.locators.get<NodeLogsLocatorParams>(NODE_LOGS_LOCATOR_ID)!;
const logsLocators = getLogsLocatorsFromUrlService(share.url);
const infraLinksAvailable = useApmFeatureFlag(
ApmFeatureFlagName.InfraUiAvailable
@ -173,8 +165,7 @@ function ActionMenuSections({
rangeTo,
environment,
allDatasetsLocator,
logsLocator,
nodeLogsLocator,
logsLocators,
dataViewId: dataView?.id,
});

View file

@ -13,6 +13,11 @@ import { merge } from 'lodash';
import { coreMock } from '@kbn/core/public/mocks';
import { UrlService } from '@kbn/share-plugin/common/url_service';
import { createObservabilityRuleTypeRegistryMock } from '@kbn/observability-plugin/public';
import {
LogsLocatorParams,
NodeLogsLocatorParams,
TraceLogsLocatorParams,
} from '@kbn/logs-shared-plugin/common';
import { UI_SETTINGS } from '@kbn/data-plugin/common';
import { MlLocatorDefinition } from '@kbn/ml-plugin/public';
import { enableComparisonByDefault } from '@kbn/observability-plugin/public';
@ -131,9 +136,10 @@ export const observabilityLogExplorerLocatorsMock = {
singleDatasetLocator: sharePluginMock.createLocator(),
};
export const infraLocatorsMock = {
nodeLogsLocator: sharePluginMock.createLocator(),
logsLocator: sharePluginMock.createLocator(),
export const logsLocatorsMock = {
logsLocator: sharePluginMock.createLocator<LogsLocatorParams>(),
nodeLogsLocator: sharePluginMock.createLocator<NodeLogsLocatorParams>(),
traceLogsLocator: sharePluginMock.createLocator<TraceLogsLocatorParams>(),
};
const mockCorePlugins = {

View file

@ -13,10 +13,8 @@ import {
LogViewReference,
ResolvedLogView,
LogsLocatorParams,
NodeLogsLocatorParams,
} from '@kbn/logs-shared-plugin/common';
import { flowRight } from 'lodash';
import { findInventoryFields } from '@kbn/metrics-data-access-plugin/common';
import type { InfraClientCoreSetup } from '../../public/types';
import { MESSAGE_FIELD, TIMESTAMP_FIELD } from '../constants';
import type { TimeRange } from '../time';
@ -33,15 +31,6 @@ interface LocationToDiscoverParams {
logView?: LogViewReference;
}
export const createNodeLogsQuery = (params: NodeLogsLocatorParams) => {
const { nodeType, nodeId, filter } = params;
const nodeFilter = `${findInventoryFields(nodeType).id}: ${nodeId}`;
const query = filter ? `(${nodeFilter}) and (${filter})` : nodeFilter;
return query;
};
export const createSearchString = ({
time,
timeRange,

View file

@ -5,13 +5,13 @@
* 2.0.
*/
import type { LogsLocator } from './logs_locator';
import type { NodeLogsLocator } from './node_logs_locator';
import type { InfraLogsLocator } from './logs_locator';
import type { InfraNodeLogsLocator } from './node_logs_locator';
export * from './logs_locator';
export * from './node_logs_locator';
export interface InfraLocators {
logsLocator: LogsLocator;
nodeLogsLocator: NodeLogsLocator;
logsLocator?: InfraLogsLocator;
nodeLogsLocator?: InfraNodeLogsLocator;
}

View file

@ -6,8 +6,8 @@
*/
import { v4 as uuidv4 } from 'uuid';
import { LogsLocatorDefinition, LogsLocatorDependencies } from './logs_locator';
import { NodeLogsLocatorDefinition } from './node_logs_locator';
import { InfraLogsLocatorDefinition, InfraLogsLocatorDependencies } from './logs_locator';
import { InfraNodeLogsLocatorDefinition } from './node_logs_locator';
import { coreMock } from '@kbn/core/public/mocks';
import { findInventoryFields } from '@kbn/metrics-data-access-plugin/common';
import moment from 'moment';
@ -19,11 +19,11 @@ import {
} from '@kbn/logs-shared-plugin/common';
const setupLogsLocator = async () => {
const deps: LogsLocatorDependencies = {
const deps: InfraLogsLocatorDependencies = {
core: coreMock.createSetup(),
};
const logsLocator = new LogsLocatorDefinition(deps);
const nodeLogsLocator = new NodeLogsLocatorDefinition(deps);
const logsLocator = new InfraLogsLocatorDefinition(deps);
const nodeLogsLocator = new InfraNodeLogsLocatorDefinition(deps);
return {
logsLocator,
@ -33,8 +33,9 @@ const setupLogsLocator = async () => {
describe('Infra Locators', () => {
const APP_ID = 'logs';
const nodeType = 'host';
const FILTER_QUERY = 'trace.id:1234';
const nodeType = 'host';
const nodeField = findInventoryFields(nodeType).id;
const nodeId = uuidv4();
const time = 1550671089404;
const from = 1676815089000;
@ -124,7 +125,7 @@ describe('Infra Locators', () => {
it('should create a link to Node Logs with no state', async () => {
const params: NodeLogsLocatorParams = {
nodeId,
nodeType,
nodeField,
time,
};
const { nodeLogsLocator } = await setupLogsLocator();
@ -139,7 +140,7 @@ describe('Infra Locators', () => {
it('should allow specifying specific logPosition', async () => {
const params: NodeLogsLocatorParams = {
nodeId,
nodeType,
nodeField,
time,
};
const { nodeLogsLocator } = await setupLogsLocator();
@ -152,7 +153,7 @@ describe('Infra Locators', () => {
it('should allow specifying specific filter', async () => {
const params: NodeLogsLocatorParams = {
nodeId,
nodeType,
nodeField,
time,
filter: FILTER_QUERY,
};
@ -166,7 +167,7 @@ describe('Infra Locators', () => {
it('should allow specifying specific view id', async () => {
const params: NodeLogsLocatorParams = {
nodeId,
nodeType,
nodeField,
time,
logView: { ...DEFAULT_LOG_VIEW, logViewId: 'test' },
};
@ -180,7 +181,7 @@ describe('Infra Locators', () => {
it('should allow specifying specific time range', async () => {
const params: NodeLogsLocatorParams = {
nodeId,
nodeType,
nodeField,
time,
from,
to,
@ -196,7 +197,7 @@ describe('Infra Locators', () => {
it('should return correct structured url', async () => {
const params: NodeLogsLocatorParams = {
nodeId,
nodeType,
nodeField,
time,
logView: DEFAULT_LOG_VIEW,
filter: FILTER_QUERY,
@ -237,7 +238,7 @@ const constructLogPosition = (time: number = 1550671089404) => {
};
const constructLogFilter = ({
nodeType,
nodeField,
nodeId,
filter,
timeRange,
@ -246,7 +247,7 @@ const constructLogFilter = ({
let finalFilter = filter || '';
if (nodeId) {
const nodeFilter = `${findInventoryFields(nodeType!).id}: ${nodeId}`;
const nodeFilter = `${nodeField}: ${nodeId}`;
finalFilter = filter ? `(${nodeFilter}) and (${filter})` : nodeFilter;
}

View file

@ -6,19 +6,19 @@
*/
import type { LocatorDefinition, LocatorPublic } from '@kbn/share-plugin/public';
import { LOGS_LOCATOR_ID, LogsLocatorParams } from '@kbn/logs-shared-plugin/common';
import { INFRA_LOGS_LOCATOR_ID, LogsLocatorParams } from '@kbn/logs-shared-plugin/common';
import type { InfraClientCoreSetup } from '../../public/types';
export type LogsLocator = LocatorPublic<LogsLocatorParams>;
export type InfraLogsLocator = LocatorPublic<LogsLocatorParams>;
export interface LogsLocatorDependencies {
export interface InfraLogsLocatorDependencies {
core: InfraClientCoreSetup;
}
export class LogsLocatorDefinition implements LocatorDefinition<LogsLocatorParams> {
public readonly id = LOGS_LOCATOR_ID;
export class InfraLogsLocatorDefinition implements LocatorDefinition<LogsLocatorParams> {
public readonly id = INFRA_LOGS_LOCATOR_ID;
constructor(protected readonly deps: LogsLocatorDependencies) {}
constructor(protected readonly deps: InfraLogsLocatorDependencies) {}
public readonly getLocation = async (params: LogsLocatorParams) => {
const { createSearchString } = await import('./helpers');

View file

@ -6,20 +6,24 @@
*/
import type { LocatorDefinition, LocatorPublic } from '@kbn/share-plugin/public';
import { NODE_LOGS_LOCATOR_ID, NodeLogsLocatorParams } from '@kbn/logs-shared-plugin/common';
import type { LogsLocatorDependencies } from './logs_locator';
import {
INFRA_NODE_LOGS_LOCATOR_ID,
NodeLogsLocatorParams,
createNodeLogsQuery,
} from '@kbn/logs-shared-plugin/common';
import type { InfraLogsLocatorDependencies } from './logs_locator';
export type NodeLogsLocator = LocatorPublic<NodeLogsLocatorParams>;
export type InfraNodeLogsLocator = LocatorPublic<NodeLogsLocatorParams>;
export type NodeLogsLocatorDependencies = LogsLocatorDependencies;
export type InfraNodeLogsLocatorDependencies = InfraLogsLocatorDependencies;
export class NodeLogsLocatorDefinition implements LocatorDefinition<NodeLogsLocatorParams> {
public readonly id = NODE_LOGS_LOCATOR_ID;
export class InfraNodeLogsLocatorDefinition implements LocatorDefinition<NodeLogsLocatorParams> {
public readonly id = INFRA_NODE_LOGS_LOCATOR_ID;
constructor(protected readonly deps: NodeLogsLocatorDependencies) {}
constructor(protected readonly deps: InfraNodeLogsLocatorDependencies) {}
public readonly getLocation = async (params: NodeLogsLocatorParams) => {
const { createNodeLogsQuery, createSearchString } = await import('./helpers');
const { createSearchString } = await import('./helpers');
const query = createNodeLogsQuery(params);

View file

@ -6,9 +6,9 @@
*/
import { i18n } from '@kbn/i18n';
import { UrlService } from '@kbn/share-plugin/common/url_service';
import { getLogsLocatorsFromUrlService } from '@kbn/logs-shared-plugin/common';
import { ObservabilityRuleTypeModel } from '@kbn/observability-plugin/public';
import type { LocatorPublic } from '@kbn/share-plugin/public';
import type { LogsLocatorParams } from '@kbn/logs-shared-plugin/common';
import {
LOG_DOCUMENT_COUNT_RULE_TYPE_ID,
PartialRuleParams,
@ -44,7 +44,7 @@ const logThresholdDefaultRecoveryMessage = i18n.translate(
export function createLogThresholdRuleType(
core: InfraClientCoreSetup,
logsLocator: LocatorPublic<LogsLocatorParams>
urlService: UrlService
): ObservabilityRuleTypeModel<PartialRuleParams> {
const ruleParamsExpression = createLazyComponentWithKibanaContext(
core,
@ -56,6 +56,8 @@ export function createLogThresholdRuleType(
() => import('./components/alert_details_app_section')
);
const { logsLocator } = getLogsLocatorsFromUrlService(urlService);
return {
id: LOG_DOCUMENT_COUNT_RULE_TYPE_ID,
description: i18n.translate('xpack.infra.logs.alertFlyout.alertDescription', {

View file

@ -12,7 +12,11 @@ import { i18n } from '@kbn/i18n';
import { EuiFieldSearch, EuiFlexGroup, EuiFlexItem, EuiButtonEmpty } from '@elastic/eui';
import { RedirectAppLinks } from '@kbn/shared-ux-link-redirect-app';
import { LogStream } from '@kbn/logs-shared-plugin/public';
import { DEFAULT_LOG_VIEW, LogViewReference } from '@kbn/logs-shared-plugin/common';
import {
DEFAULT_LOG_VIEW,
getLogsLocatorsFromUrlService,
LogViewReference,
} from '@kbn/logs-shared-plugin/common';
import { findInventoryFields } from '@kbn/metrics-data-access-plugin/common';
import { useKibanaContextForPlugin } from '../../../../hooks/use_kibana';
import { InfraLoadingPanel } from '../../../loading';
@ -34,7 +38,7 @@ export const Logs = () => {
const { loading: logViewLoading, reference: logViewReference } = logs ?? {};
const { services } = useKibanaContextForPlugin();
const { locators } = services;
const { nodeLogsLocator } = getLogsLocatorsFromUrlService(services.share.url);
const [textQuery, setTextQuery] = useState(urlState?.logsSearch ?? '');
const [textQueryDebounced, setTextQueryDebounced] = useState(urlState?.logsSearch ?? '');
@ -77,21 +81,14 @@ export const Logs = () => {
);
const logsUrl = useMemo(() => {
return locators.nodeLogsLocator.getRedirectUrl({
nodeType: asset.type,
return nodeLogsLocator.getRedirectUrl({
nodeField: findInventoryFields(asset.type).id,
nodeId: asset.name,
time: state.startTimestamp,
filter: textQueryDebounced,
logView,
});
}, [
locators.nodeLogsLocator,
asset.name,
asset.type,
state.startTimestamp,
textQueryDebounced,
logView,
]);
}, [nodeLogsLocator, asset.name, asset.type, state.startTimestamp, textQueryDebounced, logView]);
return (
<EuiFlexGroup direction="column" data-test-subj="infraAssetDetailsLogsTabContent" ref={ref}>

View file

@ -7,7 +7,7 @@
import { useEffect } from 'react';
import { useLocation, useParams } from 'react-router-dom';
import { DEFAULT_LOG_VIEW } from '@kbn/logs-shared-plugin/common';
import { DEFAULT_LOG_VIEW, getLogsLocatorsFromUrlService } from '@kbn/logs-shared-plugin/common';
import { getFilterFromLocation, getTimeFromLocation } from './query_params';
import { useKibanaContextForPlugin } from '../../hooks/use_kibana';
@ -16,14 +16,15 @@ export const RedirectToLogs = () => {
const location = useLocation();
const {
services: { locators },
services: { share },
} = useKibanaContextForPlugin();
const { logsLocator } = getLogsLocatorsFromUrlService(share.url);
const filter = getFilterFromLocation(location);
const time = getTimeFromLocation(location);
useEffect(() => {
locators.logsLocator.navigate(
logsLocator.navigate(
{
time,
filter,
@ -31,7 +32,7 @@ export const RedirectToLogs = () => {
},
{ replace: true }
);
}, [filter, locators.logsLocator, logViewId, time]);
}, [filter, logsLocator, logViewId, time]);
return null;
};

View file

@ -7,8 +7,8 @@
import { useEffect } from 'react';
import { RouteComponentProps } from 'react-router-dom';
import { DEFAULT_LOG_VIEW } from '@kbn/logs-shared-plugin/common';
import { InventoryItemType } from '@kbn/metrics-data-access-plugin/common';
import { DEFAULT_LOG_VIEW, getLogsLocatorsFromUrlService } from '@kbn/logs-shared-plugin/common';
import { findInventoryFields, InventoryItemType } from '@kbn/metrics-data-access-plugin/common';
import { useKibanaContextForPlugin } from '../../hooks/use_kibana';
import { getFilterFromLocation, getTimeFromLocation } from './query_params';
@ -26,24 +26,25 @@ export const RedirectToNodeLogs = ({
location,
}: RedirectToNodeLogsType) => {
const {
services: { locators },
services: { share },
} = useKibanaContextForPlugin();
const { nodeLogsLocator } = getLogsLocatorsFromUrlService(share.url);
const filter = getFilterFromLocation(location);
const time = getTimeFromLocation(location);
useEffect(() => {
locators.nodeLogsLocator.navigate(
nodeLogsLocator.navigate(
{
nodeField: findInventoryFields(nodeType).id,
nodeId,
nodeType,
time,
filter,
logView: { type: 'log-view-reference', logViewId },
},
{ replace: true }
);
}, [filter, locators.nodeLogsLocator, logViewId, nodeId, nodeType, time]);
}, [filter, nodeLogsLocator, logViewId, nodeId, nodeType, time]);
return null;
};

View file

@ -8,7 +8,7 @@ import React from 'react';
import { RedirectAppLinks } from '@kbn/shared-ux-link-redirect-app';
import { EuiButtonEmpty } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n-react';
import { LogViewReference } from '@kbn/logs-shared-plugin/common';
import { getLogsLocatorsFromUrlService, LogViewReference } from '@kbn/logs-shared-plugin/common';
import { useKibanaContextForPlugin } from '../../../../../../hooks/use_kibana';
interface LogsLinkToStreamProps {
@ -20,12 +20,13 @@ interface LogsLinkToStreamProps {
export const LogsLinkToStream = ({ startTime, endTime, query, logView }: LogsLinkToStreamProps) => {
const { services } = useKibanaContextForPlugin();
const { locators } = services;
const { share } = services;
const { logsLocator } = getLogsLocatorsFromUrlService(share.url);
return (
<RedirectAppLinks coreStart={services}>
<EuiButtonEmpty
href={locators.logsLocator?.getRedirectUrl({
href={logsLocator.getRedirectUrl({
time: endTime,
timeRange: {
startTime,

View file

@ -23,6 +23,7 @@ import {
} from '@kbn/observability-shared-plugin/public';
import { findInventoryModel, findInventoryFields } from '@kbn/metrics-data-access-plugin/common';
import { InventoryItemType } from '@kbn/metrics-data-access-plugin/common';
import { getLogsLocatorsFromUrlService } from '@kbn/logs-shared-plugin/common';
import { useKibanaContextForPlugin } from '../../../../../hooks/use_kibana';
import { AlertFlyout } from '../../../../../alerting/inventory/components/alert_flyout';
import { InfraWaffleMapNode, InfraWaffleMapOptions } from '../../../../../lib/lib';
@ -43,7 +44,8 @@ export const NodeContextMenu: React.FC<Props & { theme?: EuiTheme }> = withTheme
const inventoryModel = findInventoryModel(nodeType);
const nodeDetailFrom = currentTime - inventoryModel.metrics.defaultTimeRangeInSeconds * 1000;
const { services } = useKibanaContextForPlugin();
const { application, share, locators } = services;
const { application, share } = services;
const { nodeLogsLocator } = getLogsLocatorsFromUrlService(share.url);
const uiCapabilities = application?.capabilities;
// Due to the changing nature of the fields between APM and this UI,
// We need to have some exceptions until 7.0 & ECS is finalized. Reference
@ -109,8 +111,8 @@ export const NodeContextMenu: React.FC<Props & { theme?: EuiTheme }> = withTheme
defaultMessage: '{inventoryName} logs',
values: { inventoryName: inventoryModel.singularDisplayName },
}),
href: locators.nodeLogsLocator.getRedirectUrl({
nodeType,
href: nodeLogsLocator.getRedirectUrl({
nodeField: findInventoryFields(nodeType).id,
nodeId: node.id,
time: currentTime,
}),

View file

@ -27,8 +27,8 @@ import { LOG_STREAM_EMBEDDABLE } from './components/log_stream/log_stream_embedd
import { LogStreamEmbeddableFactoryDefinition } from './components/log_stream/log_stream_embeddable_factory';
import {
type InfraLocators,
LogsLocatorDefinition,
NodeLogsLocatorDefinition,
InfraLogsLocatorDefinition,
InfraNodeLogsLocatorDefinition,
} from '../common/locators';
import { createMetricsFetchData, createMetricsHasData } from './metrics_overview_fetchers';
import { registerFeatures } from './register_feature';
@ -179,13 +179,15 @@ export class Plugin implements InfraClientPluginClass {
);
// Register Locators
const logsLocator = pluginsSetup.share.url.locators.create(new LogsLocatorDefinition({ core }));
const nodeLogsLocator = pluginsSetup.share.url.locators.create(
new NodeLogsLocatorDefinition({ core })
);
const logsLocator = this.config.featureFlags.logsUIEnabled
? pluginsSetup.share.url.locators.create(new InfraLogsLocatorDefinition({ core }))
: undefined;
const nodeLogsLocator = this.config.featureFlags.logsUIEnabled
? pluginsSetup.share.url.locators.create(new InfraNodeLogsLocatorDefinition({ core }))
: undefined;
pluginsSetup.observability.observabilityRuleTypeRegistry.register(
createLogThresholdRuleType(core, logsLocator)
createLogThresholdRuleType(core, pluginsSetup.share.url)
);
if (this.config.featureFlags.logsUIEnabled) {

View file

@ -60,5 +60,13 @@ export {
} from './http_api';
// Locators
export { LOGS_LOCATOR_ID, NODE_LOGS_LOCATOR_ID } from './locators';
export type { LogsLocatorParams, NodeLogsLocatorParams } from './locators';
export {
LOGS_LOCATOR_ID,
TRACE_LOGS_LOCATOR_ID,
NODE_LOGS_LOCATOR_ID,
INFRA_LOGS_LOCATOR_ID,
INFRA_NODE_LOGS_LOCATOR_ID,
getLogsLocatorsFromUrlService,
} from './locators';
export type { LogsLocatorParams, NodeLogsLocatorParams, TraceLogsLocatorParams } from './locators';
export { createNodeLogsQuery } from './locators/helpers';

View file

@ -0,0 +1,25 @@
/*
* 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 { UrlService } from '@kbn/share-plugin/common/url_service';
import { LogsLocatorParams, NodeLogsLocatorParams, TraceLogsLocatorParams } from './types';
import { LOGS_LOCATOR_ID } from './logs_locator';
import { NODE_LOGS_LOCATOR_ID } from './node_logs_locator';
import { TRACE_LOGS_LOCATOR_ID } from './trace_logs_locator';
export const getLogsLocatorsFromUrlService = (urlService: UrlService) => {
const logsLocator = urlService.locators.get<LogsLocatorParams>(LOGS_LOCATOR_ID)!;
const nodeLogsLocator = urlService.locators.get<NodeLogsLocatorParams>(NODE_LOGS_LOCATOR_ID)!;
const traceLogsLocator = urlService.locators.get<TraceLogsLocatorParams>(TRACE_LOGS_LOCATOR_ID)!;
return {
logsLocator,
traceLogsLocator,
nodeLogsLocator,
};
};

View file

@ -0,0 +1,43 @@
/*
* 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 moment, { DurationInputObject } from 'moment';
import { LogsLocatorParams, NodeLogsLocatorParams, TraceLogsLocatorParams } from './types';
export const getLogsQuery = (params: LogsLocatorParams) => {
const { filter } = params;
return filter ? { language: 'kuery', query: filter } : undefined;
};
export const createNodeLogsQuery = (params: NodeLogsLocatorParams) => {
const { nodeField, nodeId, filter } = params;
const nodeFilter = `${nodeField}: ${nodeId}`;
return filter ? `(${nodeFilter}) and (${filter})` : nodeFilter;
};
export const getNodeQuery = (params: NodeLogsLocatorParams) => {
return { language: 'kuery', query: createNodeLogsQuery(params) };
};
export const getTraceQuery = (params: TraceLogsLocatorParams) => {
const { traceId, filter } = params;
const traceFilter = `trace.id:"${traceId}" OR (not trace.id:* AND "${traceId}")`;
const query = filter ? `(${traceFilter}) and (${filter})` : traceFilter;
return { language: 'kuery', query };
};
const defaultTimeRangeFromPositionOffset: DurationInputObject = { hours: 1 };
export const getTimeRangeStartFromTime = (time: number): string =>
moment(time).subtract(defaultTimeRangeFromPositionOffset).toISOString();
export const getTimeRangeEndFromTime = (time: number): string =>
moment(time).add(defaultTimeRangeFromPositionOffset).toISOString();

View file

@ -6,4 +6,14 @@
*/
export * from './logs_locator';
export * from './trace_logs_locator';
export * from './node_logs_locator';
export * from './infra';
export * from './get_logs_locators';
export type {
LogsSharedLocators,
LogsLocatorParams,
NodeLogsLocatorParams,
TraceLogsLocatorParams,
} from './types';

View file

@ -0,0 +1,10 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
export const INFRA_LOGS_LOCATOR_ID = 'INFRA_LOGS_LOCATOR';
export const INFRA_NODE_LOGS_LOCATOR_ID = 'INFRA_NODE_LOGS_LOCATOR';

View file

@ -5,19 +5,40 @@
* 2.0.
*/
import { SerializableRecord } from '@kbn/utility-types';
import type { TimeRange } from './time_range';
import type { LogViewReference } from '../log_views/types';
import { ALL_DATASETS_LOCATOR_ID, AllDatasetsLocatorParams } from '@kbn/deeplinks-observability';
import { LocatorDefinition } from '@kbn/share-plugin/common';
import { LocatorClient } from '@kbn/share-plugin/common/url_service';
import { INFRA_LOGS_LOCATOR_ID } from './infra';
import { LogsLocatorParams } from './types';
import { getLogsQuery, getTimeRangeEndFromTime, getTimeRangeStartFromTime } from './helpers';
export const LOGS_LOCATOR_ID = 'LOGS_LOCATOR';
export interface LogsLocatorParams extends SerializableRecord {
/** Defines log position */
time?: number;
/**
* Optionally set the time range in the time picker.
*/
timeRange?: TimeRange;
filter?: string;
logView?: LogViewReference;
export class LogsLocatorDefinition implements LocatorDefinition<LogsLocatorParams> {
public readonly id = LOGS_LOCATOR_ID;
constructor(private readonly locators: LocatorClient) {}
public readonly getLocation = async (params: LogsLocatorParams) => {
const infraLogsLocator = this.locators.get<LogsLocatorParams>(INFRA_LOGS_LOCATOR_ID);
if (infraLogsLocator) {
return infraLogsLocator.getLocation(params);
}
const allDatasetsLocator =
this.locators.get<AllDatasetsLocatorParams>(ALL_DATASETS_LOCATOR_ID)!;
const { time } = params;
return allDatasetsLocator.getLocation({
query: getLogsQuery(params),
...(time
? {
timeRange: {
from: getTimeRangeStartFromTime(time),
to: getTimeRangeEndFromTime(time),
},
}
: {}),
});
};
}

View file

@ -5,12 +5,45 @@
* 2.0.
*/
import type { InventoryItemType } from './types';
import type { LogsLocatorParams } from './logs_locator';
import {
AllDatasetsLocatorParams,
ALL_DATASETS_LOCATOR_ID,
} from '@kbn/deeplinks-observability/locators';
import { LocatorClient, LocatorDefinition } from '@kbn/share-plugin/common/url_service';
import { NodeLogsLocatorParams } from './types';
import { INFRA_NODE_LOGS_LOCATOR_ID } from './infra';
import { getNodeQuery, getTimeRangeStartFromTime, getTimeRangeEndFromTime } from './helpers';
export const NODE_LOGS_LOCATOR_ID = 'NODE_LOGS_LOCATOR';
export interface NodeLogsLocatorParams extends LogsLocatorParams {
nodeId: string;
nodeType: InventoryItemType;
export class NodeLogsLocatorDefinition implements LocatorDefinition<NodeLogsLocatorParams> {
public readonly id = NODE_LOGS_LOCATOR_ID;
constructor(private readonly locators: LocatorClient) {}
public readonly getLocation = async (params: NodeLogsLocatorParams) => {
const infraNodeLogsLocator = this.locators.get<NodeLogsLocatorParams>(
INFRA_NODE_LOGS_LOCATOR_ID
);
if (infraNodeLogsLocator) {
return infraNodeLogsLocator.getLocation(params);
}
const allDatasetsLocator =
this.locators.get<AllDatasetsLocatorParams>(ALL_DATASETS_LOCATOR_ID)!;
const { time } = params;
return allDatasetsLocator.getLocation({
query: getNodeQuery(params),
...(time
? {
timeRange: {
from: getTimeRangeStartFromTime(time),
to: getTimeRangeEndFromTime(time),
},
}
: {}),
});
};
}

View file

@ -0,0 +1,47 @@
/*
* 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 { ALL_DATASETS_LOCATOR_ID, AllDatasetsLocatorParams } from '@kbn/deeplinks-observability';
import { LocatorDefinition } from '@kbn/share-plugin/common';
import { LocatorClient } from '@kbn/share-plugin/common/url_service';
import { INFRA_LOGS_LOCATOR_ID } from './infra';
import { LogsLocatorParams, TraceLogsLocatorParams } from './types';
import { getTraceQuery, getTimeRangeEndFromTime, getTimeRangeStartFromTime } from './helpers';
export const TRACE_LOGS_LOCATOR_ID = 'TRACE_LOGS_LOCATOR';
export class TraceLogsLocatorDefinition implements LocatorDefinition<TraceLogsLocatorParams> {
public readonly id = TRACE_LOGS_LOCATOR_ID;
constructor(private readonly locators: LocatorClient) {}
public readonly getLocation = async (params: TraceLogsLocatorParams) => {
const infraLogsLocator = this.locators.get<LogsLocatorParams>(INFRA_LOGS_LOCATOR_ID);
if (infraLogsLocator) {
return infraLogsLocator.getLocation({
...params,
filter: getTraceQuery(params).query,
});
}
const { time } = params;
const allDatasetsLocator =
this.locators.get<AllDatasetsLocatorParams>(ALL_DATASETS_LOCATOR_ID)!;
return allDatasetsLocator.getLocation({
query: getTraceQuery(params),
...(time
? {
timeRange: {
from: getTimeRangeStartFromTime(time),
to: getTimeRangeEndFromTime(time),
},
}
: {}),
});
};
}

View file

@ -5,16 +5,33 @@
* 2.0.
*/
import * as rt from 'io-ts';
import { SerializableRecord } from '@kbn/utility-types';
import { LocatorPublic } from '@kbn/share-plugin/common';
import { LogViewReference } from '../log_views/types';
import { TimeRange } from './time_range';
export const ItemTypeRT = rt.keyof({
host: null,
pod: null,
container: null,
awsEC2: null,
awsS3: null,
awsSQS: null,
awsRDS: null,
});
export interface LogsLocatorParams extends SerializableRecord {
/** Defines log position */
time?: number;
/**
* Optionally set the time range in the time picker.
*/
timeRange?: TimeRange;
filter?: string;
logView?: LogViewReference;
}
export type InventoryItemType = rt.TypeOf<typeof ItemTypeRT>;
export interface TraceLogsLocatorParams extends LogsLocatorParams {
traceId: string;
}
export interface NodeLogsLocatorParams extends LogsLocatorParams {
nodeField: string;
nodeId: string;
}
export interface LogsSharedLocators {
logsLocator: LocatorPublic<LogsLocatorParams>;
nodeLogsLocator: LocatorPublic<NodeLogsLocatorParams>;
traceLogsLocator: LocatorPublic<TraceLogsLocatorParams>;
}

View file

@ -13,7 +13,8 @@
"dataViews",
"usageCollection",
"observabilityShared",
"observabilityAIAssistant"
"observabilityAIAssistant",
"share"
],
"requiredBundles": ["kibanaUtils", "kibanaReact"],
"extraPublicDirs": ["common"]

View file

@ -6,9 +6,19 @@
*/
import { CoreStart } from '@kbn/core/public';
import {
LogsLocatorDefinition,
NodeLogsLocatorDefinition,
TraceLogsLocatorDefinition,
} from '../common/locators';
import { createLogAIAssistant } from './components/log_ai_assistant';
import { LogViewsService } from './services/log_views';
import { LogsSharedClientPluginClass, LogsSharedClientStartDeps } from './types';
import {
LogsSharedClientCoreSetup,
LogsSharedClientPluginClass,
LogsSharedClientSetupDeps,
LogsSharedClientStartDeps,
} from './types';
export class LogsSharedPlugin implements LogsSharedClientPluginClass {
private logViews: LogViewsService;
@ -17,10 +27,27 @@ export class LogsSharedPlugin implements LogsSharedClientPluginClass {
this.logViews = new LogViewsService();
}
public setup() {
public setup(_: LogsSharedClientCoreSetup, pluginsSetup: LogsSharedClientSetupDeps) {
const logViews = this.logViews.setup();
return { logViews };
const logsLocator = pluginsSetup.share.url.locators.create(
new LogsLocatorDefinition(pluginsSetup.share.url.locators)
);
const nodeLogsLocator = pluginsSetup.share.url.locators.create(
new NodeLogsLocatorDefinition(pluginsSetup.share.url.locators)
);
const traceLogsLocator = pluginsSetup.share.url.locators.create(
new TraceLogsLocatorDefinition(pluginsSetup.share.url.locators)
);
const locators = {
logsLocator,
nodeLogsLocator,
traceLogsLocator,
};
return { logViews, locators };
}
public start(core: CoreStart, plugins: LogsSharedClientStartDeps) {

View file

@ -5,18 +5,14 @@
* 2.0.
*/
/*
* 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 type { CoreSetup, CoreStart, Plugin as PluginClass } from '@kbn/core/public';
import type { DataPublicPluginStart } from '@kbn/data-plugin/public';
import type { DataViewsPublicPluginStart } from '@kbn/data-views-plugin/public';
import { ObservabilityAIAssistantPluginStart } from '@kbn/observability-ai-assistant-plugin/public';
import { SharePluginSetup } from '@kbn/share-plugin/public';
import { UiActionsStart } from '@kbn/ui-actions-plugin/public';
import { LogsSharedLocators } from '../common/locators';
import type { LogAIAssistantProps } from './components/log_ai_assistant/log_ai_assistant';
// import type { OsqueryPluginStart } from '../../osquery/public';
import { LogViewsServiceSetup, LogViewsServiceStart } from './services/log_views';
@ -24,6 +20,7 @@ import { LogViewsServiceSetup, LogViewsServiceStart } from './services/log_views
// Our own setup and start contract values
export interface LogsSharedClientSetupExports {
logViews: LogViewsServiceSetup;
locators: LogsSharedLocators;
}
export interface LogsSharedClientStartExports {
@ -31,8 +28,9 @@ export interface LogsSharedClientStartExports {
LogAIAssistant: (props: Omit<LogAIAssistantProps, 'observabilityAIAssistant'>) => JSX.Element;
}
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface LogsSharedClientSetupDeps {}
export interface LogsSharedClientSetupDeps {
share: SharePluginSetup;
}
export interface LogsSharedClientStartDeps {
data: DataPublicPluginStart;

View file

@ -26,6 +26,8 @@
"@kbn/datemath",
"@kbn/core-http-browser",
"@kbn/ui-actions-plugin",
"@kbn/observability-ai-assistant-plugin"
"@kbn/observability-ai-assistant-plugin",
"@kbn/deeplinks-observability",
"@kbn/share-plugin"
]
}