device-state: maintain system info as a running average, on a schedule

Change-type: patch
Signed-off-by: Ken Bannister <kb2ma@runbox.com>
This commit is contained in:
Ken Bannister 2022-12-04 09:30:33 -05:00
parent 3e1b1b0be1
commit 4cd212f7f5

View File

@ -112,6 +112,13 @@ let scheduledApply: { force?: boolean; delay?: number } | null = null;
let shuttingDown = false; let shuttingDown = false;
let applyInProgress = false; let applyInProgress = false;
let lastSysinfo: Partial<sysInfo.SystemInfo> = {};
const averagingKeys = [
'cpu_usage',
'memory_usage',
'storage_usage',
'cpu_temp',
];
export let connected: boolean; export let connected: boolean;
export let lastSuccessfulUpdate: number | null = null; export let lastSuccessfulUpdate: number | null = null;
@ -239,6 +246,13 @@ export async function loadInitialState() {
initNetworkChecks(conf); initNetworkChecks(conf);
const updateSysinfo = async () => {
// todo: Add a try/catch block? Don't let metrics kill the supervisor.
lastSysinfo = await getSysInfo();
}
await updateSysinfo();
setInterval(updateSysinfo, 60 * 1000);
if (!conf.initialConfigSaved) { if (!conf.initialConfigSaved) {
await saveInitialConfig(); await saveInitialConfig();
} }
@ -413,11 +427,9 @@ export async function getLegacyState(): Promise<DeviceLegacyState> {
return theState as DeviceLegacyState; return theState as DeviceLegacyState;
} }
async function getSysInfo( async function getSysInfo(): Promise<sysInfo.SystemInfo> {
lastInfo: Partial<sysInfo.SystemInfo>,
): Promise<sysInfo.SystemInfo> {
// If hardwareMetrics is false, send null patch for system metrics to cloud API // If hardwareMetrics is false, send null patch for system metrics to cloud API
const currentInfo = { let currentInfo = {
...((await config.get('hardwareMetrics')) ...((await config.get('hardwareMetrics'))
? await sysInfo.getSystemMetrics() ? await sysInfo.getSystemMetrics()
: { : {
@ -431,20 +443,19 @@ async function getSysInfo(
cpu_id: null, cpu_id: null,
}), }),
...(await sysInfo.getSystemChecks()), ...(await sysInfo.getSystemChecks()),
}; } as sysInfo.SystemInfo;
return Object.assign( // Adjust running average values over last 5 readings.
{} as sysInfo.SystemInfo, averagingKeys.forEach((key) => {
...Object.keys(currentInfo).map((key: keyof sysInfo.SystemInfo) => ({ const mykey = key as keyof sysInfo.SystemInfo;
[key]: sysInfo.isSignificantChange( const currentVal = currentInfo[mykey] as number;
key, let avgVal = lastSysinfo[mykey] as number;
lastInfo[key] as number, if (! (_.isUndefined(lastSysinfo[mykey]))) {
currentInfo[key] as number, avgVal = (avgVal * 4 + currentVal) / 5;
) (currentInfo[mykey] as number) = avgVal;
? (currentInfo[key] as number) }
: (lastInfo[key] as number), });
})), return currentInfo;
);
} }
/** SysInfo (metrics) property names used in report. */ /** SysInfo (metrics) property names used in report. */
@ -491,7 +502,21 @@ export async function getCurrentForReport(
...(localMode ? ['apps', 'logs_channel'] : []), ...(localMode ? ['apps', 'logs_channel'] : []),
]; ];
const systemInfo = await getSysInfo(lastReport[uuid] ?? {}); const reportInfo = lastReport[uuid] ?? {};
const systemInfo = Object.assign(
{} as sysInfo.SystemInfo,
...Object.keys(lastSysinfo).map((key: keyof sysInfo.SystemInfo) => ({
[key]: sysInfo.isSignificantChange(
key,
reportInfo[key] as number,
(_.isNumber(lastSysinfo[key])
? Math.round(lastSysinfo[key] as number) : lastSysinfo[key] as number),
)
? (_.isNumber(lastSysinfo[key])
? Math.round(lastSysinfo[key] as number) : lastSysinfo[key] as number)
: (reportInfo[key] as number),
})),
);
return { return {
[uuid]: _.omitBy( [uuid]: _.omitBy(