327c2c4624
In BBB 3.0, a change was made to collect full WebRTC stats continuously. This method gathers stats from *all* peers and *all* senders and receivers every 2 seconds. Originally, it was intended to run only when the user opened the connection status dialog, providing in-depth info in the UI and making it available for copying. This new behavior is not ideal. Running full stats collection every 2 seconds in meetings with 20+ peers/transceivers wastes client resources since the collected data is unused 99% of the time. This commit reverts to the pre-3.0 behavior (≤2.7), where full stats collection (`startNetworkMonitoring`) runs only when the connection status modal is open. As a bonus, it fixes the packet loss status transition log to use the packet loss percentage, which is the actual trigger metric.
105 lines
3.2 KiB
JavaScript
Executable File
105 lines
3.2 KiB
JavaScript
Executable File
import { useEffect, useRef } from 'react';
|
|
import { useMutation } from '@apollo/client';
|
|
import { UPDATE_CONNECTION_ALIVE_AT } from './mutations';
|
|
import {
|
|
getStatus,
|
|
handleAudioStatsEvent,
|
|
} from '/imports/ui/components/connection-status/service';
|
|
import connectionStatus from '../../core/graphql/singletons/connectionStatus';
|
|
|
|
import getBaseUrl from '/imports/ui/core/utils/getBaseUrl';
|
|
import useCurrentUser from '../../core/hooks/useCurrentUser';
|
|
|
|
const ConnectionStatus = () => {
|
|
const STATS_INTERVAL = window.meetingClientSettings.public.stats.interval;
|
|
const networkRttInMs = useRef(0); // Ref to store the last rtt
|
|
const timeoutRef = useRef(null);
|
|
|
|
const [updateConnectionAliveAtM] = useMutation(UPDATE_CONNECTION_ALIVE_AT);
|
|
|
|
const {
|
|
data,
|
|
} = useCurrentUser((u) => ({
|
|
userId: u.userId,
|
|
avatar: u.avatar,
|
|
isModerator: u.isModerator,
|
|
color: u.color,
|
|
currentlyInMeeting: u.currentlyInMeeting,
|
|
}));
|
|
|
|
const handleUpdateConnectionAliveAt = () => {
|
|
const startTime = performance.now();
|
|
fetch(
|
|
`${getBaseUrl()}/ping`,
|
|
{ signal: AbortSignal.timeout(STATS_INTERVAL) },
|
|
)
|
|
.then((res) => {
|
|
if (res.ok && res.status === 200) {
|
|
const rttLevels = window.meetingClientSettings.public.stats.rtt;
|
|
const endTime = performance.now();
|
|
const networkRtt = Math.round(endTime - startTime);
|
|
networkRttInMs.current = networkRtt;
|
|
updateConnectionAliveAtM({
|
|
variables: {
|
|
networkRttInMs: networkRtt,
|
|
},
|
|
});
|
|
const rttStatus = getStatus(rttLevels, networkRtt);
|
|
connectionStatus.setRttValue(networkRtt);
|
|
connectionStatus.setRttStatus(rttStatus);
|
|
connectionStatus.setLastRttRequestSuccess(true);
|
|
|
|
if (Object.keys(rttLevels).includes(rttStatus)) {
|
|
connectionStatus.addUserNetworkHistory(
|
|
data,
|
|
rttStatus,
|
|
Date.now(),
|
|
);
|
|
}
|
|
}
|
|
})
|
|
.catch(() => {
|
|
connectionStatus.setLastRttRequestSuccess(false);
|
|
// gets the worst status
|
|
connectionStatus.setRttStatus('critical');
|
|
})
|
|
.finally(() => {
|
|
if (timeoutRef.current) {
|
|
clearTimeout(timeoutRef.current);
|
|
}
|
|
|
|
timeoutRef.current = setTimeout(() => {
|
|
handleUpdateConnectionAliveAt();
|
|
}, STATS_INTERVAL);
|
|
});
|
|
};
|
|
|
|
useEffect(() => {
|
|
// Delay first connectionAlive to avoid high RTT misestimation
|
|
// due to initial subscription and mutation traffic at client render
|
|
timeoutRef.current = setTimeout(() => {
|
|
handleUpdateConnectionAliveAt();
|
|
}, STATS_INTERVAL / 2);
|
|
|
|
const STATS_ENABLED = window.meetingClientSettings.public.stats.enabled;
|
|
|
|
if (STATS_ENABLED) {
|
|
// This will generate metrics usage to determine alert statuses based
|
|
// on WebRTC stats
|
|
window.addEventListener('audiostats', handleAudioStatsEvent);
|
|
}
|
|
|
|
return () => {
|
|
window.removeEventListener('audiostats', handleAudioStatsEvent);
|
|
|
|
if (timeoutRef.current) {
|
|
clearTimeout(timeoutRef.current);
|
|
}
|
|
};
|
|
}, []);
|
|
|
|
return null;
|
|
};
|
|
|
|
export default ConnectionStatus;
|