Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

[APM] Service Map data background task and API endpoint #50844

Closed
wants to merge 15 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/legacy/core_plugins/apm_oss/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ export default function apmOss(kibana) {
spanIndices: Joi.string().default('apm-*'),
metricsIndices: Joi.string().default('apm-*'),
onboardingIndices: Joi.string().default('apm-*'),
apmAgentConfigurationIndex: Joi.string().default('.apm-agent-configuration'),
}).default();
},

Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import * as fieldnames from './elasticsearch_fieldnames';

describe('Transaction', () => {
const transaction: AllowUnknownProperties<Transaction> = {
'@timestamp': new Date().toString(),
'@timestamp': new Date(1337).toISOString(),
'@metadata': 'whatever',
observer: 'whatever',
agent: {
Expand Down Expand Up @@ -61,7 +61,7 @@ describe('Transaction', () => {

describe('Span', () => {
const span: AllowUnknownProperties<Span> = {
'@timestamp': new Date().toString(),
'@timestamp': new Date(1337).toISOString(),
'@metadata': 'whatever',
observer: 'whatever',
agent: {
Expand Down Expand Up @@ -125,7 +125,7 @@ describe('Error', () => {
id: 'error id',
grouping_key: 'grouping key'
},
'@timestamp': new Date().toString(),
'@timestamp': new Date(1337).toISOString(),
host: {
hostname: 'my hostname'
},
Expand Down
8 changes: 8 additions & 0 deletions x-pack/legacy/plugins/apm/common/elasticsearch_fieldnames.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export const TRANSACTION_PAGE_URL = 'transaction.page.url';

export const TRACE_ID = 'trace.id';

export const TIMESTAMP = '@timestamp';
export const SPAN_DURATION = 'span.duration.us';
export const SPAN_TYPE = 'span.type';
export const SPAN_SUBTYPE = 'span.subtype';
Expand All @@ -37,6 +38,13 @@ export const SPAN_ACTION = 'span.action';
export const SPAN_NAME = 'span.name';
export const SPAN_ID = 'span.id';

export const DESTINATION_ADDRESS = 'destination.address';
export const CONNECTION_TYPE = 'connection.type';
export const CONNECTION_SUBTYPE = 'connection.subtype';
export const CALLEE_NAME = 'callee.name';
export const CALLEE_ENVIRONMENT = 'callee.environment';
export const CONNECTION_UPSTREAM_LIST = 'connection.upstream.list';

// Parent ID for a transaction or span
export const PARENT_ID = 'parent.id';

Expand Down
8 changes: 8 additions & 0 deletions x-pack/legacy/plugins/apm/common/service_map_constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

export const SERVICE_MAP_TASK_TYPE = 'apmServiceMap';
export const SERVICE_MAP_TASK_ID = 'apm-servicemap-processor';
Copy link
Member

Choose a reason for hiding this comment

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

Should we have a convention around camelCase vs kebab-case for constants?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We already use snake case for constants (eg SERVICE_MAP_TASK_ID) as for the value, it's depends on the context. There's no existing convention for task types and task ids. Some plugins mix snake and kebab case for id: plugin_task-id. from what i see, it looks like other plugins tend to use snake case for the task type. We could change the type to apm_service_map to conform if we want to. The task type is represented in the API by an object key in the task definition, so i don't recommend kebab case.

8 changes: 7 additions & 1 deletion x-pack/legacy/plugins/apm/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,13 @@ import { makeApmUsageCollector } from './server/lib/apm_telemetry';

export const apm: LegacyPluginInitializer = kibana => {
return new kibana.Plugin({
require: ['kibana', 'elasticsearch', 'xpack_main', 'apm_oss'],
require: [
'kibana',
'elasticsearch',
'xpack_main',
'apm_oss',
'task_manager'
Copy link
Member

Choose a reason for hiding this comment

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

This is another reason for not having serviceMapEnabled anymore: APM requires task_manager regardless.

],
id: 'apm',
configPrefix: 'xpack.apm',
publicDir: resolve(__dirname, 'public'),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ export function Cytoscape({
// Trigger a custom "data" event when data changes
useEffect(() => {
if (cy) {
cy.remove('*');
cy.add(elements);
cy.trigger('data');
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@
*/

import theme from '@elastic/eui/dist/eui_theme_light.json';
import React from 'react';
import React, { useMemo } from 'react';
import { useFetcher } from '../../../hooks/useFetcher';
import { useLicense } from '../../../hooks/useLicense';
import { useUrlParams } from '../../../hooks/useUrlParams';
import { Controls } from './Controls';
import { Cytoscape } from './Cytoscape';
import { PlatinumLicensePrompt } from './PlatinumLicensePrompt';
import { useApmPluginContext } from '../../../hooks/useApmPluginContext';
import { callApi } from '../../../services/rest/callApi';

interface ServiceMapProps {
serviceName?: string;
Expand Down Expand Up @@ -39,35 +41,77 @@ ${theme.euiColorLightShade}`,

export function ServiceMap({ serviceName }: ServiceMapProps) {
const {
urlParams: { start, end }
urlParams: { start, end, environment },
uiFilters
} = useUrlParams();

const uiFiltersOmitEnv = useMemo(
() => ({
...uiFilters,
environment: undefined
}),
[uiFilters]
);

const { http } = useApmPluginContext().core;
const { data: serviceMapStartResponse } = useFetcher(async () => {
const response = await callApi<{
taskStatus: 'initialized' | 'active';
}>(http, {
method: 'GET',
pathname: `/api/apm/service-map-start-task`
});
return response;
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [http]);

const { data } = useFetcher(
callApmApi => {
if (start && end) {
if (start && end && serviceMapStartResponse) {
return callApmApi({
pathname: '/api/apm/service-map',
params: { query: { start, end } }
params: {
query: {
start,
end,
environment,
Copy link
Member

Choose a reason for hiding this comment

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

I think my previous comment was lost in a rebase:
Is it not possible to extract environment from uiFilters on the backend?

serviceName,
uiFilters: JSON.stringify(uiFiltersOmitEnv)
}
}
});
}
},
[start, end]
[
start,
end,
uiFiltersOmitEnv,
environment,
serviceName,
serviceMapStartResponse
]
);

const elements = Array.isArray(data) ? data : [];
const license = useLicense();
const isValidPlatinumLicense =
license?.isActive && license?.type === 'platinum';
true ||
(license?.isActive &&
(license?.type === 'platinum' || license?.type === 'trial'));

return isValidPlatinumLicense ? (
<Cytoscape
elements={elements}
serviceName={serviceName}
style={cytoscapeDivStyle}
>
<Controls />
</Cytoscape>
) : (
<PlatinumLicensePrompt />
return (
<>
{isValidPlatinumLicense ? (
<Cytoscape
elements={elements}
serviceName={serviceName}
style={cytoscapeDivStyle}
>
<Controls />
</Cytoscape>
) : (
<PlatinumLicensePrompt />
)}
</>
);
}
4 changes: 3 additions & 1 deletion x-pack/legacy/plugins/apm/public/utils/testHelpers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ interface MockSetup {
'apm_oss.transactionIndices': string;
'apm_oss.metricsIndices': string;
apmAgentConfigurationIndex: string;
apmServiceConnectionsIndex: string;
};
}

Expand Down Expand Up @@ -175,7 +176,8 @@ export async function inspectSearchParams(
'apm_oss.spanIndices': 'myIndex',
'apm_oss.transactionIndices': 'myIndex',
'apm_oss.metricsIndices': 'myIndex',
apmAgentConfigurationIndex: 'myIndex'
apmAgentConfigurationIndex: 'myIndex',
apmServiceConnectionsIndex: 'myIndex'
},
dynamicIndexPattern: null as any
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ describe('timeseriesFetcher', () => {
'apm_oss.spanIndices': 'apm-*',
'apm_oss.transactionIndices': 'apm-*',
'apm_oss.metricsIndices': 'apm-*',
apmAgentConfigurationIndex: '.apm-agent-configuration'
apmAgentConfigurationIndex: '.apm-agent-configuration',
apmServiceConnectionsIndex: 'apm-service-connections'
},
dynamicIndexPattern: null as any
}
Expand Down
Loading