[APM] Add “Analyze Data” button (#103485)

Co-authored-by: Shahzad <shahzad31comp@gmail.com>
This commit is contained in:
Søren Louv-Jansen 2021-06-30 10:20:31 +02:00 committed by GitHub
parent 21858a570d
commit 4aca0b7b61
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 282 additions and 11 deletions

View file

@ -16,6 +16,9 @@ exports[`APM telemetry helpers getApmTelemetry generates a JSON object with the
"dotnet": {
"type": "long"
},
"iOS/swift": {
"type": "long"
},
"go": {
"type": "long"
},
@ -70,6 +73,9 @@ exports[`APM telemetry helpers getApmTelemetry generates a JSON object with the
"opentelemetry/ruby": {
"type": "long"
},
"opentelemetry/swift": {
"type": "long"
},
"opentelemetry/webjs": {
"type": "long"
}
@ -131,6 +137,60 @@ exports[`APM telemetry helpers getApmTelemetry generates a JSON object with the
}
}
},
"iOS/swift": {
"properties": {
"agent": {
"properties": {
"version": {
"type": "keyword"
}
}
},
"service": {
"properties": {
"framework": {
"properties": {
"name": {
"type": "keyword"
},
"version": {
"type": "keyword"
},
"composite": {
"type": "keyword"
}
}
},
"language": {
"properties": {
"name": {
"type": "keyword"
},
"version": {
"type": "keyword"
},
"composite": {
"type": "keyword"
}
}
},
"runtime": {
"properties": {
"name": {
"type": "keyword"
},
"version": {
"type": "keyword"
},
"composite": {
"type": "keyword"
}
}
}
}
}
}
},
"go": {
"properties": {
"agent": {

View file

@ -5,7 +5,7 @@
* 2.0.
*/
import { isJavaAgentName, isRumAgentName } from './agent_name';
import { isJavaAgentName, isRumAgentName, isIosAgentName } from './agent_name';
describe('agent name helpers', () => {
describe('isJavaAgentName', () => {
@ -22,7 +22,7 @@ describe('agent name helpers', () => {
});
describe('when the agent name is not java', () => {
it('returns true', () => {
it('returns false', () => {
expect(isJavaAgentName('not java')).toEqual(false);
});
});
@ -47,9 +47,35 @@ describe('agent name helpers', () => {
});
});
describe('when the agent name something else', () => {
describe('when the agent name is something else', () => {
it('returns false', () => {
expect(isRumAgentName('not rum')).toEqual(false);
});
});
});
describe('isIosAgentName', () => {
describe('when the agent name is js-base', () => {
it('returns true', () => {
expect(isRumAgentName('java')).toEqual(false);
expect(isIosAgentName('iOS/swift')).toEqual(true);
});
});
describe('when the agent name is rum-js', () => {
it('returns true', () => {
expect(isIosAgentName('ios/swift')).toEqual(true);
});
});
describe('when the agent name is opentelemetry/swift', () => {
it('returns true', () => {
expect(isIosAgentName('opentelemetry/swift')).toEqual(true);
});
});
describe('when the agent name is something else', () => {
it('returns false', () => {
expect(isIosAgentName('not ios')).toEqual(false);
});
});
});

View file

@ -26,12 +26,14 @@ export const OPEN_TELEMETRY_AGENT_NAMES: AgentName[] = [
'opentelemetry/php',
'opentelemetry/python',
'opentelemetry/ruby',
'opentelemetry/swift',
'opentelemetry/webjs',
];
export const AGENT_NAMES: AgentName[] = [
'dotnet',
'go',
'iOS/swift',
'java',
'js-base',
'nodejs',
@ -62,7 +64,9 @@ export function isRumAgentName(
return RUM_AGENT_NAMES.includes(agentName! as AgentName);
}
export function normalizeAgentName(agentName: string | undefined) {
export function normalizeAgentName<T extends string | undefined>(
agentName: T
): T | string {
if (isRumAgentName(agentName)) {
return 'rum-js';
}
@ -71,5 +75,14 @@ export function normalizeAgentName(agentName: string | undefined) {
return 'java';
}
if (isIosAgentName(agentName)) {
return 'ios';
}
return agentName;
}
export function isIosAgentName(agentName?: string) {
const lowercased = agentName && agentName.toLowerCase();
return lowercased === 'ios/swift' || lowercased === 'opentelemetry/swift';
}

View file

@ -131,6 +131,7 @@ export function Correlations() {
return (
<>
<EuiButton
fill
onClick={() => {
setIsFlyoutVisible(true);
}}

View file

@ -8,7 +8,7 @@
import { EuiFlexGroup, EuiFlexItem, EuiPanel } from '@elastic/eui';
import React from 'react';
import { useTrackPageview } from '../../../../../observability/public';
import { isRumAgentName } from '../../../../common/agent_name';
import { isRumAgentName, isIosAgentName } from '../../../../common/agent_name';
import { AnnotationsContextProvider } from '../../../context/annotations/annotations_context';
import { useApmServiceContext } from '../../../context/apm_service/use_apm_service_context';
import { ChartPointerEventContextProvider } from '../../../context/chart_pointer_event/chart_pointer_event_context';
@ -43,6 +43,7 @@ export function ServiceOverview({ serviceName }: ServiceOverviewProps) {
const { isMedium } = useBreakPoints();
const rowDirection = isMedium ? 'column' : 'row';
const isRumAgent = isRumAgentName(agentName);
const isIosAgent = isIosAgentName(agentName);
return (
<AnnotationsContextProvider>
@ -110,7 +111,7 @@ export function ServiceOverview({ serviceName }: ServiceOverviewProps) {
)}
</EuiFlexGroup>
</EuiFlexItem>
{!isRumAgent && (
{!isRumAgent && !isIosAgent && (
<EuiFlexItem>
<EuiFlexGroup
direction="column"

View file

@ -13,11 +13,18 @@ import {
EuiPageHeaderProps,
EuiTitle,
EuiBetaBadge,
EuiToolTip,
EuiButtonEmpty,
} from '@elastic/eui';
import { ApmMainTemplate } from './apm_main_template';
import { useKibana } from '../../../../../../../src/plugins/kibana_react/public';
import { ApmServiceContextProvider } from '../../../context/apm_service/apm_service_context';
import { enableServiceOverview } from '../../../../common/ui_settings_keys';
import { isJavaAgentName, isRumAgentName } from '../../../../common/agent_name';
import {
isJavaAgentName,
isRumAgentName,
isIosAgentName,
} from '../../../../common/agent_name';
import { ServiceIcons } from '../../shared/service_icons';
import { useApmPluginContext } from '../../../context/apm_plugin/use_apm_plugin_context';
import { useApmServiceContext } from '../../../context/apm_service/use_apm_service_context';
@ -29,8 +36,17 @@ import { useServiceOverviewHref } from '../../shared/Links/apm/service_overview_
import { useServiceProfilingHref } from '../../shared/Links/apm/service_profiling_link';
import { useTransactionsOverviewHref } from '../../shared/Links/apm/transaction_overview_link';
import { useUrlParams } from '../../../context/url_params_context/use_url_params';
import { ENVIRONMENT_NOT_DEFINED } from '../../../../common/environment_filter_values';
import {
SERVICE_NAME,
SERVICE_ENVIRONMENT,
} from '../../../../common/elasticsearch_fieldnames';
import { Correlations } from '../../app/correlations';
import { SearchBar } from '../../shared/search_bar';
import {
createExploratoryViewUrl,
SeriesUrl,
} from '../../../../../observability/public';
type Tab = NonNullable<EuiPageHeaderProps['tabs']>[0] & {
key:
@ -54,12 +70,12 @@ interface Props {
export function ApmServiceTemplate(props: Props) {
return (
<ApmServiceContextProvider>
<Template {...props} />
<TemplateWithContext {...props} />
</ApmServiceContextProvider>
);
}
function Template({
function TemplateWithContext({
children,
serviceName,
selectedTab,
@ -86,6 +102,10 @@ function Template({
</EuiFlexGroup>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<AnalyzeDataButton serviceName={serviceName} />
</EuiFlexItem>
<EuiFlexItem grow={false}>
<Correlations />
</EuiFlexItem>
@ -100,6 +120,53 @@ function Template({
);
}
function AnalyzeDataButton({ serviceName }: { serviceName: string }) {
const { agentName } = useApmServiceContext();
const { services } = useKibana();
const { urlParams } = useUrlParams();
const { rangeTo, rangeFrom, environment } = urlParams;
const basepath = services.http?.basePath.get();
if (isRumAgentName(agentName) || isIosAgentName(agentName)) {
const href = createExploratoryViewUrl(
{
'apm-series': {
dataType: isRumAgentName(agentName) ? 'ux' : 'mobile',
time: { from: rangeFrom, to: rangeTo },
reportType: 'kpi-over-time',
reportDefinitions: {
[SERVICE_NAME]: [serviceName],
...(!!environment && ENVIRONMENT_NOT_DEFINED.value !== environment
? { [SERVICE_ENVIRONMENT]: [environment] }
: {}),
},
operationType: 'average',
isNew: true,
} as SeriesUrl,
},
basepath
);
return (
<EuiToolTip
position="top"
content={i18n.translate('xpack.apm.analyzeDataButton.tooltip', {
defaultMessage:
'EXPERIMENTAL - Analyze Data allows you to select and filter result data in any dimension, and look for the cause or impact of performance problems',
})}
>
<EuiButtonEmpty href={href} iconType="visBarVerticalStacked">
{i18n.translate('xpack.apm.analyzeDataButton.label', {
defaultMessage: 'Analyze data',
})}
</EuiButtonEmpty>
</EuiToolTip>
);
}
return null;
}
function useTabs({
serviceName,
selectedTab,
@ -153,7 +220,10 @@ function useTabs({
defaultMessage: 'Metrics',
}),
hidden:
!agentName || isRumAgentName(agentName) || isJavaAgentName(agentName),
!agentName ||
isRumAgentName(agentName) ||
isJavaAgentName(agentName) ||
isIosAgentName(agentName),
},
{
key: 'service-map',

View file

@ -6,6 +6,7 @@
*/
import {
isIosAgentName,
isRumAgentName,
isJavaAgentName,
OPEN_TELEMETRY_AGENT_NAMES,
@ -70,6 +71,10 @@ export function getAgentIconKey(agentName: string) {
return 'java';
}
if (isIosAgentName(lowercasedAgentName)) {
return 'ios';
}
// Remove "opentelemetry/" prefix
const agentNameWithoutPrefix = lowercasedAgentName.replace(
/^opentelemetry\//,

View file

@ -74,6 +74,7 @@ const apmPerAgentSchema: Pick<
// In the meanwhile, we'll have to maintain these lists up to date (TS will remind us to update)
services_per_agent: {
dotnet: long,
'iOS/swift': long,
go: long,
java: long,
'js-base': long,
@ -92,10 +93,12 @@ const apmPerAgentSchema: Pick<
'opentelemetry/php': long,
'opentelemetry/python': long,
'opentelemetry/ruby': long,
'opentelemetry/swift': long,
'opentelemetry/webjs': long,
},
agents: {
dotnet: agentSchema,
'iOS/swift': agentSchema,
go: agentSchema,
java: agentSchema,
'js-base': agentSchema,

View file

@ -9,6 +9,7 @@ export type ElasticAgentName =
| 'go'
| 'java'
| 'js-base'
| 'iOS/swift'
| 'rum-js'
| 'nodejs'
| 'python'
@ -27,6 +28,7 @@ export type OpenTelemetryAgentName =
| 'opentelemetry/php'
| 'opentelemetry/python'
| 'opentelemetry/ruby'
| 'opentelemetry/swift'
| 'opentelemetry/webjs';
/*

View file

@ -319,6 +319,9 @@
"dotnet": {
"type": "long"
},
"iOS/swift": {
"type": "long"
},
"go": {
"type": "long"
},
@ -373,6 +376,9 @@
"opentelemetry/ruby": {
"type": "long"
},
"opentelemetry/swift": {
"type": "long"
},
"opentelemetry/webjs": {
"type": "long"
}
@ -464,6 +470,90 @@
}
}
},
"iOS/swift": {
"properties": {
"agent": {
"properties": {
"version": {
"type": "array",
"items": {
"type": "keyword"
}
}
}
},
"service": {
"properties": {
"framework": {
"properties": {
"name": {
"type": "array",
"items": {
"type": "keyword"
}
},
"version": {
"type": "array",
"items": {
"type": "keyword"
}
},
"composite": {
"type": "array",
"items": {
"type": "keyword"
}
}
}
},
"language": {
"properties": {
"name": {
"type": "array",
"items": {
"type": "keyword"
}
},
"version": {
"type": "array",
"items": {
"type": "keyword"
}
},
"composite": {
"type": "array",
"items": {
"type": "keyword"
}
}
}
},
"runtime": {
"properties": {
"name": {
"type": "array",
"items": {
"type": "keyword"
}
},
"version": {
"type": "array",
"items": {
"type": "keyword"
}
},
"composite": {
"type": "array",
"items": {
"type": "keyword"
}
}
}
}
}
}
}
},
"go": {
"properties": {
"agent": {