mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
[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:
parent
30ce43bea3
commit
2f2083b718
33 changed files with 441 additions and 319 deletions
|
@ -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 (
|
||||
|
|
|
@ -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[] = [
|
||||
{
|
||||
|
|
|
@ -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();
|
|
@ -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();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -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[] = [
|
||||
{
|
||||
|
|
|
@ -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 () => {
|
||||
|
|
|
@ -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,
|
||||
});
|
||||
|
||||
|
|
|
@ -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 = {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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');
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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', {
|
||||
|
|
|
@ -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}>
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
}),
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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';
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
};
|
43
x-pack/plugins/logs_shared/common/locators/helpers.ts
Normal file
43
x-pack/plugins/logs_shared/common/locators/helpers.ts
Normal 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();
|
|
@ -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';
|
||||
|
|
10
x-pack/plugins/logs_shared/common/locators/infra.ts
Normal file
10
x-pack/plugins/logs_shared/common/locators/infra.ts
Normal 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';
|
|
@ -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),
|
||||
},
|
||||
}
|
||||
: {}),
|
||||
});
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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),
|
||||
},
|
||||
}
|
||||
: {}),
|
||||
});
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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),
|
||||
},
|
||||
}
|
||||
: {}),
|
||||
});
|
||||
};
|
||||
}
|
|
@ -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>;
|
||||
}
|
||||
|
|
|
@ -13,7 +13,8 @@
|
|||
"dataViews",
|
||||
"usageCollection",
|
||||
"observabilityShared",
|
||||
"observabilityAIAssistant"
|
||||
"observabilityAIAssistant",
|
||||
"share"
|
||||
],
|
||||
"requiredBundles": ["kibanaUtils", "kibanaReact"],
|
||||
"extraPublicDirs": ["common"]
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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"
|
||||
]
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue