From bea70ecb13e5d51a0ffea2b29b85d55a6a71df5b Mon Sep 17 00:00:00 2001 From: Navaneeth Rao <32010211+navaneeth-dev@users.noreply.github.com> Date: Sat, 11 Jan 2025 11:15:30 +0530 Subject: [PATCH 1/9] Install recharts Signed-off-by: Navaneeth Rao <32010211+navaneeth-dev@users.noreply.github.com> --- package-lock.json | 241 +++++++++++++++++++++++++++++++- packages/jaeger-ui/package.json | 1 + 2 files changed, 239 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1fe9c4df9b..57801b798d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4417,23 +4417,48 @@ "@types/node": "*" } }, + "node_modules/@types/d3-array": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.1.tgz", + "integrity": "sha512-Y2Jn2idRrLzUfAKV2LyRImR+y4oa2AntrgID95SHJxuMUrkNXmanDSed71sRNZysveJVt1hLLemQZIady0FpEg==", + "license": "MIT" + }, "node_modules/@types/d3-color": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.3.tgz", "integrity": "sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==", - "dev": true, + "license": "MIT" + }, + "node_modules/@types/d3-ease": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-3.0.2.tgz", + "integrity": "sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==", "license": "MIT" }, "node_modules/@types/d3-interpolate": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz", "integrity": "sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==", - "dev": true, "license": "MIT", "dependencies": { "@types/d3-color": "*" } }, + "node_modules/@types/d3-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.1.0.tgz", + "integrity": "sha512-P2dlU/q51fkOc/Gfl3Ul9kicV7l+ra934qBFXCFhrZMOL6du1TM0pm1ThYvENukyOn5h9v+yMJ9Fn5JK4QozrQ==", + "license": "MIT" + }, + "node_modules/@types/d3-scale": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.8.tgz", + "integrity": "sha512-gkK1VVTr5iNiYJ7vWDI+yUFFlszhNMtVeneJ6lUTKPjprsvLLI9/tgEGiXJOnlINJA8FyA88gfnQsHbybVZrYQ==", + "license": "MIT", + "dependencies": { + "@types/d3-time": "*" + } + }, "node_modules/@types/d3-selection": { "version": "3.0.11", "resolved": "https://registry.npmjs.org/@types/d3-selection/-/d3-selection-3.0.11.tgz", @@ -4441,6 +4466,27 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/d3-shape": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.7.tgz", + "integrity": "sha512-VLvUQ33C+3J+8p+Daf+nYSOsjB4GXp19/S/aGo60m9h1v6XaxjiT82lKVWJCfzhtuZ3yD7i/TPeC/fuKLLOSmg==", + "license": "MIT", + "dependencies": { + "@types/d3-path": "*" + } + }, + "node_modules/@types/d3-time": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.4.tgz", + "integrity": "sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g==", + "license": "MIT" + }, + "node_modules/@types/d3-timer": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-3.0.2.tgz", + "integrity": "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==", + "license": "MIT" + }, "node_modules/@types/d3-zoom": { "version": "3.0.8", "resolved": "https://registry.npmjs.org/@types/d3-zoom/-/d3-zoom-3.0.8.tgz", @@ -6857,6 +6903,15 @@ "node": ">=6" } }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", @@ -7725,6 +7780,12 @@ "dev": true, "license": "MIT" }, + "node_modules/decimal.js-light": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/decimal.js-light/-/decimal.js-light-2.5.1.tgz", + "integrity": "sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg==", + "license": "MIT" + }, "node_modules/decode-uri-component": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.4.1.tgz", @@ -8177,6 +8238,16 @@ "utila": "~0.4" } }, + "node_modules/dom-helpers": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", + "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.8.7", + "csstype": "^3.0.2" + } + }, "node_modules/dom-scroll-into-view": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/dom-scroll-into-view/-/dom-scroll-into-view-1.2.1.tgz", @@ -9424,7 +9495,6 @@ "version": "4.0.7", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", - "dev": true, "license": "MIT" }, "node_modules/events": { @@ -9578,6 +9648,15 @@ "dev": true, "license": "MIT" }, + "node_modules/fast-equals": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/fast-equals/-/fast-equals-5.2.2.tgz", + "integrity": "sha512-V7/RktU11J3I36Nwq2JnZEM7tNm17eBJz+u25qdxBZeCKiX6BkVSZQjwWIr+IobgnZy+ag73tTZgZi7tr0LrBw==", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/fast-glob": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", @@ -11031,6 +11110,15 @@ "node": ">= 0.4" } }, + "node_modules/internmap": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", + "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, "node_modules/interpret": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/interpret/-/interpret-3.1.1.tgz", @@ -16465,6 +16553,21 @@ "react": "^16.3.0 || ^17.0.0 || ^18.0.0" } }, + "node_modules/react-smooth": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/react-smooth/-/react-smooth-4.0.4.tgz", + "integrity": "sha512-gnGKTpYwqL0Iii09gHobNolvX4Kiq4PKx6eWBCYYix+8cdw+cGo3do906l1NBPKkSWx1DghC1dlWG9L2uGd61Q==", + "license": "MIT", + "dependencies": { + "fast-equals": "^5.0.1", + "prop-types": "^15.8.1", + "react-transition-group": "^4.4.5" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, "node_modules/react-test-renderer": { "version": "18.3.1", "resolved": "https://registry.npmjs.org/react-test-renderer/-/react-test-renderer-18.3.1.tgz", @@ -16480,6 +16583,22 @@ "react": "^18.3.1" } }, + "node_modules/react-transition-group": { + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", + "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==", + "license": "BSD-3-Clause", + "dependencies": { + "@babel/runtime": "^7.5.5", + "dom-helpers": "^5.0.1", + "loose-envify": "^1.4.0", + "prop-types": "^15.6.2" + }, + "peerDependencies": { + "react": ">=16.6.0", + "react-dom": ">=16.6.0" + } + }, "node_modules/react-vis": { "version": "1.11.12", "resolved": "https://registry.npmjs.org/react-vis/-/react-vis-1.11.12.tgz", @@ -16639,6 +16758,38 @@ "node": ">=8.10.0" } }, + "node_modules/recharts": { + "version": "2.15.0", + "resolved": "https://registry.npmjs.org/recharts/-/recharts-2.15.0.tgz", + "integrity": "sha512-cIvMxDfpAmqAmVgc4yb7pgm/O1tmmkl/CjrvXuW+62/+7jj/iF9Ykm+hb/UJt42TREHMyd3gb+pkgoa2MxgDIw==", + "license": "MIT", + "dependencies": { + "clsx": "^2.0.0", + "eventemitter3": "^4.0.1", + "lodash": "^4.17.21", + "react-is": "^18.3.1", + "react-smooth": "^4.0.0", + "recharts-scale": "^0.4.4", + "tiny-invariant": "^1.3.1", + "victory-vendor": "^36.6.8" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "react": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/recharts-scale": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/recharts-scale/-/recharts-scale-0.4.5.tgz", + "integrity": "sha512-kivNFO+0OcUNu7jQquLXAxz1FIwZj8nrj+YkOKc5694NbjCvcT6aSZiIzNzd2Kul4o4rTto8QVR9lMNtxD4G1w==", + "license": "MIT", + "dependencies": { + "decimal.js-light": "^2.4.1" + } + }, "node_modules/rechoir": { "version": "0.8.0", "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz", @@ -19235,6 +19386,89 @@ "node": ">= 0.8" } }, + "node_modules/victory-vendor": { + "version": "36.9.2", + "resolved": "https://registry.npmjs.org/victory-vendor/-/victory-vendor-36.9.2.tgz", + "integrity": "sha512-PnpQQMuxlwYdocC8fIJqVXvkeViHYzotI+NJrCuav0ZYFoq912ZHBk3mCeuj+5/VpodOjPe1z0Fk2ihgzlXqjQ==", + "license": "MIT AND ISC", + "dependencies": { + "@types/d3-array": "^3.0.3", + "@types/d3-ease": "^3.0.0", + "@types/d3-interpolate": "^3.0.1", + "@types/d3-scale": "^4.0.2", + "@types/d3-shape": "^3.1.0", + "@types/d3-time": "^3.0.0", + "@types/d3-timer": "^3.0.0", + "d3-array": "^3.1.6", + "d3-ease": "^3.0.1", + "d3-interpolate": "^3.0.1", + "d3-scale": "^4.0.2", + "d3-shape": "^3.1.0", + "d3-time": "^3.0.0", + "d3-timer": "^3.0.1" + } + }, + "node_modules/victory-vendor/node_modules/d3-array": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz", + "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==", + "license": "ISC", + "dependencies": { + "internmap": "1 - 2" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/victory-vendor/node_modules/d3-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz", + "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/victory-vendor/node_modules/d3-scale": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", + "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", + "license": "ISC", + "dependencies": { + "d3-array": "2.10.0 - 3", + "d3-format": "1 - 3", + "d3-interpolate": "1.2.0 - 3", + "d3-time": "2.1.1 - 3", + "d3-time-format": "2 - 4" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/victory-vendor/node_modules/d3-shape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz", + "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==", + "license": "ISC", + "dependencies": { + "d3-path": "^3.1.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/victory-vendor/node_modules/d3-time": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz", + "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==", + "license": "ISC", + "dependencies": { + "d3-array": "2 - 3" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/w3c-xmlserializer": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz", @@ -20030,6 +20264,7 @@ "react-vis": "1.11.12", "react-vis-force": "^0.3.1", "react-window": "^1.8.10", + "recharts": "^2.15.0", "redux": "^5.0.1", "redux-actions": "2.6.5", "redux-first-history": "^5.2.0", diff --git a/packages/jaeger-ui/package.json b/packages/jaeger-ui/package.json index 156101b99b..35f222f388 100644 --- a/packages/jaeger-ui/package.json +++ b/packages/jaeger-ui/package.json @@ -82,6 +82,7 @@ "react-vis-force": "^0.3.1", "react-window": "^1.8.10", "redux": "^5.0.1", + "recharts": "^2.15.0", "redux-actions": "2.6.5", "redux-first-history": "^5.2.0", "redux-promise-middleware": "^6.1.3", From 28778a625df37c694a3588b878f4ee58ed228ed0 Mon Sep 17 00:00:00 2001 From: Navaneeth Rao <32010211+navaneeth-dev@users.noreply.github.com> Date: Tue, 7 Jan 2025 23:24:09 +0530 Subject: [PATCH 2/9] ScatterPlot replace with recharts - Equal interval - Proper Label position Signed-off-by: Navaneeth Rao <32010211+navaneeth-dev@users.noreply.github.com> --- .../SearchResults/ScatterPlot.jsx | 98 ++++++++++++------- 1 file changed, 65 insertions(+), 33 deletions(-) diff --git a/packages/jaeger-ui/src/components/SearchTracePage/SearchResults/ScatterPlot.jsx b/packages/jaeger-ui/src/components/SearchTracePage/SearchResults/ScatterPlot.jsx index a28e6453d5..10a661bdfa 100644 --- a/packages/jaeger-ui/src/components/SearchTracePage/SearchResults/ScatterPlot.jsx +++ b/packages/jaeger-ui/src/components/SearchTracePage/SearchResults/ScatterPlot.jsx @@ -15,28 +15,34 @@ import React, { useRef, useState, useLayoutEffect } from 'react'; import dayjs from 'dayjs'; import PropTypes from 'prop-types'; -import { XYPlot, XAxis, YAxis, MarkSeries, Hint } from 'react-vis'; +import { ScatterChart, XAxis, YAxis, ZAxis, Scatter, Tooltip, ResponsiveContainer, Cell, Label } from 'recharts'; import { FALLBACK_TRACE_NAME } from '../../../constants'; import { ONE_MILLISECOND, formatDuration } from '../../../utils/date'; -import 'react-vis/dist/style.css'; import './ScatterPlot.css'; +export const CustomTooltip = ({ overValue }) => { + if (overValue) { + return

