From 3a8a45abb804a51d19bc47131a039012521a8f97 Mon Sep 17 00:00:00 2001 From: Oliver Gupte Date: Tue, 1 Sep 2020 17:13:20 -0700 Subject: [PATCH 1/6] Fixes storybook anomaly score generation and better utilizes available screen space --- .../CytoscapeExampleData.stories.tsx | 38 ++++++++++++------- .../generate_service_map_elements.ts | 25 +++++++----- 2 files changed, 41 insertions(+), 22 deletions(-) diff --git a/x-pack/plugins/apm/public/components/app/ServiceMap/__stories__/CytoscapeExampleData.stories.tsx b/x-pack/plugins/apm/public/components/app/ServiceMap/__stories__/CytoscapeExampleData.stories.tsx index 830e3719b11f9..e38b35262197b 100644 --- a/x-pack/plugins/apm/public/components/app/ServiceMap/__stories__/CytoscapeExampleData.stories.tsx +++ b/x-pack/plugins/apm/public/components/app/ServiceMap/__stories__/CytoscapeExampleData.stories.tsx @@ -35,6 +35,9 @@ function setSessionJson(json: string) { window.sessionStorage.setItem(SESSION_STORAGE_KEY, json); } +const getCytoscapeWidth = () => window.innerWidth - 240; +const getCytoscapeHeight = () => window.innerHeight - 300; + storiesOf(STORYBOOK_PATH, module) .addDecorator((storyFn) => {storyFn()}) .add( @@ -43,16 +46,17 @@ storiesOf(STORYBOOK_PATH, module) const [size, setSize] = useState(10); const [json, setJson] = useState(''); const [elements, setElements] = useState( - generateServiceMapElements(size) + generateServiceMapElements({ size, hasAnomalies: true }) ); - return (
{ - setElements(generateServiceMapElements(size)); + setElements( + generateServiceMapElements({ size, hasAnomalies: true }) + ); setJson(''); }} > @@ -79,7 +83,11 @@ storiesOf(STORYBOOK_PATH, module) - + {json && ( - + @@ -204,8 +216,8 @@ storiesOf(STORYBOOK_PATH, module)
); @@ -224,8 +236,8 @@ storiesOf(STORYBOOK_PATH, module)
); @@ -244,8 +256,8 @@ storiesOf(STORYBOOK_PATH, module)
); @@ -264,8 +276,8 @@ storiesOf(STORYBOOK_PATH, module)
); diff --git a/x-pack/plugins/apm/public/components/app/ServiceMap/__stories__/generate_service_map_elements.ts b/x-pack/plugins/apm/public/components/app/ServiceMap/__stories__/generate_service_map_elements.ts index 012256db3ab98..57ef2d49291c4 100644 --- a/x-pack/plugins/apm/public/components/app/ServiceMap/__stories__/generate_service_map_elements.ts +++ b/x-pack/plugins/apm/public/components/app/ServiceMap/__stories__/generate_service_map_elements.ts @@ -4,9 +4,13 @@ * you may not use this file except in compliance with the Elastic License. */ -import { getSeverity } from '../Popover/getSeverity'; - -export function generateServiceMapElements(size: number): any[] { +export function generateServiceMapElements({ + size, + hasAnomalies, +}: { + size: number; + hasAnomalies: boolean; +}): any[] { const services = range(size).map((i) => { const name = getName(); const anomalyScore = randn(101); @@ -15,11 +19,14 @@ export function generateServiceMapElements(size: number): any[] { 'service.environment': 'production', 'service.name': name, 'agent.name': getAgentName(), - anomaly_score: anomalyScore, - anomaly_severity: getSeverity(anomalyScore), - actual_value: Math.random() * 2000000, - typical_value: Math.random() * 1000000, - ml_job_id: `${name}-request-high_mean_response_time`, + serviceAnomalyStats: hasAnomalies + ? { + transactionType: 'request', + anomalyScore, + actualValue: Math.random() * 2000000, + jobId: `${name}-request-high_mean_response_time`, + } + : undefined, }; }); @@ -146,7 +153,7 @@ const NAMES = [ 'leech', 'loki', 'longshot', - 'lumpkin,', + 'lumpkin', 'madame-web', 'magician', 'magneto', From 41214580a33cf8ebe66cb645f4dea3fe93ea9858 Mon Sep 17 00:00:00 2001 From: Oliver Gupte Date: Wed, 2 Sep 2020 01:58:14 -0700 Subject: [PATCH 2/6] Closes #71770 for APM service maps by replacing breadthfirst layout with one from the cytoscape-dagre extension. Also replaces the taxi edges with cubic bezier edges. Finally, this adds the ability to drag individual nodes around the service map. --- x-pack/package.json | 1 + .../components/app/ServiceMap/Cytoscape.tsx | 90 +++++++------------ .../app/ServiceMap/Popover/index.tsx | 2 + .../__stories__/Cytoscape.stories.tsx | 4 +- .../CytoscapeExampleData.stories.tsx | 17 +--- .../app/ServiceMap/cytoscapeOptions.ts | 6 +- .../components/app/ServiceMap/index.tsx | 3 +- .../plugins/apm/typings/cytoscape_dagre.d.ts | 7 ++ yarn.lock | 22 +++++ 9 files changed, 72 insertions(+), 80 deletions(-) create mode 100644 x-pack/plugins/apm/typings/cytoscape_dagre.d.ts diff --git a/x-pack/package.json b/x-pack/package.json index 0e9aef37aa253..bf093fed30747 100644 --- a/x-pack/package.json +++ b/x-pack/package.json @@ -305,6 +305,7 @@ "concat-stream": "1.6.2", "content-disposition": "0.5.3", "cytoscape": "^3.10.0", + "cytoscape-dagre": "^2.2.2", "d3-array": "1.2.4", "dedent": "^0.7.0", "del": "^5.1.0", diff --git a/x-pack/plugins/apm/public/components/app/ServiceMap/Cytoscape.tsx b/x-pack/plugins/apm/public/components/app/ServiceMap/Cytoscape.tsx index 1cde473aae6fa..1270b2d8d0e4e 100644 --- a/x-pack/plugins/apm/public/components/app/ServiceMap/Cytoscape.tsx +++ b/x-pack/plugins/apm/public/components/app/ServiceMap/Cytoscape.tsx @@ -13,6 +13,7 @@ import React, { useState, } from 'react'; import cytoscape from 'cytoscape'; +import dagre from 'cytoscape-dagre'; import { debounce } from 'lodash'; import { useTheme } from '../../../hooks/useTheme'; import { @@ -22,6 +23,8 @@ import { } from './cytoscapeOptions'; import { useUiTracker } from '../../../../../observability/public'; +cytoscape.use(dagre); + export const CytoscapeContext = createContext( undefined ); @@ -30,7 +33,6 @@ interface CytoscapeProps { children?: ReactNode; elements: cytoscape.ElementDefinition[]; height: number; - width: number; serviceName?: string; style?: CSSProperties; } @@ -57,59 +59,42 @@ function useCytoscape(options: cytoscape.CytoscapeOptions) { return [ref, cy] as [React.MutableRefObject, cytoscape.Core | undefined]; } -function rotatePoint( - { x, y }: { x: number; y: number }, - degreesRotated: number -) { - const radiansPerDegree = Math.PI / 180; - const θ = radiansPerDegree * degreesRotated; - const cosθ = Math.cos(θ); - const sinθ = Math.sin(θ); - return { - x: x * cosθ - y * sinθ, - y: x * sinθ + y * cosθ, - }; -} - -function getLayoutOptions( - selectedRoots: string[], - height: number, - width: number, - nodeHeight: number -): cytoscape.LayoutOptions { +function getLayoutOptions(nodeHeight: number): cytoscape.LayoutOptions { return { - name: 'breadthfirst', - // @ts-ignore DefinitelyTyped is incorrect here. Roots can be an Array - roots: selectedRoots.length ? selectedRoots : undefined, + name: 'dagre', fit: true, padding: nodeHeight, spacingFactor: 1.2, // @ts-ignore - // Rotate nodes counter-clockwise to transform layout from top→bottom to left→right. - // The extra 5° achieves the effect of separating overlapping taxi-styled edges. - transform: (node: any, pos: cytoscape.Position) => rotatePoint(pos, -95), - // swap width/height of boundingBox to compensate for the rotation - boundingBox: { x1: 0, y1: 0, w: height, h: width }, + nodeSep: nodeHeight, + edgeSep: 32, + rankSep: 128, + rankDir: 'LR', + ranker: 'network-simplex', }; } -function selectRoots(cy: cytoscape.Core): string[] { - const bfs = cy.elements().bfs({ - roots: cy.elements().leaves(), +function applyCubicBezierStyles(edges: cytoscape.EdgeCollection) { + edges.forEach((edge) => { + const { x: x0, y: y0 } = edge.source().position(); + const { x: x1, y: y1 } = edge.target().position(); + const x = x1 - x0; + const y = y1 - y0; + const z = Math.sqrt(x * x + y * y); + const costheta = z === 0 ? 0 : x / z; + const alpha = 0.25; + edge.style('control-point-distances', [ + -alpha * y * costheta, + alpha * y * costheta, + ]); + edge.style('control-point-weights', [alpha, 1 - alpha]); }); - const furthestNodeFromLeaves = bfs.path.last(); - return cy - .elements() - .roots() - .union(furthestNodeFromLeaves) - .map((el) => el.id()); } export function Cytoscape({ children, elements, height, - width, serviceName, style, }: CytoscapeProps) { @@ -151,13 +136,9 @@ export function Cytoscape({ } else { resetConnectedEdgeStyle(); } - - const selectedRoots = selectRoots(event.cy); - const layout = cy.layout( - getLayoutOptions(selectedRoots, height, width, nodeHeight) - ); - - layout.run(); + cy.layout(getLayoutOptions(nodeHeight)).run(); + cy.nodes().grabify(); + // cy.elements().panify(); } }; let layoutstopDelayTimeout: NodeJS.Timeout; @@ -180,6 +161,7 @@ export function Cytoscape({ event.cy.fit(undefined, nodeHeight); } }, 0); + applyCubicBezierStyles(event.cy.edges()); }; // debounce hover tracking so it doesn't spam telemetry with redundant events const trackNodeEdgeHover = debounce( @@ -211,6 +193,9 @@ export function Cytoscape({ console.debug('cytoscape:', event); } }; + const dragHandler: cytoscape.EventHandler = (event) => { + applyCubicBezierStyles(event.target.connectedEdges()); + }; if (cy) { cy.on('data layoutstop select unselect', debugHandler); @@ -220,6 +205,7 @@ export function Cytoscape({ cy.on('mouseout', 'edge, node', mouseoutHandler); cy.on('select', 'node', selectHandler); cy.on('unselect', 'node', unselectHandler); + cy.on('drag', 'node', dragHandler); cy.remove(cy.elements()); cy.add(elements); @@ -239,19 +225,11 @@ export function Cytoscape({ cy.removeListener('mouseout', 'edge, node', mouseoutHandler); cy.removeListener('select', 'node', selectHandler); cy.removeListener('unselect', 'node', unselectHandler); + cy.removeListener('drag', 'node', dragHandler); } clearTimeout(layoutstopDelayTimeout); }; - }, [ - cy, - elements, - height, - serviceName, - trackApmEvent, - width, - nodeHeight, - theme, - ]); + }, [cy, elements, height, serviceName, trackApmEvent, nodeHeight, theme]); return ( diff --git a/x-pack/plugins/apm/public/components/app/ServiceMap/Popover/index.tsx b/x-pack/plugins/apm/public/components/app/ServiceMap/Popover/index.tsx index 1658c36e8a92f..8291d94d91c48 100644 --- a/x-pack/plugins/apm/public/components/app/ServiceMap/Popover/index.tsx +++ b/x-pack/plugins/apm/public/components/app/ServiceMap/Popover/index.tsx @@ -71,6 +71,7 @@ export function Popover({ focusedServiceName }: PopoverProps) { cy.on('select', 'node', selectHandler); cy.on('unselect', 'node', deselect); cy.on('data viewport', deselect); + cy.on('drag', 'node', deselect); } return () => { @@ -78,6 +79,7 @@ export function Popover({ focusedServiceName }: PopoverProps) { cy.removeListener('select', 'node', selectHandler); cy.removeListener('unselect', 'node', deselect); cy.removeListener('data viewport', undefined, deselect); + cy.removeListener('drag', 'node', deselect); } }; }, [cy, deselect]); diff --git a/x-pack/plugins/apm/public/components/app/ServiceMap/__stories__/Cytoscape.stories.tsx b/x-pack/plugins/apm/public/components/app/ServiceMap/__stories__/Cytoscape.stories.tsx index 2a7d11bb57ca5..5b50eb953d896 100644 --- a/x-pack/plugins/apm/public/components/app/ServiceMap/__stories__/Cytoscape.stories.tsx +++ b/x-pack/plugins/apm/public/components/app/ServiceMap/__stories__/Cytoscape.stories.tsx @@ -49,13 +49,11 @@ storiesOf('app/ServiceMap/Cytoscape', module) }, ]; const height = 300; - const width = 1340; const serviceName = 'opbeans-python'; return ( ); @@ -330,7 +328,7 @@ storiesOf('app/ServiceMap/Cytoscape', module) }, }, ]; - return ; + return ; }, { info: { propTables: false, source: false }, diff --git a/x-pack/plugins/apm/public/components/app/ServiceMap/__stories__/CytoscapeExampleData.stories.tsx b/x-pack/plugins/apm/public/components/app/ServiceMap/__stories__/CytoscapeExampleData.stories.tsx index e38b35262197b..d8dcc71f5051d 100644 --- a/x-pack/plugins/apm/public/components/app/ServiceMap/__stories__/CytoscapeExampleData.stories.tsx +++ b/x-pack/plugins/apm/public/components/app/ServiceMap/__stories__/CytoscapeExampleData.stories.tsx @@ -35,7 +35,6 @@ function setSessionJson(json: string) { window.sessionStorage.setItem(SESSION_STORAGE_KEY, json); } -const getCytoscapeWidth = () => window.innerWidth - 240; const getCytoscapeHeight = () => window.innerHeight - 300; storiesOf(STORYBOOK_PATH, module) @@ -83,11 +82,7 @@ storiesOf(STORYBOOK_PATH, module)
- + {json && ( - + @@ -217,7 +208,6 @@ storiesOf(STORYBOOK_PATH, module)
); @@ -237,7 +227,6 @@ storiesOf(STORYBOOK_PATH, module) ); @@ -257,7 +246,6 @@ storiesOf(STORYBOOK_PATH, module) ); @@ -277,7 +265,6 @@ storiesOf(STORYBOOK_PATH, module) ); diff --git a/x-pack/plugins/apm/public/components/app/ServiceMap/cytoscapeOptions.ts b/x-pack/plugins/apm/public/components/app/ServiceMap/cytoscapeOptions.ts index 4a271019e06db..37ae42ce26b8f 100644 --- a/x-pack/plugins/apm/public/components/app/ServiceMap/cytoscapeOptions.ts +++ b/x-pack/plugins/apm/public/components/app/ServiceMap/cytoscapeOptions.ts @@ -168,9 +168,7 @@ const getStyle = (theme: EuiTheme): cytoscape.Stylesheet[] => { { selector: 'edge', style: { - 'curve-style': 'taxi', - // @ts-ignore - 'taxi-direction': 'auto', + 'curve-style': 'unbundled-bezier', 'line-color': lineColor, 'overlay-opacity': 0, 'target-arrow-color': lineColor, @@ -264,7 +262,7 @@ ${theme.eui.euiColorLightShade}`, export const getCytoscapeOptions = ( theme: EuiTheme ): cytoscape.CytoscapeOptions => ({ - autoungrabify: true, + // autoungrabify: true, boxSelectionEnabled: false, maxZoom: 3, minZoom: 0.2, diff --git a/x-pack/plugins/apm/public/components/app/ServiceMap/index.tsx b/x-pack/plugins/apm/public/components/app/ServiceMap/index.tsx index d4be4da2ae1c5..83fab95bc91c9 100644 --- a/x-pack/plugins/apm/public/components/app/ServiceMap/index.tsx +++ b/x-pack/plugins/apm/public/components/app/ServiceMap/index.tsx @@ -57,7 +57,7 @@ export function ServiceMap({ serviceName }: ServiceMapProps) { } }, [license, serviceName, urlParams]); - const { ref, height, width } = useRefDimensions(); + const { ref, height } = useRefDimensions(); useTrackPageview({ app: 'apm', path: 'service_map' }); useTrackPageview({ app: 'apm', path: 'service_map', delay: 15000 }); @@ -78,7 +78,6 @@ export function ServiceMap({ serviceName }: ServiceMapProps) { height={height} serviceName={serviceName} style={getCytoscapeDivStyle(theme)} - width={width} > diff --git a/x-pack/plugins/apm/typings/cytoscape_dagre.d.ts b/x-pack/plugins/apm/typings/cytoscape_dagre.d.ts new file mode 100644 index 0000000000000..b5bbdfc14d9d3 --- /dev/null +++ b/x-pack/plugins/apm/typings/cytoscape_dagre.d.ts @@ -0,0 +1,7 @@ +/* + * 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. + */ + +declare module 'cytoscape-dagre'; diff --git a/yarn.lock b/yarn.lock index 3be2599c64201..7b7e13692af86 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9997,6 +9997,13 @@ cypress@4.11.0: url "0.11.0" yauzl "2.10.0" +cytoscape-dagre@^2.2.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/cytoscape-dagre/-/cytoscape-dagre-2.2.2.tgz#5f32a85c0ba835f167efee531df9e89ac58ff411" + integrity sha512-zsg36qNwua/L2stJSWkcbSDcvW3E6VZf6KRe6aLnQJxuXuz89tMqI5EVYVKEcNBgzTEzFMFv0PE3T0nD4m6VDw== + dependencies: + dagre "^0.8.2" + cytoscape@^3.10.0: version "3.10.0" resolved "https://registry.yarnpkg.com/cytoscape/-/cytoscape-3.10.0.tgz#3b462e0d35121ecd2d2702f470915fd6dae01777" @@ -10209,6 +10216,14 @@ d@1: dependencies: es5-ext "^0.10.9" +dagre@^0.8.2: + version "0.8.5" + resolved "https://registry.yarnpkg.com/dagre/-/dagre-0.8.5.tgz#ba30b0055dac12b6c1fcc247817442777d06afee" + integrity sha512-/aTqmnRta7x7MCCpExk7HQL2O4owCT2h8NT//9I1OQ9vt29Pa0BzSAkR5lwFUcQ7491yVi/3CXU9jQ5o0Mn2Sw== + dependencies: + graphlib "^2.1.8" + lodash "^4.17.15" + damerau-levenshtein@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.4.tgz#03191c432cb6eea168bb77f3a55ffdccb8978514" @@ -14374,6 +14389,13 @@ graceful-fs@~1.1: resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-1.1.14.tgz#07078db5f6377f6321fceaaedf497de124dc9465" integrity sha1-BweNtfY3f2Mh/Oqu30l94STclGU= +graphlib@^2.1.8: + version "2.1.8" + resolved "https://registry.yarnpkg.com/graphlib/-/graphlib-2.1.8.tgz#5761d414737870084c92ec7b5dbcb0592c9d35da" + integrity sha512-jcLLfkpoVGmH7/InMC/1hIvOPSUh38oJtGhvrOFGzioE1DZ+0YW16RgmOJhHiuWTvGiJQ9Z1Ik43JvkRPRvE+A== + dependencies: + lodash "^4.17.15" + graphql-anywhere@^4.1.0-alpha.0: version "4.1.16" resolved "https://registry.yarnpkg.com/graphql-anywhere/-/graphql-anywhere-4.1.16.tgz#82bb59643e30183cfb7b485ed4262a7b39d8a6c1" From 0bfe1f10668c7bfc78478a7a7b91fe830b5c2c8e Mon Sep 17 00:00:00 2001 From: Oliver Gupte Date: Wed, 2 Sep 2020 02:09:23 -0700 Subject: [PATCH 3/6] Removes unused code --- .../plugins/apm/public/components/app/ServiceMap/Cytoscape.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/x-pack/plugins/apm/public/components/app/ServiceMap/Cytoscape.tsx b/x-pack/plugins/apm/public/components/app/ServiceMap/Cytoscape.tsx index 1270b2d8d0e4e..4af3a360e9fb4 100644 --- a/x-pack/plugins/apm/public/components/app/ServiceMap/Cytoscape.tsx +++ b/x-pack/plugins/apm/public/components/app/ServiceMap/Cytoscape.tsx @@ -137,8 +137,6 @@ export function Cytoscape({ resetConnectedEdgeStyle(); } cy.layout(getLayoutOptions(nodeHeight)).run(); - cy.nodes().grabify(); - // cy.elements().panify(); } }; let layoutstopDelayTimeout: NodeJS.Timeout; From cba22a864a5f48f220ddaaf9307a4c4d7da7d847 Mon Sep 17 00:00:00 2001 From: Oliver Gupte Date: Wed, 2 Sep 2020 02:11:34 -0700 Subject: [PATCH 4/6] removes commented line of code --- .../apm/public/components/app/ServiceMap/cytoscapeOptions.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/x-pack/plugins/apm/public/components/app/ServiceMap/cytoscapeOptions.ts b/x-pack/plugins/apm/public/components/app/ServiceMap/cytoscapeOptions.ts index 37ae42ce26b8f..9d58ed142dab7 100644 --- a/x-pack/plugins/apm/public/components/app/ServiceMap/cytoscapeOptions.ts +++ b/x-pack/plugins/apm/public/components/app/ServiceMap/cytoscapeOptions.ts @@ -262,7 +262,6 @@ ${theme.eui.euiColorLightShade}`, export const getCytoscapeOptions = ( theme: EuiTheme ): cytoscape.CytoscapeOptions => ({ - // autoungrabify: true, boxSelectionEnabled: false, maxZoom: 3, minZoom: 0.2, From 20daa20db7584483acc85a2b55162f3f53b7fc92 Mon Sep 17 00:00:00 2001 From: Oliver Gupte Date: Wed, 2 Sep 2020 14:36:21 -0700 Subject: [PATCH 5/6] - Adds ability for scripts/notice.js to check files with the .tsx file extension - Adds attribution for `applyCubicBezierStyles` --- NOTICE.txt | 7 +++++++ src/dev/notice/generate_notice_from_source.ts | 2 +- .../apm/public/components/app/ServiceMap/Cytoscape.tsx | 10 ++++++++++ 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/NOTICE.txt b/NOTICE.txt index e1552852d0349..e1f2d8b498215 100644 --- a/NOTICE.txt +++ b/NOTICE.txt @@ -281,6 +281,13 @@ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +--- +This product includes code in the function applyCubicBezierStyles that was +inspired by a public Codepen, which was available under a "MIT" license. + +Copyright (c) 2020 by Guillaume (https://codepen.io/guillaumethomas/pen/xxbbBKO) +MIT License http://www.opensource.org/licenses/mit-license.php + --- This product includes code that is adapted from mapbox-gl-js, which is available under a "BSD-3-Clause" license. diff --git a/src/dev/notice/generate_notice_from_source.ts b/src/dev/notice/generate_notice_from_source.ts index 0bef5bc5f32d4..9f7eb9d9e1aa4 100644 --- a/src/dev/notice/generate_notice_from_source.ts +++ b/src/dev/notice/generate_notice_from_source.ts @@ -41,7 +41,7 @@ interface Options { * into the repository. */ export async function generateNoticeFromSource({ productName, directory, log }: Options) { - const globs = ['**/*.{js,less,css,ts}']; + const globs = ['**/*.{js,less,css,ts,tsx}']; const options = { cwd: directory, diff --git a/x-pack/plugins/apm/public/components/app/ServiceMap/Cytoscape.tsx b/x-pack/plugins/apm/public/components/app/ServiceMap/Cytoscape.tsx index 4af3a360e9fb4..76ff046882f28 100644 --- a/x-pack/plugins/apm/public/components/app/ServiceMap/Cytoscape.tsx +++ b/x-pack/plugins/apm/public/components/app/ServiceMap/Cytoscape.tsx @@ -74,6 +74,14 @@ function getLayoutOptions(nodeHeight: number): cytoscape.LayoutOptions { }; } +/* + * @notice + * This product includes code in the function applyCubicBezierStyles that was + * inspired by a public Codepen, which was available under a "MIT" license. + * + * Copyright (c) 2020 by Guillaume (https://codepen.io/guillaumethomas/pen/xxbbBKO) + * MIT License http://www.opensource.org/licenses/mit-license.php + */ function applyCubicBezierStyles(edges: cytoscape.EdgeCollection) { edges.forEach((edge) => { const { x: x0, y: y0 } = edge.source().position(); @@ -83,6 +91,8 @@ function applyCubicBezierStyles(edges: cytoscape.EdgeCollection) { const z = Math.sqrt(x * x + y * y); const costheta = z === 0 ? 0 : x / z; const alpha = 0.25; + // Two values for control-point-distances represent a pair symmetric quadratic + // bezier curves joined to appear as a single cubic bezier curve: edge.style('control-point-distances', [ -alpha * y * costheta, alpha * y * costheta, From 39420aada1f3dc1785b8a9c9cf6ec020e312fa6d Mon Sep 17 00:00:00 2001 From: Oliver Gupte Date: Wed, 2 Sep 2020 17:01:13 -0700 Subject: [PATCH 6/6] Refine comment text and MIT license url --- NOTICE.txt | 2 +- .../apm/public/components/app/ServiceMap/Cytoscape.tsx | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/NOTICE.txt b/NOTICE.txt index e1f2d8b498215..d689abf4c4e05 100644 --- a/NOTICE.txt +++ b/NOTICE.txt @@ -286,7 +286,7 @@ This product includes code in the function applyCubicBezierStyles that was inspired by a public Codepen, which was available under a "MIT" license. Copyright (c) 2020 by Guillaume (https://codepen.io/guillaumethomas/pen/xxbbBKO) -MIT License http://www.opensource.org/licenses/mit-license.php +MIT License http://www.opensource.org/licenses/mit-license --- This product includes code that is adapted from mapbox-gl-js, which is diff --git a/x-pack/plugins/apm/public/components/app/ServiceMap/Cytoscape.tsx b/x-pack/plugins/apm/public/components/app/ServiceMap/Cytoscape.tsx index 76ff046882f28..0b00c8a8bf093 100644 --- a/x-pack/plugins/apm/public/components/app/ServiceMap/Cytoscape.tsx +++ b/x-pack/plugins/apm/public/components/app/ServiceMap/Cytoscape.tsx @@ -80,7 +80,7 @@ function getLayoutOptions(nodeHeight: number): cytoscape.LayoutOptions { * inspired by a public Codepen, which was available under a "MIT" license. * * Copyright (c) 2020 by Guillaume (https://codepen.io/guillaumethomas/pen/xxbbBKO) - * MIT License http://www.opensource.org/licenses/mit-license.php + * MIT License http://www.opensource.org/licenses/mit-license */ function applyCubicBezierStyles(edges: cytoscape.EdgeCollection) { edges.forEach((edge) => { @@ -92,7 +92,7 @@ function applyCubicBezierStyles(edges: cytoscape.EdgeCollection) { const costheta = z === 0 ? 0 : x / z; const alpha = 0.25; // Two values for control-point-distances represent a pair symmetric quadratic - // bezier curves joined to appear as a single cubic bezier curve: + // bezier curves joined in the middle as a seamless cubic bezier curve: edge.style('control-point-distances', [ -alpha * y * costheta, alpha * y * costheta,