mirror of
https://github.com/balena-os/balena-supervisor.git
synced 2024-12-19 21:57:54 +00:00
Merge pull request #1485 from balena-io/sysinfo-refactor
Refactor system information filtering
This commit is contained in:
commit
27f8872672
@ -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);
|
||||
};
|
||||
|
@ -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<number> {
|
||||
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<number> {
|
||||
return Math.round((await systeminformation.cpuTemperature()).main);
|
||||
}
|
||||
|
||||
export async function getCpuId() {
|
||||
export async function getCpuId(): Promise<string | undefined> {
|
||||
// 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<boolean> {
|
||||
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<typeof getSysInfoToReport>
|
||||
>;
|
||||
|
||||
const significantChange: { [key in keyof SystemInfo]?: number } = {
|
||||
cpu_usage: 20,
|
||||
cpu_temp: 5,
|
||||
memory_usage: 10,
|
||||
};
|
||||
|
||||
export function filterNonSignificantChanges(
|
||||
past: Partial<SystemInfo>,
|
||||
current: SystemInfo,
|
||||
): Array<keyof SystemInfo> {
|
||||
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<keyof SystemInfo>;
|
||||
}
|
||||
|
||||
function bytesToMb(bytes: number) {
|
||||
return Math.floor(bytes / 1024 / 1024);
|
||||
|
58
test/38-sys-info.spec.ts
Normal file
58
test/38-sys-info.spec.ts
Normal file
@ -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([]);
|
||||
});
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue
Block a user