Add host temperature telemetry and history
This commit is contained in:
@@ -34,6 +34,101 @@ async function sample(id: string, at: number, cpu = 25, memory = 4 * GiB, cores
|
||||
}
|
||||
|
||||
describe('capacity history', () => {
|
||||
it('keeps separate CPU series, device drill-down, real zero and missing temperature gaps', async () => {
|
||||
await host('one');
|
||||
await host('two');
|
||||
await host('unsupported');
|
||||
await host('removed');
|
||||
const { recordTemperatures } = await import('../../src/lib/server/hosts/temperatures.js');
|
||||
const cpu = (celsius: number) => ({
|
||||
id: 'package',
|
||||
kind: 'cpu-package' as const,
|
||||
device: 'coretemp',
|
||||
label: 'Package id 0',
|
||||
celsius
|
||||
});
|
||||
const drive = {
|
||||
id: 'drive',
|
||||
kind: 'nvme' as const,
|
||||
device: 'nvme',
|
||||
label: 'Composite',
|
||||
celsius: 50.9
|
||||
};
|
||||
recordTemperatures(
|
||||
'one',
|
||||
{ temperatures: [cpu(65), drive] },
|
||||
new Date(epoch - 55_000).toISOString()
|
||||
);
|
||||
recordTemperatures(
|
||||
'one',
|
||||
{ temperatures: [cpu(75)] },
|
||||
new Date(epoch - 30_000).toISOString()
|
||||
);
|
||||
recordTemperatures(
|
||||
'one',
|
||||
{ temperatures: [cpu(0)] },
|
||||
new Date(epoch - 180_000).toISOString()
|
||||
);
|
||||
recordTemperatures(
|
||||
'two',
|
||||
{ temperatures: [cpu(60)] },
|
||||
new Date(epoch - 40_000).toISOString()
|
||||
);
|
||||
recordTemperatures(
|
||||
'removed',
|
||||
{ temperatures: [cpu(99)] },
|
||||
new Date(epoch - 40_000).toISOString()
|
||||
);
|
||||
const { db } = await import('../../src/lib/server/db/index.js');
|
||||
db()
|
||||
.prepare('UPDATE ec_hosts SET deleted_at=? WHERE id=?')
|
||||
.run(new Date(epoch).toISOString(), 'removed');
|
||||
const { readCapacityHistory } =
|
||||
await import('../../src/lib/server/hosts/capacity-history.js');
|
||||
const fleet = readCapacityHistory(query, epoch).temperatures;
|
||||
expect(fleet.map((s) => s.label)).toEqual(['one', 'two', 'unsupported']);
|
||||
expect(fleet[0].points.slice(-3).map((p) => p.celsius)).toEqual([0, null, 75]);
|
||||
expect(fleet[1].points.at(-1)?.celsius).toBe(60);
|
||||
expect(fleet[2].points.every((p) => p.celsius === null)).toBe(true);
|
||||
const selected = readCapacityHistory(
|
||||
{ ...query, hostId: 'one', game: 't5' },
|
||||
epoch
|
||||
).temperatures;
|
||||
expect(selected.map((s) => s.kind)).toEqual(['cpu', 'nvme']);
|
||||
expect(selected[1].points.at(-1)?.celsius).toBe(50.9);
|
||||
expect(
|
||||
readCapacityHistory({ ...query, hostId: 'one', game: 't6' }, epoch).temperatures
|
||||
).toEqual(selected);
|
||||
expect(readCapacityHistory({ ...query, hostId: 'missing' }, epoch).temperatures).toEqual(
|
||||
[]
|
||||
);
|
||||
});
|
||||
|
||||
it('preserves temperature peaks for long ranges and includes a host enrolled during the current minute', async () => {
|
||||
await host('new', epoch - 20_000);
|
||||
const { recordTemperatures } = await import('../../src/lib/server/hosts/temperatures.js');
|
||||
recordTemperatures(
|
||||
'new',
|
||||
{
|
||||
temperatures: [
|
||||
{
|
||||
id: 'pkg',
|
||||
device: 'coretemp',
|
||||
kind: 'cpu-package',
|
||||
label: 'Package id 0',
|
||||
celsius: 65
|
||||
}
|
||||
]
|
||||
},
|
||||
new Date(epoch - 10_000).toISOString()
|
||||
);
|
||||
const { readCapacityHistory } =
|
||||
await import('../../src/lib/server/hosts/capacity-history.js');
|
||||
expect(readCapacityHistory(query, epoch).temperatures[0].points.at(-1)?.celsius).toBe(65);
|
||||
const long = readCapacityHistory({ ...query, range: '7d' }, epoch).temperatures[0];
|
||||
expect(long.points).toHaveLength(168);
|
||||
expect(long.points.at(-1)?.celsius).toBe(65);
|
||||
});
|
||||
it('averages each host before summing fleet headroom and exposes missing observations as gaps', async () => {
|
||||
await host('one');
|
||||
await host('two');
|
||||
|
||||
Reference in New Issue
Block a user