{overValue.current?.name || FALLBACK_TRACE_NAME}

; + } + return null; +}; + export default function ScatterPlot(props) { const { data, onValueClick, calculateContainerWidth } = props; const containerRef = useRef(null); const [containerWidth, setContainerWidth] = useState(0); - const [overValue, setValueOver] = useState(null); + const overValue = useRef(); const onValueOver = value => { - setValueOver(value); + overValue.current = value; }; const onValueOut = () => { - setValueOver(null); + overValue.current = null; }; useLayoutEffect(() => { @@ -54,37 +60,63 @@ export default function ScatterPlot(props) { return () => window.removeEventListener('resize', updateContainerWidth); }, []); + function generateTicks() { + const start = data[data.length - 1].x; + const end = data[0].x; + + const step = (end - start) / 3; // Divide range into 3 equal steps + return [start, start + step, start + 2 * step, end]; + } + return (
{containerWidth && ( - - dayjs(t / ONE_MILLISECOND).format('hh:mm:ss a')} - /> - formatDuration(t)} /> - - {overValue && ( - -

{overValue.name || FALLBACK_TRACE_NAME}

-
- )} -
+ + + + {data.map(entry => ( + + ))} + + + dayjs(t / ONE_MILLISECOND).format('hh:mm:ss a')} + fontSize="11px" + tickLine={{ stroke: '#e6e6e9', strokeWidth: 2 }} + axisLine={{ stroke: '#e6e6e9', strokeWidth: 2 }} + scale="time" + ticks={generateTicks()} + interval={0} + allowDataOverflow={true} + > + + formatDuration(t)} + fontSize="11px" + tickLine={{ stroke: '#e6e6e9', strokeWidth: 2 }} + axisLine={{ stroke: '#e6e6e9', strokeWidth: 2 }} + > + + + + } + /> + + )}
); From 980720fb4a4eb7fada8acbb72f8472d4992f8a0b Mon Sep 17 00:00:00 2001 From: Navaneeth Rao <32010211+navaneeth-dev@users.noreply.github.com> Date: Wed, 8 Jan 2025 09:55:06 +0530 Subject: [PATCH 3/9] Remove defaultProps to fix deprecation warning Signed-off-by: Navaneeth Rao <32010211+navaneeth-dev@users.noreply.github.com> --- .../SearchTracePage/SearchResults/ScatterPlot.jsx | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/packages/jaeger-ui/src/components/SearchTracePage/SearchResults/ScatterPlot.jsx b/packages/jaeger-ui/src/components/SearchTracePage/SearchResults/ScatterPlot.jsx index 10a661bdfa..5f42030264 100644 --- a/packages/jaeger-ui/src/components/SearchTracePage/SearchResults/ScatterPlot.jsx +++ b/packages/jaeger-ui/src/components/SearchTracePage/SearchResults/ScatterPlot.jsx @@ -30,7 +30,7 @@ export const CustomTooltip = ({ overValue }) => { }; export default function ScatterPlot(props) { - const { data, onValueClick, calculateContainerWidth } = props; + const { data, onValueClick, calculateContainerWidth = container => container.clientWidth } = props; const containerRef = useRef(null); const [containerWidth, setContainerWidth] = useState(0); @@ -135,8 +135,3 @@ ScatterPlot.propTypes = { onValueClick: PropTypes.func.isRequired, calculateContainerWidth: PropTypes.func, }; - -ScatterPlot.defaultProps = { - // JSDOM does not, as of 2023, have a layout engine, so allow tests to supply a mock width as a workaround. - calculateContainerWidth: container => container.clientWidth, -}; From 6213c70a746f1d8714756f4cdb5290e828292eb9 Mon Sep 17 00:00:00 2001 From: Navaneeth Rao <32010211+navaneeth-dev@users.noreply.github.com> Date: Sat, 25 Jan 2025 12:29:38 +0530 Subject: [PATCH 4/9] Update serviceGraph to recharts Signed-off-by: Navaneeth Rao <32010211+navaneeth-dev@users.noreply.github.com> --- .../components/Monitor/ServicesView/index.tsx | 12 +- .../Monitor/ServicesView/serviceGraph.tsx | 247 +++++++++++------- 2 files changed, 156 insertions(+), 103 deletions(-) diff --git a/packages/jaeger-ui/src/components/Monitor/ServicesView/index.tsx b/packages/jaeger-ui/src/components/Monitor/ServicesView/index.tsx index 0eb888ad06..a2235a1eef 100644 --- a/packages/jaeger-ui/src/components/Monitor/ServicesView/index.tsx +++ b/packages/jaeger-ui/src/components/Monitor/ServicesView/index.tsx @@ -127,8 +127,10 @@ const calcDisplayTimeUnit = (serviceLatencies: ServiceMetricsObject | ServiceMet }; // export for tests -export const yAxisTickFormat = (timeInMS: number, displayTimeUnit: string) => - convertToTimeUnit(timeInMS * 1000, displayTimeUnit); +export const yAxisTickFormat = (timeInMS: number, displayTimeUnit: string): string => { + const formattedValue = convertToTimeUnit(timeInMS * 1000, displayTimeUnit); + return formattedValue.toString(); +} const convertServiceErrorRateToPercentages = (serviceErrorRate: null | ServiceMetricsObject) => { if (!serviceErrorRate) return null; @@ -332,10 +334,8 @@ export class MonitorATMServicesViewImpl extends React.PureComponent number; + yAxisTickFormat?: (v: number) => string; xDomain: number[]; }; @@ -59,6 +59,36 @@ export const tickFormat = (v: number) => { return `${hours.length === 1 ? `0${hours}` : hours}:${minutes.length === 1 ? `0${minutes}` : minutes}`; }; +type TPlaceholder = { + name: string; + marginClassName?: string; + width: number; + height: number; + children: string | React.ReactNode; +}; + +const Placeholder = ({ name, marginClassName, width, height, children }: TPlaceholder) => { + return ( +
+

{name}

+
+ {children} +
+
+ ); +}; + // export for tests export class ServiceGraphImpl extends React.PureComponent { height = 242; @@ -78,6 +108,23 @@ export class ServiceGraphImpl extends React.PureComponent { return Array.isArray(metricsData) ? metricsData : [metricsData]; } + getMetricsData(): number[] { + const serviceMetricObjects = this.getData(); + // Create data array for recharts with length of the first metricPoint + let result = Array(serviceMetricObjects[0].metricPoints.length); + // Loop through len and create array objects of data + for (let i = 0; i < serviceMetricObjects[0].metricPoints.length; i++) { + result[i] = { + x: serviceMetricObjects[0].metricPoints[i].x, + ...serviceMetricObjects.reduce((acc: Record, obj) => { + acc[obj.quantile.toString()] = obj.metricPoints[i].y ?? 0; + return acc; + }, {}), + }; + } + return result; + } + renderLines() { const { metricsData, color } = this.props; @@ -87,28 +134,14 @@ export class ServiceGraphImpl extends React.PureComponent { this.getData().forEach((line: ServiceMetricsObject, idx: number) => { graphs.push( - d.y !== null} - onNearestX={(_datapoint: Points, { index }: { index: number }) => { - this.setState({ - crosshairValues: this.getData().map((d: ServiceMetricsObject) => ({ - ...d.metricPoints[index], - label: d.quantile, - })), - }); - }} - opacity={0.1} - color={[color || this.colors[idx]]} - /> - ); - graphs.push( - d.y !== null} + ); }); @@ -149,74 +182,94 @@ export class ServiceGraphImpl extends React.PureComponent { yAxisTickFormat, xDomain, } = this.props; - let GraphComponent = this.generatePlaceholder(); - const noDataComponent = this.generatePlaceholder('No Data'); - const apiErrorComponent = this.generatePlaceholder('Couldn’t fetch data'); - - const Plot = ( - this.setState({ crosshairValues: [] })} + + if (loading || xDomain.length === 0) + return - {showHorizontalLines ? : null} - - - {this.renderLines()} - -
- {this.state.crosshairValues[0] && - `${new Date(this.state.crosshairValues[0].x).toLocaleDateString()} ${new Date( - this.state.crosshairValues[0].x - ).toLocaleTimeString()}`} - {this.state.crosshairValues.reverse().map((d: TCrossHairValues) => - showLegend ? ( -
- P{d.label * 100}: {d.y} -
- ) : ( -
{d.y}
- ) - )} -
-
- {showLegend ? ( - ({ - color: this.colors[idx], - title: `${d.quantile * 100}th`, - })) - .reverse()} - /> - ) : null} -
- ); + height={this.height}> + + ; - if (!loading && xDomain.length > 0) { - GraphComponent = metricsData === null ? noDataComponent : Plot; - } + if (error) + return + Couldn't fetch data + ; - if (error) { - GraphComponent = apiErrorComponent; - } + if (metricsData === null) + return + No Data + ; - return ( -
-

