Skip to content

Commit

Permalink
[7.x] [APM] Service overview: Dependencies table (#83416) (#85522)
Browse files Browse the repository at this point in the history
Co-authored-by: Kibana Machine <[email protected]>

Co-authored-by: Kibana Machine <[email protected]>
  • Loading branch information
dgieselaar and kibanamachine authored Dec 10, 2020
1 parent 48a2063 commit 1d3fc74
Show file tree
Hide file tree
Showing 48 changed files with 1,953 additions and 228 deletions.

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

5 changes: 5 additions & 0 deletions x-pack/plugins/apm/common/elasticsearch_fieldnames.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,11 @@ export const SPAN_NAME = 'span.name';
export const SPAN_ID = 'span.id';
export const SPAN_DESTINATION_SERVICE_RESOURCE =
'span.destination.service.resource';
export const SPAN_DESTINATION_SERVICE_RESPONSE_TIME_COUNT =
'span.destination.service.response_time.count';

export const SPAN_DESTINATION_SERVICE_RESPONSE_TIME_SUM =
'span.destination.service.response_time.sum.us';

// Parent ID for a transaction or span
export const PARENT_ID = 'parent.id';
Expand Down
3 changes: 1 addition & 2 deletions x-pack/plugins/apm/common/utils/formatters/duration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { i18n } from '@kbn/i18n';
import moment from 'moment';
import { memoize } from 'lodash';
import { NOT_AVAILABLE_LABEL } from '../../../common/i18n';
import { asDecimal, asDecimalOrInteger, asInteger } from './formatters';
import { asDecimalOrInteger, asInteger, asDecimal } from './formatters';
import { TimeUnit } from './datetime';
import { Maybe } from '../../../typings/common';
import { isFiniteNumber } from '../is_finite_number';
Expand Down Expand Up @@ -181,7 +181,6 @@ export function asDuration(
const formatter = getDurationFormatter(value);
return formatter(value, { defaultValue }).formatted;
}

/**
* Convert a microsecond value to decimal milliseconds. Normally we use
* `asDuration`, but this is used in places like tables where we always want
Expand Down
61 changes: 61 additions & 0 deletions x-pack/plugins/apm/common/utils/join_by_key/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,4 +101,65 @@ describe('joinByKey', () => {
},
]);
});

it('uses the custom merge fn to replace items', () => {
const joined = joinByKey(
[
{
serviceName: 'opbeans-java',
values: ['a'],
},
{
serviceName: 'opbeans-node',
values: ['a'],
},
{
serviceName: 'opbeans-node',
values: ['b'],
},
{
serviceName: 'opbeans-node',
values: ['c'],
},
],
'serviceName',
(a, b) => ({
...a,
...b,
values: a.values.concat(b.values),
})
);

expect(
joined.find((item) => item.serviceName === 'opbeans-node')?.values
).toEqual(['a', 'b', 'c']);
});

it('deeply merges objects', () => {
const joined = joinByKey(
[
{
serviceName: 'opbeans-node',
properties: {
foo: '',
},
},
{
serviceName: 'opbeans-node',
properties: {
bar: '',
},
},
],
'serviceName'
);

expect(joined[0]).toEqual({
serviceName: 'opbeans-node',
properties: {
foo: '',
bar: '',
},
});
});
});
42 changes: 33 additions & 9 deletions x-pack/plugins/apm/common/utils/join_by_key/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
import { UnionToIntersection, ValuesType } from 'utility-types';
import { isEqual } from 'lodash';
import { isEqual, pull, merge, castArray } from 'lodash';

/**
* Joins a list of records by a given key. Key can be any type of value, from
Expand All @@ -23,24 +23,48 @@ import { isEqual } from 'lodash';
*/

type JoinedReturnType<
T extends Record<string, any>,
U extends UnionToIntersection<T>
> = Array<
Partial<U> &
{
[k in keyof T]: T[k];
}
>;

type ArrayOrSingle<T> = T | T[];

export function joinByKey<
T extends Record<string, any>,
U extends UnionToIntersection<T>,
V extends keyof T & keyof U
> = Array<Partial<U> & Record<V, U[V]>>;
V extends ArrayOrSingle<keyof T & keyof U>
>(items: T[], key: V): JoinedReturnType<T, U>;

export function joinByKey<
T extends Record<string, any>,
U extends UnionToIntersection<T>,
V extends keyof T & keyof U
>(items: T[], key: V): JoinedReturnType<T, U, V> {
return items.reduce<JoinedReturnType<T, U, V>>((prev, current) => {
let item = prev.find((prevItem) => isEqual(prevItem[key], current[key]));
V extends ArrayOrSingle<keyof T & keyof U>,
W extends JoinedReturnType<T, U>,
X extends (a: T, b: T) => ValuesType<W>
>(items: T[], key: V, mergeFn: X): W;

export function joinByKey(
items: Array<Record<string, any>>,
key: string | string[],
mergeFn: Function = (a: Record<string, any>, b: Record<string, any>) =>
merge({}, a, b)
) {
const keys = castArray(key);
return items.reduce<Array<Record<string, any>>>((prev, current) => {
let item = prev.find((prevItem) =>
keys.every((k) => isEqual(prevItem[k], current[k]))
);

if (!item) {
item = { ...current } as ValuesType<JoinedReturnType<T, U, V>>;
item = { ...current };
prev.push(item);
} else {
Object.assign(item, current);
pull(prev, item).push(mergeFn(item, current));
}

return prev;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {
ServiceHealthStatus,
} from '../../../../common/service_health_status';
import { FETCH_STATUS } from '../../../hooks/use_fetcher';
import { defaultIcon, iconForNode } from './icons';
import { iconForNode } from './icons';

export const popoverWidth = 280;

Expand Down Expand Up @@ -116,9 +116,7 @@ const getStyle = (theme: EuiTheme): cytoscape.Stylesheet[] => {
'background-color': theme.eui.euiColorGhost,
// The DefinitelyTyped definitions don't specify that a function can be
// used here.
'background-image': isIE11
? undefined
: (el: cytoscape.NodeSingular) => iconForNode(el) ?? defaultIcon,
'background-image': (el: cytoscape.NodeSingular) => iconForNode(el),
'background-height': (el: cytoscape.NodeSingular) =>
isService(el) ? '60%' : '40%',
'background-width': (el: cytoscape.NodeSingular) =>
Expand Down
67 changes: 1 addition & 66 deletions x-pack/plugins/apm/public/components/app/ServiceMap/icons.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,73 +10,8 @@ import {
SPAN_SUBTYPE,
SPAN_TYPE,
} from '../../../../common/elasticsearch_fieldnames';
import awsIcon from './icons/aws.svg';
import cassandraIcon from './icons/cassandra.svg';
import databaseIcon from './icons/database.svg';
import defaultIconImport from './icons/default.svg';
import documentsIcon from './icons/documents.svg';
import elasticsearchIcon from './icons/elasticsearch.svg';
import globeIcon from './icons/globe.svg';
import graphqlIcon from './icons/graphql.svg';
import grpcIcon from './icons/grpc.svg';
import handlebarsIcon from './icons/handlebars.svg';
import kafkaIcon from './icons/kafka.svg';
import mongodbIcon from './icons/mongodb.svg';
import mysqlIcon from './icons/mysql.svg';
import postgresqlIcon from './icons/postgresql.svg';
import redisIcon from './icons/redis.svg';
import websocketIcon from './icons/websocket.svg';
import javaIcon from '../../shared/AgentIcon/icons/java.svg';
import { getAgentIcon } from '../../shared/AgentIcon/get_agent_icon';

export const defaultIcon = defaultIconImport;

const defaultTypeIcons: { [key: string]: string } = {
cache: databaseIcon,
db: databaseIcon,
ext: globeIcon,
external: globeIcon,
messaging: documentsIcon,
resource: globeIcon,
};

const typeIcons: { [key: string]: { [key: string]: string } } = {
aws: {
servicename: awsIcon,
},
db: {
cassandra: cassandraIcon,
elasticsearch: elasticsearchIcon,
mongodb: mongodbIcon,
mysql: mysqlIcon,
postgresql: postgresqlIcon,
redis: redisIcon,
},
external: {
graphql: graphqlIcon,
grpc: grpcIcon,
websocket: websocketIcon,
},
messaging: {
jms: javaIcon,
kafka: kafkaIcon,
},
template: {
handlebars: handlebarsIcon,
},
};

function getSpanIcon(type?: string, subtype?: string) {
if (!type) {
return;
}

const types = type ? typeIcons[type] : {};
if (subtype && types && subtype in types) {
return types[subtype];
}
return defaultTypeIcons[type] || defaultIcon;
}
import { defaultIcon, getSpanIcon } from '../../shared/span_icon/get_span_icon';

// IE 11 does not properly load some SVGs, which causes a runtime error and the
// map to not work at all. We would prefer to do some kind of feature detection
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,11 @@ import { isRumAgentName } from '../../../../common/agent_name';
import { ChartPointerEventContextProvider } from '../../../context/chart_pointer_event/chart_pointer_event_context';
import { TransactionBreakdownChart } from '../../shared/charts/transaction_breakdown_chart';
import { TransactionErrorRateChart } from '../../shared/charts/transaction_error_rate_chart';
import { ServiceMapLink } from '../../shared/Links/apm/ServiceMapLink';
import { SearchBar } from '../../shared/search_bar';
import { ServiceOverviewErrorsTable } from './service_overview_errors_table';
import { ServiceOverviewDependenciesTable } from './service_overview_dependencies_table';
import { ServiceOverviewThroughputChart } from './service_overview_throughput_chart';
import { ServiceOverviewTransactionsTable } from './service_overview_transactions_table';
import { TableLinkFlexItem } from './table_link_flex_item';

/**
* The height a chart should be if it's next to a table with 5 rows and a title.
Expand Down Expand Up @@ -98,30 +97,7 @@ export function ServiceOverview({
</EuiFlexItem>
<EuiFlexItem grow={6}>
<EuiPanel>
<EuiFlexGroup>
<EuiFlexItem>
<EuiTitle size="xs">
<h2>
{i18n.translate(
'xpack.apm.serviceOverview.dependenciesTableTitle',
{
defaultMessage: 'Dependencies',
}
)}
</h2>
</EuiTitle>
</EuiFlexItem>
<TableLinkFlexItem>
<ServiceMapLink serviceName={serviceName}>
{i18n.translate(
'xpack.apm.serviceOverview.dependenciesTableLinkText',
{
defaultMessage: 'View service map',
}
)}
</ServiceMapLink>
</TableLinkFlexItem>
</EuiFlexGroup>
<ServiceOverviewDependenciesTable serviceName={serviceName} />
</EuiPanel>
</EuiFlexItem>
</EuiFlexGroup>
Expand Down
Loading

0 comments on commit 1d3fc74

Please sign in to comment.