Skip to content

Commit 7f6edcd

Browse files
samfreundmcm001Gold856
authored
feat: add metrics publisher for NT (#1791)
Publishes metrics to NT using a protobuf under `photonvision/coprocessors/metrics` using the device host name as the key. Refactors metrics to use numbers where possible, instead of strings. Removes GPU mem display from metrics card when it can't be determined. Updates UI metrics periodically. Resolves #1988 Closes #830 --------- Co-authored-by: Matt <[email protected]> Co-authored-by: Gold856 <[email protected]>
1 parent d7e536d commit 7f6edcd

File tree

15 files changed

+381
-115
lines changed

15 files changed

+381
-115
lines changed

photon-client/src/components/settings/MetricsCard.vue

Lines changed: 42 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -39,48 +39,69 @@ const generalMetrics = computed<MetricItem[]>(() => {
3939
return stats;
4040
});
4141
42+
// @ts-expect-error This uses Intl.DurationFormat which is newly implemented and not available in TS.
43+
const durationFormatter = new Intl.DurationFormat("en", { style: "narrow" });
4244
const platformMetrics = computed<MetricItem[]>(() => {
45+
const metrics = useSettingsStore().metrics;
4346
const stats = [
4447
{
4548
header: "CPU Temp",
46-
value: useSettingsStore().metrics.cpuTemp === undefined ? "Unknown" : `${useSettingsStore().metrics.cpuTemp}°C`
49+
value: metrics.cpuTemp === undefined || metrics.cpuTemp == -1 ? "Unknown" : `${metrics.cpuTemp}°C`
4750
},
4851
{
4952
header: "CPU Usage",
50-
value: useSettingsStore().metrics.cpuUtil === undefined ? "Unknown" : `${useSettingsStore().metrics.cpuUtil}%`
53+
value: metrics.cpuUtil === undefined ? "Unknown" : `${metrics.cpuUtil}%`
5154
},
5255
{
5356
header: "CPU Memory Usage",
5457
value:
55-
useSettingsStore().metrics.ramUtil === undefined || useSettingsStore().metrics.cpuMem === undefined
56-
? "Unknown"
57-
: `${useSettingsStore().metrics.ramUtil || "Unknown"}MB of ${useSettingsStore().metrics.cpuMem}MB`
58+
metrics.ramUtil && metrics.ramMem && metrics.ramUtil >= 0 && metrics.ramMem >= 0
59+
? `${metrics.ramUtil}MB of ${metrics.ramMem}MB`
60+
: "Unknown"
5861
},
5962
{
60-
header: "GPU Memory Usage",
61-
value:
62-
useSettingsStore().metrics.gpuMemUtil === undefined || useSettingsStore().metrics.gpuMem === undefined
63-
? "Unknown"
64-
: `${useSettingsStore().metrics.gpuMemUtil}MB of ${useSettingsStore().metrics.gpuMem}MB`
65-
},
66-
{
67-
header: "CPU Throttling",
68-
value: useSettingsStore().metrics.cpuThr || "Unknown"
69-
},
70-
{
71-
header: "CPU Uptime",
72-
value: useSettingsStore().metrics.cpuUptime || "Unknown"
63+
header: "Uptime",
64+
value: (() => {
65+
const seconds = metrics.uptime;
66+
if (seconds === undefined) return "Unknown";
67+
68+
const days = Math.floor(seconds / 86400);
69+
const hours = Math.floor((seconds % 86400) / 3600);
70+
const minutes = Math.floor((seconds % 3600) / 60);
71+
const secs = Math.floor(seconds % 60);
72+
73+
return durationFormatter.format({
74+
days: days,
75+
hours: hours,
76+
minutes: minutes,
77+
seconds: secs
78+
});
79+
})()
7380
},
7481
{
7582
header: "Disk Usage",
76-
value: useSettingsStore().metrics.diskUtilPct || "Unknown"
83+
value: metrics.diskUtilPct === undefined ? "Unknown" : `${metrics.diskUtilPct}%`
7784
}
7885
];
7986
80-
if (useSettingsStore().metrics.npuUsage) {
87+
if (metrics.npuUsage && metrics.npuUsage.length > 0) {
8188
stats.push({
8289
header: "NPU Usage",
83-
value: useSettingsStore().metrics.npuUsage || "Unknown"
90+
value: metrics.npuUsage?.map((usage, index) => `Core${index} ${usage}%`).join(", ") || "Unknown"
91+
});
92+
}
93+
94+
if (metrics.gpuMem && metrics.gpuMemUtil && metrics.gpuMem > 0 && metrics.gpuMemUtil > 0) {
95+
stats.push({
96+
header: "GPU Memory Usage",
97+
value: `${metrics.gpuMemUtil}MB of ${metrics.gpuMem}MB`
98+
});
99+
}
100+
101+
if (metrics.cpuThr) {
102+
stats.push({
103+
header: "CPU Throttling",
104+
value: metrics.cpuThr.toString()
84105
});
85106
}
86107

photon-client/src/stores/settings/GeneralSettingsStore.ts

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -56,15 +56,15 @@ export const useSettingsStore = defineStore("settings", {
5656
metrics: {
5757
cpuTemp: undefined,
5858
cpuUtil: undefined,
59-
cpuMem: undefined,
60-
gpuMem: undefined,
59+
cpuThr: undefined,
60+
ramMem: undefined,
6161
ramUtil: undefined,
62+
gpuMem: undefined,
6263
gpuMemUtil: undefined,
63-
cpuThr: undefined,
64-
cpuUptime: undefined,
6564
diskUtilPct: undefined,
6665
npuUsage: undefined,
67-
ipAddress: undefined
66+
ipAddress: undefined,
67+
uptime: undefined
6868
},
6969
currentFieldLayout: {
7070
field: {
@@ -90,15 +90,15 @@ export const useSettingsStore = defineStore("settings", {
9090
this.metrics = {
9191
cpuTemp: data.cpuTemp || undefined,
9292
cpuUtil: data.cpuUtil || undefined,
93-
cpuMem: data.cpuMem || undefined,
94-
gpuMem: data.gpuMem || undefined,
93+
cpuThr: data.cpuThr || undefined,
94+
ramMem: data.ramMem || undefined,
9595
ramUtil: data.ramUtil || undefined,
96+
gpuMem: data.gpuMem || undefined,
9697
gpuMemUtil: data.gpuMemUtil || undefined,
97-
cpuThr: data.cpuThr || undefined,
98-
cpuUptime: data.cpuUptime || undefined,
9998
diskUtilPct: data.diskUtilPct || undefined,
10099
npuUsage: data.npuUsage || undefined,
101-
ipAddress: data.ipAddress || undefined
100+
ipAddress: data.ipAddress || undefined,
101+
uptime: data.uptime || undefined
102102
};
103103
},
104104
updateGeneralSettingsFromWebsocket(data: WebsocketSettingsUpdate) {

photon-client/src/types/SettingTypes.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,17 +25,17 @@ export interface ObjectDetectionModelProperties {
2525
}
2626

2727
export interface MetricData {
28-
cpuTemp?: string;
29-
cpuUtil?: string;
30-
cpuMem?: string;
31-
gpuMem?: string;
32-
ramUtil?: string;
33-
gpuMemUtil?: string;
28+
cpuTemp?: number;
29+
cpuUtil?: number;
3430
cpuThr?: string;
35-
cpuUptime?: string;
36-
diskUtilPct?: string;
37-
npuUsage?: string;
31+
ramMem?: number;
32+
ramUtil?: number;
33+
gpuMem?: number;
34+
gpuMemUtil?: number;
35+
diskUtilPct?: number;
36+
npuUsage?: number[];
3837
ipAddress?: string;
38+
uptime?: number;
3939
}
4040

4141
export enum NetworkConnectionType {

photon-core/src/main/java/org/photonvision/common/dataflow/networktables/NetworkTablesManager.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,12 @@ public class NetworkTablesManager {
5555

5656
private final NetworkTableInstance ntInstance = NetworkTableInstance.getDefault();
5757
private final String kRootTableName = "/photonvision";
58-
private final String kCoprocTableName = "coprocessors";
58+
public final String kCoprocTableName = "coprocessors";
5959
private final String kFieldLayoutName = "apriltag_field_layout";
6060
public final NetworkTable kRootTable = ntInstance.getTable(kRootTableName);
6161

62+
// This is used to subscribe to all coprocessor tables, so we can detect conflicts
63+
@SuppressWarnings("unused")
6264
private final MultiSubscriber sub =
6365
new MultiSubscriber(ntInstance, new String[] {kRootTableName + "/" + kCoprocTableName + "/"});
6466

photon-core/src/main/java/org/photonvision/common/hardware/HardwareManager.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,9 @@ private HardwareManager(HardwareConfig hardwareConfig, HardwareSettings hardware
7676
this.metricsManager = new MetricsManager();
7777
this.metricsManager.setConfig(hardwareConfig);
7878

79+
TimedTaskManager.getInstance()
80+
.addTask("Metrics Publisher", this.metricsManager::publishMetrics, 5000);
81+
7982
ledModeRequest =
8083
NetworkTablesManager.getInstance()
8184
.kRootTable
@@ -222,10 +225,6 @@ private void statusLEDUpdate() {
222225
blinkCounter++;
223226
}
224227

225-
public HardwareConfig getConfig() {
226-
return hardwareConfig;
227-
}
228-
229228
public void publishMetrics() {
230229
metricsManager.publishMetrics();
231230
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*
2+
* Copyright (C) Photon Vision.
3+
*
4+
* This program is free software: you can redistribute it and/or modify
5+
* it under the terms of the GNU General Public License as published by
6+
* the Free Software Foundation, either version 3 of the License, or
7+
* (at your option) any later version.
8+
*
9+
* This program is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
* GNU General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU General Public License
15+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
16+
*/
17+
18+
package org.photonvision.common.hardware.metrics;
19+
20+
import org.photonvision.common.hardware.metrics.proto.DeviceMetricsProto;
21+
22+
public record DeviceMetrics(
23+
double cpuTemp,
24+
double cpuUtil,
25+
String cpuThr,
26+
double ramMem,
27+
double ramUtil,
28+
double gpuMem,
29+
double gpuMemUtil,
30+
double diskUtilPct,
31+
double[] npuUsage,
32+
String ipAddress,
33+
double uptime) {
34+
public static final DeviceMetricsProto proto = new DeviceMetricsProto();
35+
}

0 commit comments

Comments
 (0)