diff --git a/x-pack/plugins/apm/public/components/app/TransactionOverview/TransactionList/TransactionList.stories.tsx b/x-pack/plugins/apm/public/components/app/TransactionOverview/TransactionList/TransactionList.stories.tsx new file mode 100644 index 000000000000..bc9df71c534e --- /dev/null +++ b/x-pack/plugins/apm/public/components/app/TransactionOverview/TransactionList/TransactionList.stories.tsx @@ -0,0 +1,119 @@ +/* + * 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. + */ + +import { storiesOf } from '@storybook/react'; +import React from 'react'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { TransactionGroup } from '../../../../../server/lib/transaction_groups/fetcher'; +import { TransactionList } from './'; + +storiesOf('app/TransactionOverview/TransactionList', module).add( + 'Single Row', + () => { + const items: TransactionGroup[] = [ + { + name: + 'GET /api/v1/regions/azure-eastus2/clusters/elasticsearch/xc18de071deb4262be54baebf5f6a1ce/proxy/_snapshot/found-snapshots/_all', + sample: { + container: { + id: + 'xa802046074071c9c828e8db3b7ef92ea0484d9fe783b9c518f65a7b45dfdd2c', + }, + agent: { + name: 'java', + ephemeral_id: 'x787d6b7-3241-4b55-ba49-0c96bc9857d1', + version: '1.17.0', + }, + process: { + pid: 28, + title: '/usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java', + }, + processor: { + name: 'transaction', + event: 'transaction', + }, + labels: { + path: + '/api/v1/regions/azure-eastus2/clusters/elasticsearch/xc18de071deb4262be54baebf5f6a1ce/proxy/_snapshot/found-snapshots/_all', + status_code: '200', + request_method: 'GET', + request_id: 'x273dc2477e021979125e0ec67e8d778', + }, + observer: { + hostname: 'x840922c967b', + name: 'instance-000000000x', + id: 'xb384baf-c16a-415a-928a-a10635a04b81', + ephemeral_id: 'x9227f0e-848d-423e-a65a-5fdee321f4a9', + type: 'apm-server', + version: '7.8.1', + version_major: 7, + }, + trace: { + id: 'x998d7e5db84aa8341b358a264a78984', + }, + '@timestamp': '2020-08-26T14:40:31.472Z', + ecs: { + version: '1.5.0', + }, + service: { + node: { + name: + 'xa802046074071c9c828e8db3b7ef92ea0484d9fe783b9c518f65a7b45dfdd2c', + }, + environment: 'qa', + framework: { + name: 'API', + }, + name: 'adminconsole', + runtime: { + name: 'Java', + version: '1.8.0_265', + }, + language: { + name: 'Java', + version: '1.8.0_265', + }, + version: 'ms-44.1-BC_1', + }, + host: { + hostname: 'xa8020460740', + os: { + platform: 'Linux', + }, + ip: '3.83.239.24', + name: 'xa8020460740', + architecture: 'amd64', + }, + transaction: { + duration: { + us: 8260617, + }, + result: 'HTTP 2xx', + name: + 'GET /api/v1/regions/azure-eastus2/clusters/elasticsearch/xc18de071deb4262be54baebf5f6a1ce/proxy/_snapshot/found-snapshots/_all', + span_count: { + dropped: 0, + started: 8, + }, + id: 'xaa3cae6fd4f7023', + type: 'request', + sampled: true, + }, + timestamp: { + us: 1598452831472001, + }, + }, + p95: 11974156, + averageResponseTime: 8087434.558974359, + transactionsPerMinute: 0.40625, + impact: 100, + impactRelative: 100, + }, + ]; + + return ; + } +); diff --git a/x-pack/plugins/apm/public/components/app/TransactionOverview/List/index.tsx b/x-pack/plugins/apm/public/components/app/TransactionOverview/TransactionList/index.tsx similarity index 85% rename from x-pack/plugins/apm/public/components/app/TransactionOverview/List/index.tsx rename to x-pack/plugins/apm/public/components/app/TransactionOverview/TransactionList/index.tsx index 2b1c1b8e8c11..d8c6d7d28fa9 100644 --- a/x-pack/plugins/apm/public/components/app/TransactionOverview/List/index.tsx +++ b/x-pack/plugins/apm/public/components/app/TransactionOverview/TransactionList/index.tsx @@ -19,9 +19,16 @@ import { LoadingStatePrompt } from '../../../shared/LoadingStatePrompt'; import { EmptyMessage } from '../../../shared/EmptyMessage'; import { TransactionDetailLink } from '../../../shared/Links/apm/TransactionDetailLink'; +// Truncate both the link and the child span (the tooltip anchor.) The link so +// it doesn't overflow, and the anchor so we get the ellipsis. const TransactionNameLink = styled(TransactionDetailLink)` - ${truncate('100%')}; font-family: ${fontFamilyCode}; + white-space: nowrap; + ${truncate('100%')}; + + > span { + ${truncate('100%')}; + } `; interface Props { @@ -41,20 +48,20 @@ export function TransactionList({ items, isLoading }: Props) { sortable: true, render: (_, { sample }: TransactionGroup) => { return ( - - - {sample.transaction.name || NOT_AVAILABLE_LABEL} - - + <>{sample.transaction.name || NOT_AVAILABLE_LABEL} + + ); }, }, diff --git a/x-pack/plugins/apm/public/components/app/TransactionOverview/index.tsx b/x-pack/plugins/apm/public/components/app/TransactionOverview/index.tsx index 81d8a6f80737..5999988abe84 100644 --- a/x-pack/plugins/apm/public/components/app/TransactionOverview/index.tsx +++ b/x-pack/plugins/apm/public/components/app/TransactionOverview/index.tsx @@ -33,7 +33,7 @@ import { ElasticDocsLink } from '../../shared/Links/ElasticDocsLink'; import { fromQuery, toQuery } from '../../shared/Links/url_helpers'; import { LocalUIFilters } from '../../shared/LocalUIFilters'; import { TransactionTypeFilter } from '../../shared/LocalUIFilters/TransactionTypeFilter'; -import { TransactionList } from './List'; +import { TransactionList } from './TransactionList'; import { useRedirect } from './useRedirect'; function getRedirectLocation({ @@ -62,6 +62,7 @@ function getRedirectLocation({ export function TransactionOverview() { const location = useLocation(); const { urlParams } = useUrlParams(); + const { serviceName, transactionType } = urlParams; // TODO: fetching of transaction types should perhaps be lifted since it is needed in several places. Context? diff --git a/x-pack/plugins/apm/public/components/shared/ApmHeader/ApmHeader.stories.tsx b/x-pack/plugins/apm/public/components/shared/ApmHeader/ApmHeader.stories.tsx new file mode 100644 index 000000000000..c9b7c7740984 --- /dev/null +++ b/x-pack/plugins/apm/public/components/shared/ApmHeader/ApmHeader.stories.tsx @@ -0,0 +1,30 @@ +/* + * 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. + */ + +import { EuiTitle } from '@elastic/eui'; +import { storiesOf } from '@storybook/react'; +import React from 'react'; +import { MockApmPluginContextWrapper } from '../../../context/ApmPluginContext/MockApmPluginContext'; +import { ApmHeader } from './'; + +storiesOf('shared/ApmHeader', module) + .addDecorator((storyFn) => { + return ( + {storyFn()} + ); + }) + .add('Example', () => { + return ( + + +

