Skip to content

Commit

Permalink
Service map language icons (#58633)
Browse files Browse the repository at this point in the history
Add icons as described in #56235.

Also:

* Add double-border and ghost "shadow" on nodes
* Add framework name capability to popover metrics
  • Loading branch information
smith authored Mar 2, 2020
1 parent 90b3678 commit 2378d8a
Show file tree
Hide file tree
Showing 22 changed files with 599 additions and 177 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,51 +4,52 @@
* you may not use this file except in compliance with the Elastic License.
*/

import { EuiCard, EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
import { storiesOf } from '@storybook/react';
import cytoscape from 'cytoscape';
import React from 'react';
import { Cytoscape } from './Cytoscape';

const elements: cytoscape.ElementDefinition[] = [
{
data: {
id: 'opbeans-python',
label: 'opbeans-python',
agentName: 'python',
type: 'service'
}
},
{
data: {
id: 'opbeans-node',
label: 'opbeans-node',
agentName: 'nodejs',
type: 'service'
}
},
{
data: {
id: 'opbeans-ruby',
label: 'opbeans-ruby',
agentName: 'ruby',
type: 'service'
}
},
{ data: { source: 'opbeans-python', target: 'opbeans-node' } },
{
data: {
bidirectional: true,
source: 'opbeans-python',
target: 'opbeans-ruby'
}
}
];
const height = 300;
const serviceName = 'opbeans-python';
import { iconForNode } from './icons';

storiesOf('app/ServiceMap/Cytoscape', module).add(
'example',
() => {
const elements: cytoscape.ElementDefinition[] = [
{
data: {
id: 'opbeans-python',
label: 'opbeans-python',
agentName: 'python',
type: 'service'
}
},
{
data: {
id: 'opbeans-node',
label: 'opbeans-node',
agentName: 'nodejs',
type: 'service'
}
},
{
data: {
id: 'opbeans-ruby',
label: 'opbeans-ruby',
agentName: 'ruby',
type: 'service'
}
},
{ data: { source: 'opbeans-python', target: 'opbeans-node' } },
{
data: {
bidirectional: true,
source: 'opbeans-python',
target: 'opbeans-ruby'
}
}
];
const height = 300;
const serviceName = 'opbeans-python';
return (
<Cytoscape
elements={elements}
Expand All @@ -59,6 +60,119 @@ storiesOf('app/ServiceMap/Cytoscape', module).add(
},
{
info: {
propTables: false,
source: false
}
}
);

storiesOf('app/ServiceMap/Cytoscape', module).add(
'node icons',
() => {
const cy = cytoscape();
const elements = [
{ data: { id: 'default', label: 'default', type: undefined } },
{ data: { id: 'cache', label: 'cache', type: 'cache' } },
{ data: { id: 'database', label: 'database', type: 'database' } },
{ data: { id: 'external', label: 'external', type: 'external' } },
{ data: { id: 'messaging', label: 'messaging', type: 'messaging' } },

{
data: {
id: 'dotnet',
label: 'dotnet service',
type: 'service',
agentName: 'dotnet'
}
},
{
data: {
id: 'go',
label: 'go service',
type: 'service',
agentName: 'go'
}
},
{
data: {
id: 'java',
label: 'java service',
type: 'service',
agentName: 'java'
}
},
{
data: {
id: 'js-base',
label: 'js-base service',
type: 'service',
agentName: 'js-base'
}
},
{
data: {
id: 'nodejs',
label: 'nodejs service',
type: 'service',
agentName: 'nodejs'
}
},
{
data: {
id: 'php',
label: 'php service',
type: 'service',
agentName: 'php'
}
},
{
data: {
id: 'python',
label: 'python service',
type: 'service',
agentName: 'python'
}
},
{
data: {
id: 'ruby',
label: 'ruby service',
type: 'service',
agentName: 'ruby'
}
}
];
cy.add(elements);

return (
<EuiFlexGroup gutterSize="l" wrap={true}>
{cy.nodes().map(node => (
<EuiFlexItem key={node.data('id')}>
<EuiCard
description={
<pre>
agentName: {node.data('agentName') || 'undefined'}, type:{' '}
{node.data('type') || 'undefined'}
</pre>
}
icon={
<img
alt={node.data('label')}
src={iconForNode(node)}
height={80}
width={80}
/>
}
title={node.data('label')}
/>
</EuiFlexItem>
))}
</EuiFlexGroup>
);
},
{
info: {
propTables: false,
source: false
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export function Contents({
onFocusClick,
selectedNodeServiceName
}: ContentsProps) {
const frameworkName = selectedNodeData.frameworkName;
return (
<EuiFlexGroup
direction="column"
Expand All @@ -49,7 +50,10 @@ export function Contents({
</EuiFlexItem>
<EuiFlexItem>
{isService ? (
<ServiceMetricFetcher serviceName={selectedNodeServiceName} />
<ServiceMetricFetcher
frameworkName={frameworkName}
serviceName={selectedNodeServiceName}
/>
) : (
<Info {...selectedNodeData} />
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ storiesOf('app/ServiceMap/Popover/ServiceMetricList', module)
avgRequestsPerMinute={164.47222031860858}
avgCpuUsage={0.32809666568309237}
avgMemoryUsage={0.5504868173242986}
frameworkName="Spring"
numInstances={2}
isLoading={false}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@ import { useUrlParams } from '../../../../hooks/useUrlParams';
import { ServiceMetricList } from './ServiceMetricList';

interface ServiceMetricFetcherProps {
frameworkName?: string;
serviceName: string;
}

export function ServiceMetricFetcher({
frameworkName,
serviceName
}: ServiceMetricFetcherProps) {
const {
Expand All @@ -37,5 +39,11 @@ export function ServiceMetricFetcher({
);
const isLoading = status === 'loading';

return <ServiceMetricList {...data} isLoading={isLoading} />;
return (
<ServiceMetricList
{...data}
frameworkName={frameworkName}
isLoading={isLoading}
/>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ function LoadingSpinner() {
);
}

const BadgeRow = styled(EuiFlexItem)`
padding-bottom: ${lightTheme.gutterTypes.gutterSmall};
`;

const ItemRow = styled('tr')`
line-height: 2;
`;
Expand All @@ -44,6 +48,7 @@ const ItemDescription = styled('td')`
`;

interface ServiceMetricListProps extends ServiceNodeMetrics {
frameworkName?: string;
isLoading: boolean;
}

Expand All @@ -53,6 +58,7 @@ export function ServiceMetricList({
avgErrorsPerMinute,
avgCpuUsage,
avgMemoryUsage,
frameworkName,
numInstances,
isLoading
}: ServiceMetricListProps) {
Expand Down Expand Up @@ -106,23 +112,27 @@ export function ServiceMetricList({
: null
}
];
const showBadgeRow = frameworkName || numInstances > 1;

return isLoading ? (
<LoadingSpinner />
) : (
<>
{numInstances && numInstances > 1 && (
<EuiFlexItem>
<div>
<EuiBadge iconType="apps" color="hollow">
{i18n.translate('xpack.apm.serviceMap.numInstancesMetric', {
values: { numInstances },
defaultMessage: '{numInstances} instances'
})}
</EuiBadge>
</div>
</EuiFlexItem>
{showBadgeRow && (
<BadgeRow>
<EuiFlexGroup gutterSize="none">
{frameworkName && <EuiBadge>{frameworkName}</EuiBadge>}
{numInstances > 1 && (
<EuiBadge iconType="apps" color="hollow">
{i18n.translate('xpack.apm.serviceMap.numInstancesMetric', {
values: { numInstances },
defaultMessage: '{numInstances} instances'
})}
</EuiBadge>
)}
</EuiFlexGroup>
</BadgeRow>
)}

<table>
<tbody>
{listItems.map(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,19 +42,23 @@ const style: cytoscape.Stylesheet[] = [
'background-image': (el: cytoscape.NodeSingular) =>
iconForNode(el) ?? defaultIcon,
'background-height': (el: cytoscape.NodeSingular) =>
isService(el) ? '85%' : '40%',
isService(el) ? '60%' : '40%',
'background-width': (el: cytoscape.NodeSingular) =>
isService(el) ? '85%' : '40%',
isService(el) ? '60%' : '40%',
'border-color': (el: cytoscape.NodeSingular) =>
el.hasClass('primary') || el.selected()
? theme.euiColorPrimary
: theme.euiColorMediumShade,
'border-width': 1,
'border-width': 2,
color: theme.textColors.default,
// theme.euiFontFamily doesn't work here for some reason, so we're just
// specifying a subset of the fonts for the label text.
'font-family': 'Inter UI, Segoe UI, Helvetica, Arial, sans-serif',
'font-size': theme.euiFontSizeXS,
ghost: 'yes',
'ghost-offset-x': 0,
'ghost-offset-y': 2,
'ghost-opacity': 0.15,
height: nodeHeight,
label: 'data(label)',
'min-zoomed-font-size': theme.euiSizeL,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,8 @@ export function getCytoscapeElements(
`/services/${node['service.name']}/service-map`,
search
),
agentName: node['agent.name'] || node['agent.name'],
agentName: node['agent.name'],
frameworkName: node['service.framework.name'],
type: 'service'
};
}
Expand Down
Loading

0 comments on commit 2378d8a

Please sign in to comment.