From a2ceb5c93189704beaf8b4f5c8b71c46d8e2a966 Mon Sep 17 00:00:00 2001 From: Cameron Diver Date: Mon, 12 Oct 2020 14:09:35 +0100 Subject: [PATCH] Refactor system information filtering Change-type: patch Signed-off-by: Cameron Diver --- src/device-state/current-state.ts | 36 +++---------------- src/lib/system-info.ts | 53 ++++++++++++++++++++++++---- test/38-sys-info.spec.ts | 58 +++++++++++++++++++++++++++++++ 3 files changed, 109 insertions(+), 38 deletions(-) create mode 100644 test/38-sys-info.spec.ts diff --git a/src/device-state/current-state.ts b/src/device-state/current-state.ts index b6347559..39edd5eb 100644 --- a/src/device-state/current-state.ts +++ b/src/device-state/current-state.ts @@ -122,38 +122,10 @@ const getStateDiff = (): DeviceStatus => { .value(), }; - const shouldReportSysInfo = (type: string, past: number, now: number) => { - if (!past) { - return true; - } - // TODO: Deduplicate this code - switch (type) { - case 'cpu_usage': - // The bucket size of cpu usage is 20 - return Math.floor(past / 20) !== Math.floor(now / 20); - case 'cpu_temp': - return Math.floor(past / 5) !== Math.floor(now / 5); - case 'memory_usage': - return Math.floor(past / 10) !== Math.floor(now / 10); - } - return true; - }; - - const toOmit: string[] = []; - _.each(diff.local, (value, key) => { - // if we have some system information that has changed, we check that it's - // within a certain range before reporting - if ( - !shouldReportSysInfo( - key, - (lastReportedLocal as any)[key], - value as number, - ) - ) { - toOmit.push(key); - } - }); - + const toOmit: string[] = sysInfo.filterNonSignificantChanges( + lastReportedLocal as sysInfo.SystemInfo, + stateForReport.local as sysInfo.SystemInfo, + ); diff.local = _.omit(diff.local, toOmit); return _.omitBy(diff, _.isEmpty); }; diff --git a/src/lib/system-info.ts b/src/lib/system-info.ts index 716737bc..34c9cbf6 100644 --- a/src/lib/system-info.ts +++ b/src/lib/system-info.ts @@ -1,8 +1,9 @@ import * as systeminformation from 'systeminformation'; import * as osUtils from 'os-utils'; +import * as _ from 'lodash'; import { fs, child_process } from 'mz'; -export function getCpuUsage() { +export function getCpuUsage(): Promise { return new Promise((resolve) => { osUtils.cpuUsage((percent) => { resolve(Math.round(percent * 100)); @@ -11,7 +12,11 @@ export function getCpuUsage() { } const blockDeviceRegex = /(\/dev\/.*)p\d+/; -export async function getStorageInfo() { +export async function getStorageInfo(): Promise<{ + blockDevice: string; + storageUsed?: number; + storageTotal?: number; +}> { const fsInfo = await systeminformation.fsSize(); let mainFs: string | undefined; let total = 0; @@ -51,7 +56,10 @@ export async function getStorageInfo() { }; } -export async function getMemoryInformation() { +export async function getMemoryInformation(): Promise<{ + used: number; + total: number; +}> { const mem = await systeminformation.mem(); return { used: bytesToMb(mem.used), @@ -59,11 +67,11 @@ export async function getMemoryInformation() { }; } -export async function getCpuTemp() { +export async function getCpuTemp(): Promise { return Math.round((await systeminformation.cpuTemperature()).main); } -export async function getCpuId() { +export async function getCpuId(): Promise { // Read /proc/device-tree/serial-number // if it's not there, return undefined try { @@ -76,7 +84,7 @@ export async function getCpuId() { } const undervoltageRegex = /under.*voltage/; -export async function undervoltageDetected() { +export async function undervoltageDetected(): Promise { try { const [dmesgStdout] = await child_process.exec('dmesg'); return undervoltageRegex.test(dmesgStdout.toString()); @@ -107,6 +115,39 @@ export async function getSysInfoToReport() { is_undervolted: undervoltage, }; } +export type SystemInfo = UnwrappedPromise< + ReturnType +>; + +const significantChange: { [key in keyof SystemInfo]?: number } = { + cpu_usage: 20, + cpu_temp: 5, + memory_usage: 10, +}; + +export function filterNonSignificantChanges( + past: Partial, + current: SystemInfo, +): Array { + return Object.keys( + _.omitBy(current, (value, key: keyof SystemInfo) => { + // If we didn't have a value for this in the past, include it + if (past[key] == null) { + return true; + } + const bucketSize = significantChange[key]; + // If we don't have any requirements on this value, include it + if (bucketSize == null) { + return true; + } + + return ( + Math.floor((value as number) / bucketSize) !== + Math.floor((past[key] as number) / bucketSize) + ); + }), + ) as Array; +} function bytesToMb(bytes: number) { return Math.floor(bytes / 1024 / 1024); diff --git a/test/38-sys-info.spec.ts b/test/38-sys-info.spec.ts new file mode 100644 index 00000000..cb0becb8 --- /dev/null +++ b/test/38-sys-info.spec.ts @@ -0,0 +1,58 @@ +import { expect } from 'chai'; +import * as sysInfo from '../src/lib/system-info'; + +describe('System information', () => { + describe('Delta-based filtering', () => { + it('should correctly filter cpu usage', () => { + expect( + sysInfo.filterNonSignificantChanges({ cpu_usage: 21 }, { + cpu_usage: 20, + } as sysInfo.SystemInfo), + ).to.deep.equal(['cpu_usage']); + + expect( + sysInfo.filterNonSignificantChanges({ cpu_usage: 10 }, { + cpu_usage: 20, + } as sysInfo.SystemInfo), + ).to.deep.equal([]); + }); + + it('should correctly filter cpu temperature', () => { + expect( + sysInfo.filterNonSignificantChanges({ cpu_temp: 21 }, { + cpu_temp: 22, + } as sysInfo.SystemInfo), + ).to.deep.equal(['cpu_temp']); + + expect( + sysInfo.filterNonSignificantChanges({ cpu_temp: 10 }, { + cpu_temp: 20, + } as sysInfo.SystemInfo), + ).to.deep.equal([]); + }); + + it('should correctly filter memory usage', () => { + expect( + sysInfo.filterNonSignificantChanges({ memory_usage: 21 }, { + memory_usage: 22, + } as sysInfo.SystemInfo), + ).to.deep.equal(['memory_usage']); + + expect( + sysInfo.filterNonSignificantChanges({ memory_usage: 10 }, { + memory_usage: 20, + } as sysInfo.SystemInfo), + ).to.deep.equal([]); + }); + + it('should not filter if we didnt have a past value', () => { + expect( + sysInfo.filterNonSignificantChanges({}, { + memory_usage: 22, + cpu_usage: 10, + cpu_temp: 5, + } as sysInfo.SystemInfo), + ).to.deep.equal([]); + }); + }); +});