diff --git a/desktop/app/src/chrome/FpsGraph.tsx b/desktop/app/src/chrome/FpsGraph.tsx index ccdc711f8..39f6364c6 100644 --- a/desktop/app/src/chrome/FpsGraph.tsx +++ b/desktop/app/src/chrome/FpsGraph.tsx @@ -84,7 +84,12 @@ export default function FpsGraph({ return (
- +
); } diff --git a/desktop/app/src/chrome/NetworkGraph.tsx b/desktop/app/src/chrome/NetworkGraph.tsx new file mode 100644 index 000000000..be31bbf4d --- /dev/null +++ b/desktop/app/src/chrome/NetworkGraph.tsx @@ -0,0 +1,72 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + */ + +import React, {useEffect, useRef, useState} from 'react'; +import {onBytesReceived} from '../dispatcher/tracking'; + +export default function NetworkGraph({ + width, + height, +}: { + width: number; + height: number; +}) { + const canvasRef = useRef(null); + const lastTime = useRef(performance.now()); + const lastBytes = useRef(0); + const pluginStats = useRef>({}); + const [hoverText, setHoverText] = useState(''); + + useEffect(() => { + return onBytesReceived((plugin, bytes) => { + lastBytes.current += bytes; + if (!pluginStats.current[plugin]) { + pluginStats.current[plugin] = bytes; + } else { + pluginStats.current[plugin] += bytes; + } + }); + }, []); + + useEffect(() => { + const interval = setInterval(() => { + const deltaTime = performance.now() - lastTime.current; + lastTime.current = performance.now(); + const deltaBytes = lastBytes.current; + lastBytes.current = 0; + + // cause kiloBytesPerSecond === bytes per millisecond + const kiloBytesPerSecond = Math.round(deltaBytes / deltaTime); + + const ctx = canvasRef.current!.getContext('2d')!; + ctx.clearRect(0, 0, width, height); + ctx.strokeStyle = kiloBytesPerSecond >= 1000 ? '#f00' : '#ccc'; + ctx.textAlign = 'end'; + ctx.strokeText(`${kiloBytesPerSecond} kB/s`, width - 5, 5 + height / 2); + + setHoverText( + 'Total data traffic per plugin:\n\n' + + Object.entries(pluginStats.current) + .sort(([_p, bytes], [_p2, bytes2]) => bytes2 - bytes) + .map(([key, bytes]) => `${key}: ${Math.round(bytes / 1000)}kb`) + .join('\n'), + ); + }, 1000); + + return () => { + clearInterval(interval); + }; + }, []); + + return ( +
+ +
+ ); +} diff --git a/desktop/app/src/chrome/TitleBar.tsx b/desktop/app/src/chrome/TitleBar.tsx index 6de15fee3..5e2c4c9ae 100644 --- a/desktop/app/src/chrome/TitleBar.tsx +++ b/desktop/app/src/chrome/TitleBar.tsx @@ -45,6 +45,7 @@ import React from 'react'; import {State} from '../reducers'; import {reportUsage} from '../utils/metrics'; import FpsGraph from './FpsGraph'; +import NetworkGraph from './NetworkGraph'; import MetroButton from './MetroButton'; const AppTitleBar = styled(FlexRow)<{focused?: boolean}>(({focused}) => ({ @@ -167,6 +168,7 @@ class TitleBar extends React.Component { )} + {!isProduction() && } {!isProduction() && } {config.showFlipperRating ? : null}