mirror of https://github.com/jetkvm/kvm.git
Compare commits
5 Commits
3bd9f841e0
...
050d5d053c
Author | SHA1 | Date |
---|---|---|
|
050d5d053c | |
|
379a794bd7 | |
|
6b37cf8e3f | |
|
0340aa3749 | |
|
8a07f7d186 |
|
@ -1,3 +1,4 @@
|
||||||
|
/* eslint-disable react-refresh/only-export-components */
|
||||||
import { ComponentProps } from "react";
|
import { ComponentProps } from "react";
|
||||||
import { cva, cx } from "cva";
|
import { cva, cx } from "cva";
|
||||||
|
|
||||||
|
@ -28,7 +29,12 @@ interface MetricProps<T, K extends keyof T> {
|
||||||
badgeTheme?: ComponentProps<typeof MetricHeader>["badgeTheme"];
|
badgeTheme?: ComponentProps<typeof MetricHeader>["badgeTheme"];
|
||||||
}
|
}
|
||||||
|
|
||||||
/* eslint-disable-next-line */
|
/**
|
||||||
|
* Creates a chart array from a metrics map and a metric name.
|
||||||
|
*
|
||||||
|
* @param metrics - Expected to be ordered from oldest to newest.
|
||||||
|
* @param metricName - Name of the metric to create a chart array for.
|
||||||
|
*/
|
||||||
export function createChartArray<T, K extends keyof T>(
|
export function createChartArray<T, K extends keyof T>(
|
||||||
metrics: Map<number, T>,
|
metrics: Map<number, T>,
|
||||||
metricName: K,
|
metricName: K,
|
||||||
|
@ -36,12 +42,12 @@ export function createChartArray<T, K extends keyof T>(
|
||||||
const result: { date: number; metric: number | null }[] = [];
|
const result: { date: number; metric: number | null }[] = [];
|
||||||
const iter = metrics.entries();
|
const iter = metrics.entries();
|
||||||
let next = iter.next() as IteratorResult<[number, T]>;
|
let next = iter.next() as IteratorResult<[number, T]>;
|
||||||
const now = Math.floor(Date.now() / 1000);
|
const nowSeconds = Math.floor(Date.now() / 1000);
|
||||||
|
|
||||||
// We want 120 data points, in the chart.
|
// We want 120 data points, in the chart.
|
||||||
const firstDate = Math.min(next.value?.[0] ?? now, now - 120);
|
const firstDate = Math.min(next.value?.[0] ?? nowSeconds, nowSeconds - 120);
|
||||||
|
|
||||||
for (let t = firstDate; t < now; t++) {
|
for (let t = firstDate; t < nowSeconds; t++) {
|
||||||
while (!next.done && next.value[0] < t) next = iter.next();
|
while (!next.done && next.value[0] < t) next = iter.next();
|
||||||
const has = !next.done && next.value[0] === t;
|
const has = !next.done && next.value[0] === t;
|
||||||
|
|
||||||
|
@ -55,6 +61,18 @@ export function createChartArray<T, K extends keyof T>(
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function computeReferenceValue(points: ChartPoint[]): number | undefined {
|
||||||
|
const values = points
|
||||||
|
.filter(p => p.metric != null && Number.isFinite(p.metric))
|
||||||
|
.map(p => Number(p.metric));
|
||||||
|
|
||||||
|
if (values.length === 0) return undefined;
|
||||||
|
|
||||||
|
const sum = values.reduce((acc, v) => acc + v, 0);
|
||||||
|
const mean = sum / values.length;
|
||||||
|
return Math.round(mean);
|
||||||
|
}
|
||||||
|
|
||||||
const theme = {
|
const theme = {
|
||||||
light:
|
light:
|
||||||
"bg-white text-black border border-slate-800/20 dark:border dark:border-slate-700 dark:bg-slate-800 dark:text-slate-300",
|
"bg-white text-black border border-slate-800/20 dark:border dark:border-slate-700 dark:bg-slate-800 dark:text-slate-300",
|
||||||
|
@ -122,17 +140,9 @@ export function Metric<T, K extends keyof T>({
|
||||||
|
|
||||||
// If the consumer provides a map function, we apply it to the raw data.
|
// If the consumer provides a map function, we apply it to the raw data.
|
||||||
const dataFinal: ChartPoint[] = map ? raw.map(map) : raw;
|
const dataFinal: ChartPoint[] = map ? raw.map(map) : raw;
|
||||||
const recent = dataFinal
|
|
||||||
.slice(-(raw.length - 1))
|
|
||||||
.filter(x => x.metric != null) as ChartPoint[];
|
|
||||||
|
|
||||||
// Average the recent values
|
// Compute the average value of the metric.
|
||||||
const computedReferenceValue =
|
const referenceValue = computeReferenceValue(dataFinal);
|
||||||
recent.length > 0
|
|
||||||
? Math.round(
|
|
||||||
recent.reduce((sum, x) => sum + (x.metric as number), 0) / recent.length,
|
|
||||||
)
|
|
||||||
: undefined;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
|
@ -156,7 +166,7 @@ export function Metric<T, K extends keyof T>({
|
||||||
data={dataFinal}
|
data={dataFinal}
|
||||||
domain={domain}
|
domain={domain}
|
||||||
unit={unit}
|
unit={unit}
|
||||||
referenceValue={computedReferenceValue}
|
referenceValue={referenceValue}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<div className="flex flex-col items-center space-y-1">
|
<div className="flex flex-col items-center space-y-1">
|
||||||
|
|
|
@ -29,6 +29,10 @@ export default function ConnectionStatsSidebar() {
|
||||||
useInterval(function collectWebRTCStats() {
|
useInterval(function collectWebRTCStats() {
|
||||||
(async () => {
|
(async () => {
|
||||||
if (!mediaStream) return;
|
if (!mediaStream) return;
|
||||||
|
|
||||||
|
const videoTrack = mediaStream.getVideoTracks()[0];
|
||||||
|
if (!videoTrack) return;
|
||||||
|
|
||||||
const stats = await peerConnection?.getStats();
|
const stats = await peerConnection?.getStats();
|
||||||
let successfulLocalCandidateId: string | null = null;
|
let successfulLocalCandidateId: string | null = null;
|
||||||
let successfulRemoteCandidateId: string | null = null;
|
let successfulRemoteCandidateId: string | null = null;
|
||||||
|
@ -69,22 +73,22 @@ export default function ConnectionStatsSidebar() {
|
||||||
if (idx === 0) return { date: d.date, metric: null };
|
if (idx === 0) return { date: d.date, metric: null };
|
||||||
const prevDelay = jitterBufferDelay[idx - 1]?.metric as number | null | undefined;
|
const prevDelay = jitterBufferDelay[idx - 1]?.metric as number | null | undefined;
|
||||||
const currDelay = d.metric as number | null | undefined;
|
const currDelay = d.metric as number | null | undefined;
|
||||||
const prevEmitted =
|
const prevCountEmitted =
|
||||||
(jitterBufferEmittedCount[idx - 1]?.metric as number | null | undefined) ?? null;
|
(jitterBufferEmittedCount[idx - 1]?.metric as number | null | undefined) ?? null;
|
||||||
const currEmitted =
|
const currCountEmitted =
|
||||||
(jitterBufferEmittedCount[idx]?.metric as number | null | undefined) ?? null;
|
(jitterBufferEmittedCount[idx]?.metric as number | null | undefined) ?? null;
|
||||||
|
|
||||||
if (
|
if (
|
||||||
prevDelay == null ||
|
prevDelay == null ||
|
||||||
currDelay == null ||
|
currDelay == null ||
|
||||||
prevEmitted == null ||
|
prevCountEmitted == null ||
|
||||||
currEmitted == null
|
currCountEmitted == null
|
||||||
) {
|
) {
|
||||||
return { date: d.date, metric: null };
|
return { date: d.date, metric: null };
|
||||||
}
|
}
|
||||||
|
|
||||||
const deltaDelay = currDelay - prevDelay;
|
const deltaDelay = currDelay - prevDelay;
|
||||||
const deltaEmitted = currEmitted - prevEmitted;
|
const deltaEmitted = currCountEmitted - prevCountEmitted;
|
||||||
|
|
||||||
// Guard counter resets or no emitted frames
|
// Guard counter resets or no emitted frames
|
||||||
if (deltaDelay < 0 || deltaEmitted <= 0) {
|
if (deltaDelay < 0 || deltaEmitted <= 0) {
|
||||||
|
|
Loading…
Reference in New Issue