Skip to content

Commit

Permalink
[APM] Improve types for tabs and properties table (elastic#32462)
Browse files Browse the repository at this point in the history
* [APM] Improve types for tabs

* Update translations

* Rename Tab to PropertyTab

* Add comment about agent names
  • Loading branch information
sorenlouv authored Mar 8, 2019
1 parent cc7788d commit d2e16b5
Show file tree
Hide file tree
Showing 26 changed files with 731 additions and 574 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ exports[`Error PARENT_ID 1`] = `"parentId"`;

exports[`Error PROCESSOR_EVENT 1`] = `"error"`;

exports[`Error SERVICE_AGENT_NAME 1`] = `"agent name"`;
exports[`Error SERVICE_AGENT_NAME 1`] = `"java"`;

exports[`Error SERVICE_NAME 1`] = `"service name"`;

Expand Down Expand Up @@ -90,7 +90,7 @@ exports[`Span PARENT_ID 1`] = `"parentId"`;

exports[`Span PROCESSOR_EVENT 1`] = `"span"`;

exports[`Span SERVICE_AGENT_NAME 1`] = `"agent name"`;
exports[`Span SERVICE_AGENT_NAME 1`] = `"java"`;

exports[`Span SERVICE_NAME 1`] = `"service name"`;

Expand Down Expand Up @@ -152,7 +152,7 @@ exports[`Transaction PARENT_ID 1`] = `"parentId"`;

exports[`Transaction PROCESSOR_EVENT 1`] = `"transaction"`;

exports[`Transaction SERVICE_AGENT_NAME 1`] = `"agent name"`;
exports[`Transaction SERVICE_AGENT_NAME 1`] = `"java"`;

exports[`Transaction SERVICE_NAME 1`] = `"service name"`;

Expand Down
6 changes: 3 additions & 3 deletions x-pack/plugins/apm/common/elasticsearch_fieldnames.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ describe('Transaction', () => {
const transaction: Transaction = {
'@timestamp': new Date().toString(),
agent: {
name: 'agent name',
name: 'java',
version: 'agent version'
},
http: {
Expand Down Expand Up @@ -59,7 +59,7 @@ describe('Span', () => {
const span: Span = {
'@timestamp': new Date().toString(),
agent: {
name: 'agent name',
name: 'java',
version: 'agent version'
},
processor: {
Expand Down Expand Up @@ -101,7 +101,7 @@ describe('Span', () => {
describe('Error', () => {
const errorDoc: APMError = {
agent: {
name: 'agent name',
name: 'java',
version: 'agent version'
},
error: {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* 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 { i18n } from '@kbn/i18n';
import { isEmpty } from 'lodash';
import { idx } from 'x-pack/plugins/apm/common/idx';
import { APMError } from 'x-pack/plugins/apm/typings/es_schemas/Error';
import {
getTabsFromObject,
PropertyTab
} from '../../../shared/PropertiesTable/tabConfig';

export type ErrorTab = PropertyTab | ExceptionTab | LogTab;

interface LogTab {
key: 'log_stacktrace';
label: string;
}

export const logStacktraceTab: LogTab = {
key: 'log_stacktrace',
label: i18n.translate('xpack.apm.propertiesTable.tabs.logStacktraceLabel', {
defaultMessage: 'Log stacktrace'
})
};

interface ExceptionTab {
key: 'exception_stacktrace';
label: string;
}

export const exceptionStacktraceTab: ExceptionTab = {
key: 'exception_stacktrace',
label: i18n.translate(
'xpack.apm.propertiesTable.tabs.exceptionStacktraceLabel',
{
defaultMessage: 'Exception stacktrace'
}
)
};

export function getTabs(error: APMError) {
const hasLogStacktrace = !isEmpty(idx(error, _ => _.error.log.stacktrace));
return [
...(hasLogStacktrace ? [logStacktraceTab] : []),
exceptionStacktraceTab,
...getTabsFromObject(error)
];
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* 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 { shallow } from 'enzyme';
import React from 'react';
import { APMError } from 'x-pack/plugins/apm/typings/es_schemas/Error';
import { Transaction } from 'x-pack/plugins/apm/typings/es_schemas/Transaction';
import { StickyErrorProperties } from './StickyErrorProperties';

describe('StickyErrorProperties', () => {
it('should render StickyProperties', () => {
const transaction = {
http: { request: { method: 'GET' } },
url: { full: 'myUrl' },
trace: { id: 'traceId' },
transaction: {
type: 'myTransactionType',
name: 'myTransactionName',
id: 'myTransactionName'
},
service: { name: 'myService' },
user: { id: 'myUserId' }
} as Transaction;

const error = {
'@timestamp': 'myTimestamp',
http: { request: { method: 'GET' } },
url: { full: 'myUrl' },
service: { name: 'myService' },
user: { id: 'myUserId' },
error: { exception: [{ handled: true }] },
transaction: { id: 'myTransactionId', sampled: true }
} as APMError;

const wrapper = shallow(
<StickyErrorProperties error={error} transaction={transaction} />
);

expect(wrapper).toMatchSnapshot();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
/*
* 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 { i18n } from '@kbn/i18n';
import React, { Fragment } from 'react';
import {
ERROR_EXC_HANDLED,
HTTP_REQUEST_METHOD,
TRANSACTION_ID,
URL_FULL,
USER_ID
} from 'x-pack/plugins/apm/common/elasticsearch_fieldnames';
import { NOT_AVAILABLE_LABEL } from 'x-pack/plugins/apm/common/i18n';
import { idx } from 'x-pack/plugins/apm/common/idx';
import { APMError } from 'x-pack/plugins/apm/typings/es_schemas/Error';
import { Transaction } from 'x-pack/plugins/apm/typings/es_schemas/Transaction';
import { KibanaLink } from '../../../shared/Links/KibanaLink';
import { legacyEncodeURIComponent } from '../../../shared/Links/url_helpers';
import { StickyProperties } from '../../../shared/StickyProperties';

interface Props {
error: APMError;
transaction: Transaction | undefined;
}

function TransactionLink({ error, transaction }: Props) {
if (!transaction) {
return <Fragment>{NOT_AVAILABLE_LABEL}</Fragment>;
}

const isSampled = error.transaction.sampled;
if (!isSampled) {
return <Fragment>{transaction.transaction.id}</Fragment>;
}

const path = `/${
transaction.service.name
}/transactions/${legacyEncodeURIComponent(
transaction.transaction.type
)}/${legacyEncodeURIComponent(transaction.transaction.name)}`;

return (
<KibanaLink
hash={path}
query={{
transactionId: transaction.transaction.id,
traceId: transaction.trace.id
}}
>
{transaction.transaction.id}
</KibanaLink>
);
}

export function StickyErrorProperties({ error, transaction }: Props) {
const stickyProperties = [
{
fieldName: '@timestamp',
label: i18n.translate('xpack.apm.errorGroupDetails.timestampLabel', {
defaultMessage: 'Timestamp'
}),
val: error['@timestamp'],
width: '50%'
},
{
fieldName: URL_FULL,
label: 'URL',
val:
idx(error, _ => _.context.page.url) ||
idx(error, _ => _.url.full) ||
NOT_AVAILABLE_LABEL,
truncated: true,
width: '50%'
},
{
fieldName: HTTP_REQUEST_METHOD,
label: i18n.translate('xpack.apm.errorGroupDetails.requestMethodLabel', {
defaultMessage: 'Request method'
}),
val: idx(error, _ => _.http.request.method) || NOT_AVAILABLE_LABEL,
width: '25%'
},
{
fieldName: ERROR_EXC_HANDLED,
label: i18n.translate('xpack.apm.errorGroupDetails.handledLabel', {
defaultMessage: 'Handled'
}),
val:
String(idx(error, _ => _.error.exception[0].handled)) ||
NOT_AVAILABLE_LABEL,
width: '25%'
},
{
fieldName: TRANSACTION_ID,
label: i18n.translate(
'xpack.apm.errorGroupDetails.transactionSampleIdLabel',
{
defaultMessage: 'Transaction sample ID'
}
),
val: <TransactionLink transaction={transaction} error={error} />,
width: '25%'
},
{
fieldName: USER_ID,
label: i18n.translate('xpack.apm.errorGroupDetails.userIdLabel', {
defaultMessage: 'User ID'
}),
val: idx(error, _ => _.user.id) || NOT_AVAILABLE_LABEL,
width: '25%'
}
];

return <StickyProperties stickyProperties={stickyProperties} />;
}
Original file line number Diff line number Diff line change
@@ -1,48 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`DetailView should render Discover button 1`] = `
<DiscoverErrorLink
error={
Object {
"@timestamp": "myTimestamp",
"error": Object {
"exception": Object {
"handled": true,
},
},
"http": Object {
"request": Object {
"method": "GET",
},
},
"service": Object {
"name": "myService",
},
"transaction": Object {
"id": "myTransactionId",
"sampled": true,
},
"url": Object {
"full": "myUrl",
},
"user": Object {
"id": "myUserId",
},
}
}
>
<EuiButtonEmpty
color="primary"
iconSide="left"
iconType="discoverApp"
type="button"
>
View 10 occurrences in Discover
</EuiButtonEmpty>
</DiscoverErrorLink>
`;

exports[`DetailView should render StickyProperties 1`] = `
exports[`StickyErrorProperties should render StickyProperties 1`] = `
<StickyProperties
stickyProperties={
Array [
Expand Down Expand Up @@ -144,60 +102,3 @@ exports[`DetailView should render StickyProperties 1`] = `
}
/>
`;

exports[`DetailView should render TabContent 1`] = `
<TabContent
currentTab={
Object {
"key": "exception_stacktrace",
"label": "Exception stacktrace",
}
}
error={
Object {
"@timestamp": "myTimestamp",
"context": Object {},
}
}
/>
`;

exports[`DetailView should render tabs 1`] = `
<EuiTabs
expand={false}
size="m"
>
<EuiTab
disabled={false}
isSelected={true}
key="exception_stacktrace"
onClick={[Function]}
>
Exception stacktrace
</EuiTab>
<EuiTab
disabled={false}
isSelected={false}
key="service"
onClick={[Function]}
>
Service
</EuiTab>
<EuiTab
disabled={false}
isSelected={false}
key="user"
onClick={[Function]}
>
User
</EuiTab>
<EuiTab
disabled={false}
isSelected={false}
key="labels"
onClick={[Function]}
>
Labels
</EuiTab>
</EuiTabs>
`;
Loading

0 comments on commit d2e16b5

Please sign in to comment.