+ GET + /api/v1/regions/azure-eastus2/clusters/elasticsearch/xc18de071deb4262be54baebf5f6a1ce/proxy/_snapshot/found-snapshots/_all +

+
+
+ ); + }); diff --git a/x-pack/plugins/apm/public/components/shared/ApmHeader/index.tsx b/x-pack/plugins/apm/public/components/shared/ApmHeader/index.tsx index 4ffd42280181..9f67ba99103e 100644 --- a/x-pack/plugins/apm/public/components/shared/ApmHeader/index.tsx +++ b/x-pack/plugins/apm/public/components/shared/ApmHeader/index.tsx @@ -6,15 +6,25 @@ import { EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui'; import React, { ReactNode } from 'react'; -import { KueryBar } from '../KueryBar'; +import styled from 'styled-components'; import { DatePicker } from '../DatePicker'; import { EnvironmentFilter } from '../EnvironmentFilter'; +import { KueryBar } from '../KueryBar'; + +// Header titles with long, unbroken words, like you would see for a long URL in +// a transaction name, with the default `work-break`, don't break, and that ends +// up pushing the date picker off of the screen. Setting `break-all` here lets +// it wrap even if it has a long, unbroken work. The wrapped result is not great +// looking, since it wraps, but it doesn't push any controls off of the screen. +const ChildrenContainerFlexItem = styled(EuiFlexItem)` + word-break: break-all; +`; export function ApmHeader({ children }: { children: ReactNode }) { return ( <> - {children} + {children} diff --git a/x-pack/plugins/apm/server/lib/transaction_groups/fetcher.ts b/x-pack/plugins/apm/server/lib/transaction_groups/fetcher.ts index d0ba31f42c53..5c1e1839d9c5 100644 --- a/x-pack/plugins/apm/server/lib/transaction_groups/fetcher.ts +++ b/x-pack/plugins/apm/server/lib/transaction_groups/fetcher.ts @@ -185,10 +185,12 @@ export async function transactionGroupsFetcher( } export interface TransactionGroup { - key: Record | string; + name?: string; + key?: Record | string; averageResponseTime: number | null | undefined; transactionsPerMinute: number; p95: number | null | undefined; impact: number; + impactRelative?: number; sample: Transaction; } diff --git a/x-pack/plugins/apm/typings/es_schemas/raw/fields/host.ts b/x-pack/plugins/apm/typings/es_schemas/raw/fields/host.ts index 51c09e59d9b6..1869a4fc1bef 100644 --- a/x-pack/plugins/apm/typings/es_schemas/raw/fields/host.ts +++ b/x-pack/plugins/apm/typings/es_schemas/raw/fields/host.ts @@ -5,5 +5,11 @@ */ export interface Host { + architecture?: string; hostname?: string; + name?: string; + ip?: string; + os?: { + platform?: string; + }; } diff --git a/x-pack/plugins/apm/typings/es_schemas/raw/fields/observer.ts b/x-pack/plugins/apm/typings/es_schemas/raw/fields/observer.ts index 0815b7cd8816..823d12cbd809 100644 --- a/x-pack/plugins/apm/typings/es_schemas/raw/fields/observer.ts +++ b/x-pack/plugins/apm/typings/es_schemas/raw/fields/observer.ts @@ -5,7 +5,11 @@ */ export interface Observer { + ephemeral_id?: string; + hostname?: string; + id?: string; name?: string; + type?: string; version: string; version_major: number; } diff --git a/x-pack/plugins/apm/typings/es_schemas/raw/fields/process.ts b/x-pack/plugins/apm/typings/es_schemas/raw/fields/process.ts index 63e1faa38216..898ef04ed6a0 100644 --- a/x-pack/plugins/apm/typings/es_schemas/raw/fields/process.ts +++ b/x-pack/plugins/apm/typings/es_schemas/raw/fields/process.ts @@ -5,8 +5,8 @@ */ export interface Process { - args: string[]; + args?: string[]; pid: number; - ppid: number; - title: string; + ppid?: number; + title?: string; } diff --git a/x-pack/plugins/apm/typings/es_schemas/raw/fields/service.ts b/x-pack/plugins/apm/typings/es_schemas/raw/fields/service.ts index 3ef852ebf6dd..00795d69e13b 100644 --- a/x-pack/plugins/apm/typings/es_schemas/raw/fields/service.ts +++ b/x-pack/plugins/apm/typings/es_schemas/raw/fields/service.ts @@ -9,7 +9,10 @@ export interface Service { environment?: string; framework?: { name: string; - version: string; + version?: string; + }; + node?: { + name?: string; }; runtime?: { name: string; @@ -19,4 +22,5 @@ export interface Service { name: string; version?: string; }; + version?: string; } diff --git a/x-pack/plugins/apm/typings/es_schemas/raw/transaction_raw.ts b/x-pack/plugins/apm/typings/es_schemas/raw/transaction_raw.ts index b8ebb4cf8da5..cdfe4183c96f 100644 --- a/x-pack/plugins/apm/typings/es_schemas/raw/transaction_raw.ts +++ b/x-pack/plugins/apm/typings/es_schemas/raw/transaction_raw.ts @@ -54,6 +54,7 @@ export interface TransactionRaw extends APMBaseDoc { // Shared by errors and transactions container?: Container; + ecs?: { version?: string }; host?: Host; http?: Http; kubernetes?: Kubernetes; diff --git a/x-pack/plugins/apm/typings/es_schemas/ui/fields/agent.ts b/x-pack/plugins/apm/typings/es_schemas/ui/fields/agent.ts index 1e542dec06a7..4d98825f36b5 100644 --- a/x-pack/plugins/apm/typings/es_schemas/ui/fields/agent.ts +++ b/x-pack/plugins/apm/typings/es_schemas/ui/fields/agent.ts @@ -19,6 +19,7 @@ export type AgentName = | 'ruby'; export interface Agent { + ephemeral_id?: string; name: AgentName; version: string; }