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] Profiling #91818

Merged
merged 18 commits into from
Feb 22, 2021
Merged
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

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

14 changes: 14 additions & 0 deletions x-pack/plugins/apm/common/elasticsearch_fieldnames.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,3 +132,17 @@ export const LCP_FIELD = 'transaction.marks.agent.largestContentfulPaint';
export const TBT_FIELD = 'transaction.experience.tbt';
export const FID_FIELD = 'transaction.experience.fid';
export const CLS_FIELD = 'transaction.experience.cls';

export const PROFILE_ID = 'profile.id';
export const PROFILE_DURATION = 'profile.duration';
export const PROFILE_TOP_ID = 'profile.top.id';
export const PROFILE_STACK = 'profile.stack';

export const PROFILE_SAMPLES_COUNT = 'profile.samples.count';
export const PROFILE_CPU_NS = 'profile.cpu.ns';
export const PROFILE_WALL_US = 'profile.wall.us';

export const PROFILE_ALLOC_OBJECTS = 'profile.alloc_objects.count';
export const PROFILE_ALLOC_SPACE = 'profile.alloc_space.bytes';
export const PROFILE_INUSE_OBJECTS = 'profile.inuse_objects.count';
export const PROFILE_INUSE_SPACE = 'profile.inuse_space.bytes';
1 change: 1 addition & 0 deletions x-pack/plugins/apm/common/processor_event.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export enum ProcessorEvent {
error = 'error',
metric = 'metric',
span = 'span',
profile = 'profile',
}
/**
* Processor events that are searchable in the UI via the query bar.
Expand Down
112 changes: 112 additions & 0 deletions x-pack/plugins/apm/common/profiling.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
/*
* 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 { i18n } from '@kbn/i18n';
import {
PROFILE_ALLOC_OBJECTS,
PROFILE_ALLOC_SPACE,
PROFILE_CPU_NS,
PROFILE_INUSE_OBJECTS,
PROFILE_INUSE_SPACE,
PROFILE_SAMPLES_COUNT,
PROFILE_WALL_US,
} from './elasticsearch_fieldnames';

export enum ProfilingValueType {
wallTime = 'wall_time',
cpuTime = 'cpu_time',
samples = 'samples',
allocObjects = 'alloc_objects',
allocSpace = 'alloc_space',
inuseObjects = 'inuse_objects',
inuseSpace = 'inuse_space',
}

export enum ProfilingValueTypeUnit {
ns = 'ns',
us = 'us',
count = 'count',
bytes = 'bytes',
}

export interface ProfileNode {
id: string;
label: string;
fqn: string;
value: number;
children: string[];
}

const config = {
[ProfilingValueType.wallTime]: {
unit: ProfilingValueTypeUnit.us,
label: i18n.translate(
'xpack.apm.serviceProfiling.valueTypeLabel.wallTime',
{
defaultMessage: 'Wall',
}
),
field: PROFILE_WALL_US,
},
[ProfilingValueType.cpuTime]: {
unit: ProfilingValueTypeUnit.ns,
label: i18n.translate('xpack.apm.serviceProfiling.valueTypeLabel.cpuTime', {
defaultMessage: 'On-CPU',
}),
field: PROFILE_CPU_NS,
},
[ProfilingValueType.samples]: {
unit: ProfilingValueTypeUnit.count,
label: i18n.translate('xpack.apm.serviceProfiling.valueTypeLabel.samples', {
defaultMessage: 'Samples',
}),
field: PROFILE_SAMPLES_COUNT,
},
[ProfilingValueType.allocObjects]: {
unit: ProfilingValueTypeUnit.count,
label: i18n.translate(
'xpack.apm.serviceProfiling.valueTypeLabel.allocObjects',
{
defaultMessage: 'Alloc. objects',
}
),
field: PROFILE_ALLOC_OBJECTS,
},
[ProfilingValueType.allocSpace]: {
unit: ProfilingValueTypeUnit.bytes,
label: i18n.translate(
'xpack.apm.serviceProfiling.valueTypeLabel.allocSpace',
{
defaultMessage: 'Alloc. space',
}
),
field: PROFILE_ALLOC_SPACE,
},
[ProfilingValueType.inuseObjects]: {
unit: ProfilingValueTypeUnit.count,
label: i18n.translate(
'xpack.apm.serviceProfiling.valueTypeLabel.inuseObjects',
{
defaultMessage: 'In-use objects',
}
),
field: PROFILE_INUSE_OBJECTS,
},
[ProfilingValueType.inuseSpace]: {
unit: ProfilingValueTypeUnit.bytes,
label: i18n.translate(
'xpack.apm.serviceProfiling.valueTypeLabel.inuseSpace',
{
defaultMessage: 'In-use space',
}
),
field: PROFILE_INUSE_SPACE,
},
};

export const getValueTypeConfig = (type: ProfilingValueType) => {
return config[type];
};

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 @@ -114,6 +114,12 @@ function ServiceDetailsTransactions(
return <ServiceDetails {...props} tab="transactions" />;
}

function ServiceDetailsProfiling(
props: RouteComponentProps<{ serviceName: string }>
) {
return <ServiceDetails {...props} tab="profiling" />;
}

function SettingsAgentConfiguration(props: RouteComponentProps<{}>) {
return (
<Settings {...props}>
Expand Down Expand Up @@ -307,6 +313,14 @@ export const routes: APMRouteDefinition[] = [
return query.transactionName as string;
},
},
{
exact: true,
path: '/services/:serviceName/profiling',
component: withApmServiceContext(ServiceDetailsProfiling),
breadcrumb: i18n.translate('xpack.apm.breadcrumb.serviceProfilingTitle', {
defaultMessage: 'Profiling',
}),
},
{
exact: true,
path: '/services/:serviceName/service-map',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
import { EuiTab } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import React, { ReactNode } from 'react';
import { EuiBetaBadge } from '@elastic/eui';
import { EuiFlexItem } from '@elastic/eui';
import { EuiFlexGroup } from '@elastic/eui';
import { isJavaAgentName, isRumAgentName } from '../../../../common/agent_name';
import { enableServiceOverview } from '../../../../common/ui_settings_keys';
import { useApmPluginContext } from '../../../context/apm_plugin/use_apm_plugin_context';
Expand All @@ -19,19 +22,21 @@ import { useServiceMapHref } from '../../shared/Links/apm/ServiceMapLink';
import { useServiceNodeOverviewHref } from '../../shared/Links/apm/ServiceNodeOverviewLink';
import { useServiceOverviewHref } from '../../shared/Links/apm/service_overview_link';
import { useTransactionsOverviewHref } from '../../shared/Links/apm/transaction_overview_link';
import { useServiceProfilingHref } from '../../shared/Links/apm/service_profiling_link';
import { MainTabs } from '../../shared/main_tabs';
import { ErrorGroupOverview } from '../error_group_overview';
import { ServiceMap } from '../ServiceMap';
import { ServiceNodeOverview } from '../service_node_overview';
import { ServiceMetrics } from '../service_metrics';
import { ServiceOverview } from '../service_overview';
import { TransactionOverview } from '../transaction_overview';
import { ServiceProfiling } from '../service_profiling';
import { Correlations } from '../correlations';

interface Tab {
key: string;
href: string;
text: string;
text: ReactNode;
render: () => ReactNode;
}

Expand All @@ -43,12 +48,16 @@ interface Props {
| 'nodes'
| 'overview'
| 'service-map'
| 'profiling'
| 'transactions';
}

export function ServiceDetailTabs({ serviceName, tab }: Props) {
const { agentName } = useApmServiceContext();
const { uiSettings } = useApmPluginContext().core;
const {
core: { uiSettings },
config,
} = useApmPluginContext();
const {
urlParams: { latencyAggregationType },
} = useUrlParams();
Expand Down Expand Up @@ -114,6 +123,38 @@ export function ServiceDetailTabs({ serviceName, tab }: Props) {
) : null,
};

const profilingTab = {
key: 'profiling',
href: useServiceProfilingHref({ serviceName }),
text: (
<EuiFlexGroup direction="row" gutterSize="s">
<EuiFlexItem>
{i18n.translate('xpack.apm.serviceDetails.profilingTabLabel', {
defaultMessage: 'Profiling',
})}
</EuiFlexItem>
<EuiFlexItem>
<EuiBetaBadge
label={i18n.translate(
'xpack.apm.serviceDetails.profilingTabExperimentalLabel',
{
defaultMessage: 'Experimental',
}
)}
tooltipContent={i18n.translate(
'xpack.apm.serviceDetails.profilingTabExperimentalDescription',
{
defaultMessage:
'Profiling is highly experimental and for internal use only.',
}
)}
/>
</EuiFlexItem>
</EuiFlexGroup>
),
render: () => <ServiceProfiling serviceName={serviceName} />,
};

const tabs: Tab[] = [transactionsTab, errorsTab];

if (uiSettings.get(enableServiceOverview)) {
Expand All @@ -128,6 +169,10 @@ export function ServiceDetailTabs({ serviceName, tab }: Props) {

tabs.push(serviceMapTab);

if (config.profilingEnabled) {
tabs.push(profilingTab);
}

const selectedTab = tabs.find((serviceTab) => serviceTab.key === tab);

return (
Expand Down
Loading