{name}

- {GraphComponent} -
- ); + return + + + + + + + {this.renderLines()} + + { + return new Date(value).toLocaleString() + }} + formatter={(value: number, name: string, props: any) => { + if (!showLegend) { + return [value]; + } + + const formattedName = Number(name) * 100; + return [value, `P${formattedName}`]; + }} /> + + {showLegend && ( + { + const dataVal = this.getData(); + const idx = dataVal.length - index - 1; + return {dataVal[idx].quantile * 100}th; + }} + /> + )} + + + ; } } From edfc34fe26a76624c95237bfff2ce4375502676e Mon Sep 17 00:00:00 2001 From: Navaneeth Rao <32010211+navaneeth-dev@users.noreply.github.com> Date: Sat, 25 Jan 2025 17:43:58 +0530 Subject: [PATCH 5/9] Fixed xAxis time order Signed-off-by: Navaneeth Rao <32010211+navaneeth-dev@users.noreply.github.com> --- .../src/components/Monitor/ServicesView/serviceGraph.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/jaeger-ui/src/components/Monitor/ServicesView/serviceGraph.tsx b/packages/jaeger-ui/src/components/Monitor/ServicesView/serviceGraph.tsx index c49c4c4eef..e481fb5e53 100644 --- a/packages/jaeger-ui/src/components/Monitor/ServicesView/serviceGraph.tsx +++ b/packages/jaeger-ui/src/components/Monitor/ServicesView/serviceGraph.tsx @@ -136,7 +136,7 @@ export class ServiceGraphImpl extends React.PureComponent { graphs.push( { tickLine={{ stroke: '#e6e6e9', strokeWidth: 2 }} axisLine={{ stroke: '#e6e6e9', strokeWidth: 2 }} height={30} - reversed /> + /> Date: Sat, 25 Jan 2025 17:44:18 +0530 Subject: [PATCH 6/9] Updated opsGraph to recharts Signed-off-by: Navaneeth Rao <32010211+navaneeth-dev@users.noreply.github.com> --- .../operationDetailsTable/opsGraph.tsx | 43 +++++++------------ 1 file changed, 16 insertions(+), 27 deletions(-) diff --git a/packages/jaeger-ui/src/components/Monitor/ServicesView/operationDetailsTable/opsGraph.tsx b/packages/jaeger-ui/src/components/Monitor/ServicesView/operationDetailsTable/opsGraph.tsx index 08e1cc2ac1..91be16a509 100644 --- a/packages/jaeger-ui/src/components/Monitor/ServicesView/operationDetailsTable/opsGraph.tsx +++ b/packages/jaeger-ui/src/components/Monitor/ServicesView/operationDetailsTable/opsGraph.tsx @@ -13,12 +13,7 @@ // limitations under the License. import * as React from 'react'; -import { - XYPlot, - AreaSeries, - LineSeries, - // @ts-ignore -} from 'react-vis'; +import { AreaChart, Area, ResponsiveContainer, YAxis } from 'recharts'; import { ApiError } from '../../../../types/api-error'; import { Points } from '../../../../types/metrics'; @@ -51,34 +46,28 @@ export class OperationsGraph extends React.PureComponent { } const dynProps: { - yDomain?: yDomain; + domain?: yDomain; } = {}; if (yDomain) { - dynProps.yDomain = yDomain; + dynProps.domain = yDomain; } return (
- - - - + + + + + +
); } From de87ba7e86360e7696d074dd33ec8f7a98e5511a Mon Sep 17 00:00:00 2001 From: Navaneeth Rao <32010211+navaneeth-dev@users.noreply.github.com> Date: Sun, 26 Jan 2025 10:20:48 +0530 Subject: [PATCH 7/9] Revert formatter change for ServicesView/index.tsx Signed-off-by: Navaneeth Rao <32010211+navaneeth-dev@users.noreply.github.com> --- .../jaeger-ui/src/components/Monitor/ServicesView/index.tsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/jaeger-ui/src/components/Monitor/ServicesView/index.tsx b/packages/jaeger-ui/src/components/Monitor/ServicesView/index.tsx index a2235a1eef..baad6359b7 100644 --- a/packages/jaeger-ui/src/components/Monitor/ServicesView/index.tsx +++ b/packages/jaeger-ui/src/components/Monitor/ServicesView/index.tsx @@ -334,8 +334,10 @@ export class MonitorATMServicesViewImpl extends React.PureComponent Date: Sun, 26 Jan 2025 10:32:50 +0530 Subject: [PATCH 8/9] Remove unnecessary useRef code in ScatterPlot Signed-off-by: Navaneeth Rao <32010211+navaneeth-dev@users.noreply.github.com> --- .../SearchResults/ScatterPlot.jsx | 21 ++++--------------- 1 file changed, 4 insertions(+), 17 deletions(-) diff --git a/packages/jaeger-ui/src/components/SearchTracePage/SearchResults/ScatterPlot.jsx b/packages/jaeger-ui/src/components/SearchTracePage/SearchResults/ScatterPlot.jsx index 5f42030264..b6c003da6c 100644 --- a/packages/jaeger-ui/src/components/SearchTracePage/SearchResults/ScatterPlot.jsx +++ b/packages/jaeger-ui/src/components/SearchTracePage/SearchResults/ScatterPlot.jsx @@ -22,11 +22,10 @@ import { ONE_MILLISECOND, formatDuration } from '../../../utils/date'; import './ScatterPlot.css'; -export const CustomTooltip = ({ overValue }) => { - if (overValue) { - return

{overValue.current?.name || FALLBACK_TRACE_NAME}

; +const CustomTooltip = ({ active, payload }) => { + if (active && payload && payload.length) { + return

{payload[0].payload.name || FALLBACK_TRACE_NAME}

; } - return null; }; export default function ScatterPlot(props) { @@ -35,16 +34,6 @@ export default function ScatterPlot(props) { const containerRef = useRef(null); const [containerWidth, setContainerWidth] = useState(0); - const overValue = useRef(); - - const onValueOver = value => { - overValue.current = value; - }; - - const onValueOut = () => { - overValue.current = null; - }; - useLayoutEffect(() => { function updateContainerWidth() { if (containerRef.current) { @@ -77,8 +66,6 @@ export default function ScatterPlot(props) { data={data} fillOpacity={0.5} onClick={onValueClick} - onMouseOver={onValueOver} - onMouseOut={onValueOut} > {data.map(entry => ( @@ -113,7 +100,7 @@ export default function ScatterPlot(props) { } + content={} /> From d8e85eb2fc6d457498cff81f6e8c9c8b450396cb Mon Sep 17 00:00:00 2001 From: Navaneeth Rao <32010211+navaneeth-dev@users.noreply.github.com> Date: Sun, 26 Jan 2025 10:45:07 +0530 Subject: [PATCH 9/9] Added pointer cursor to ScatterPlot circles Signed-off-by: Navaneeth Rao <32010211+navaneeth-dev@users.noreply.github.com> --- .../components/SearchTracePage/SearchResults/ScatterPlot.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/jaeger-ui/src/components/SearchTracePage/SearchResults/ScatterPlot.jsx b/packages/jaeger-ui/src/components/SearchTracePage/SearchResults/ScatterPlot.jsx index b6c003da6c..6ed476efb4 100644 --- a/packages/jaeger-ui/src/components/SearchTracePage/SearchResults/ScatterPlot.jsx +++ b/packages/jaeger-ui/src/components/SearchTracePage/SearchResults/ScatterPlot.jsx @@ -68,7 +68,7 @@ export default function ScatterPlot(props) { onClick={onValueClick} > {data.map(entry => ( - + ))}