Skip to content

Commit

Permalink
update
Browse files Browse the repository at this point in the history
  • Loading branch information
C-D-Lewis committed Oct 18, 2024
1 parent 1760faf commit 4c17b11
Show file tree
Hide file tree
Showing 9 changed files with 83 additions and 39 deletions.
20 changes: 20 additions & 0 deletions apps/conduit/src/modules/fleet.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,23 @@ attic.setHost(OPTIONS.FLEET.HOST);
*/
const sortByLastCheckIn = (a, b) => (a.lastCheckIn > b.lastCheckIn ? -1 : 1);

/**
* Get uptime in days.
*
* @returns {number} Number of days of uptime.
*/
const getUptimeDays = () => {
const start = new Date(execSync('uptime -s').toString()).getTime();
const now = new Date().getTime();

const diff = now - start;
const s = Math.round(diff / 1000);
const h = Math.round(s / (60 * 60));
const d = Math.round(h / 24);

return d;
};

/**
* Send the data to remote Attic to perform the checkin.
*/
Expand All @@ -65,6 +82,8 @@ const checkIn = async () => {

const { size: diskSize, usePerc: diskUsage } = mainDisk;

const uptimeDays = getUptimeDays();

const updatePayload = {
deviceName: hostname(),
lastCheckIn: now.getTime(),
Expand All @@ -76,6 +95,7 @@ const checkIn = async () => {
commitDate,
diskUsage,
diskSize,
uptimeDays,
};

const fleetList = await attic.get(FLEET_LIST_KEY);
Expand Down
20 changes: 0 additions & 20 deletions apps/monitor/src/plugins/system-metrics.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,23 +25,6 @@ const getDiskUsage = (mountPath) => {
};
};

/**
* Get uptime in days.
*
* @returns {number} Number of days of uptime.
*/
const getUptimeDays = () => {
const start = new Date(execSync('uptime -s').toString()).getTime();
const now = new Date().getTime();

const diff = now - start;
const s = Math.round(diff / 1000);
const h = Math.round(s / (60 * 60));
const d = Math.round(h / 24);

return d;
};

/**
* Get current frequency as a percentage of reported maximum.
*
Expand Down Expand Up @@ -84,8 +67,6 @@ module.exports = async (args = {}) => {

const tempRaw = temperature.get();

const uptimeDays = getUptimeDays();

const freqPerc = getFrequencyPerc();

// Metrics with 'Perc' in the name are treated as a 0-100% range in the dashboard
Expand All @@ -96,7 +77,6 @@ module.exports = async (args = {}) => {
diskGb,
diskPerc,
tempRaw,
uptimeDays,
freqPerc,
});
} catch (e) {
Expand Down
Binary file added dashboard2/assets/images/uptime.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
59 changes: 47 additions & 12 deletions dashboard2/src/components/DeviceMetrics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,16 @@ import {
} from '../types';
import { fetchMetric } from '../util';
import Theme from '../theme';
import { BUCKET_SIZE } from '../constants';

declare const fabricate: Fabricate<AppState>;

/** Plot point label offset */
const LABEL_OFFSET = 3;

/** Graph width based on length of a day */
const GRAPH_WIDTH = Math.round(1440 / BUCKET_SIZE);

/**
* NoDeviceLabel component.
*
Expand All @@ -27,6 +34,13 @@ const NoMetricsLabel = () => fabricate('Text')
})
.setText('No metrics to show');

/** Chart plot point */
type PlotPoint = {
x: number;
y: number;
value: number;
};

/**
* MetricGraph component.
*
Expand All @@ -50,35 +64,54 @@ const MetricGraph = ({ name } : { name: MetricName }) => {
const range = maxValue - minValue;

const ctx = canvas.getContext('2d')!;
ctx.imageSmoothingEnabled = false;
ctx.translate(0.5, 0.5);

// Background
ctx.fillStyle = Theme.palette.grey2;
ctx.fillStyle = 'black';
ctx.fillRect(0, 0, width, height);

if (!buckets.length) {
// ctx.font = '24px Arial';
// ctx.fillStyle = 'white';
// ctx.fillText('No data', width / 2, height / 2);
ctx.font = '18px Arial';
ctx.fillStyle = 'white';
ctx.fillText('No data', 15, 15);
return;
}

// Latest data
ctx.fillStyle = Theme.palette.secondary;
const points = buckets.length > width ? buckets.slice(buckets.length - width) : buckets;
let minPoint: PlotPoint = { x: 0, y: 0, value: 0 };
let maxPoint: PlotPoint = { x: 0, y: 99999999, value: 0 };

ctx.lineWidth = 1.5;
ctx.strokeStyle = Theme.palette.secondary;
ctx.beginPath();
points.forEach((p: DataPoint, i: number) => {
const pHeight = ((p.value - minValue) * height) / range;
const { value } = p;
const pHeight = ((value - minValue) * height) / range;
const x = i;
const y = height - pHeight;

ctx.fillRect(x, y, 2, 2);
if (y > minPoint.y) {
minPoint = { x, y, value };
}
if (y < maxPoint.y) {
maxPoint = { x, y, value };
}

ctx.lineTo(x, y);
});
ctx.stroke();

// Label min/max
ctx.font = '14px Arial';
ctx.fillStyle = 'white';
ctx.fillText(minPoint.value.toFixed(1), minPoint.x + LABEL_OFFSET, minPoint.y - LABEL_OFFSET);
ctx.fillText(maxPoint.value.toFixed(1), maxPoint.x + LABEL_OFFSET, maxPoint.y - LABEL_OFFSET);
};

return fabricate('div')
.setStyles(({ palette }) => ({
width: '100%',
height: '100%',
}))
.setStyles(() => ({ width: '100%', height: '100%' }))
.setChildren([canvas as unknown as FabricateComponent<AppState>])
.onUpdate(async (el, state, keys) => {
if (keys.includes(fabricate.StateKeys.Created)) {
Expand All @@ -105,12 +138,13 @@ const MetricGraph = ({ name } : { name: MetricName }) => {
const MetricContainer = ({ name } : { name: MetricName }) => fabricate('Column')
.setStyles(({ palette }) => ({
margin: '15px',
width: '30%',
width: `${GRAPH_WIDTH}px`,
height: '180px',
border: `solid 2px ${palette.grey6}`,
}))
.setNarrowStyles({
width: '100%',
margin: '10px 0px',
})
.setChildren([
fabricate('Text')
Expand Down Expand Up @@ -148,6 +182,7 @@ const DeviceMetrics = () => fabricate('Row')
MetricContainer({ name: 'cpu' }),
MetricContainer({ name: 'memoryPerc' }),
MetricContainer({ name: 'tempRaw' }),
MetricContainer({ name: 'freqPerc' }),
]);
}, [fabricate.StateKeys.Created, 'selectedDevice']);

Expand Down
7 changes: 6 additions & 1 deletion dashboard2/src/components/StatRow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ const StatView = ({
*/
const StatRow = ({ device }: { device: Device }) => {
const {
commit, commitDate, lastCheckIn, diskSize, diskUsage,
commit, commitDate, lastCheckIn, diskSize, diskUsage, uptimeDays,
} = device;

return fabricate('Row')
Expand All @@ -146,6 +146,11 @@ const StatRow = ({ device }: { device: Device }) => {
text: `${diskUsage}% of ${diskSize} used`,
fontFamily: Theme.fonts.body,
}),
StatView({
iconSrc: 'assets/images/uptime.png',
text: `${uptimeDays || '-'} days`,
fontFamily: Theme.fonts.body,
}),
Toolbar({ device }),
]);
};
Expand Down
3 changes: 3 additions & 0 deletions dashboard2/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,6 @@ export const ICON_NAMES: Record<string, string> = {

/** Navbar height from fabricate.js */
export const NAVBAR_HEIGHT = 40;

/** Metric bucket size */
export const BUCKET_SIZE = 5;
2 changes: 1 addition & 1 deletion dashboard2/src/theme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
const Theme = {
palette: {
primary: '#c7053d',
secondary: '#ffeb3b',
secondary: 'orange',
text: 'white',
grey1: '#111',
grey2: '#222',
Expand Down
3 changes: 2 additions & 1 deletion dashboard2/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export type Device = {
deviceType: 'other' | 'pc' | 'pi' | 'other';
diskSize: string;
diskUsage: number;
uptimeDays?: number;
};

/** Graph data point. */
Expand All @@ -38,7 +39,7 @@ export type DataPoint = {
};

/** Available graphed metrics */
export type MetricName = 'cpu' | 'memoryPerc' | 'tempRaw';
export type MetricName = 'cpu' | 'memoryPerc' | 'tempRaw' | 'freqPerc';

/** Raw metric point */
export type MetricPoint = [number, number];
Expand Down
8 changes: 4 additions & 4 deletions dashboard2/src/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Fabricate, FabricateComponent } from 'fabricate.js';
import {
AppState, DataPoint, Device, DeviceApp, MetricName,
} from './types';
import { CONDUIT_PORT, FLEET_HOST } from './constants';
import { BUCKET_SIZE, CONDUIT_PORT, FLEET_HOST } from './constants';
import { sendConduitPacket } from './services/conduitService';

declare const fabricate: Fabricate<AppState>;
Expand Down Expand Up @@ -204,7 +204,7 @@ export const fetchMetric = async (state: AppState, name: MetricName) => {
);
const { message: newHistory } = res;
if (res.error) console.log(res);
if (!newHistory) return;
if (!newHistory.length) return;

const type = Array.isArray(newHistory[0][1]) ? 'array' : 'number';

Expand All @@ -223,7 +223,7 @@ export const fetchMetric = async (state: AppState, name: MetricName) => {
9999999,
);
maxValue = name.includes('Perc')
? 100
? 110
: newHistory.reduce(
// @ts-expect-error handled with 'type'
(acc: number, [, value]: MetricPoint) => (value > acc ? value : acc),
Expand All @@ -237,7 +237,7 @@ export const fetchMetric = async (state: AppState, name: MetricName) => {
const copy = [...newHistory];
const buckets: DataPoint[] = [];
while (copy.length) {
const points = copy.splice(0, 5);
const points = copy.splice(0, BUCKET_SIZE);
const avgIndex = Math.floor(points.length / 2);
buckets.push({
value: points.reduce((acc, [, value]) => acc + value, 0) / points.length,
Expand Down

0 comments on commit 4c17b11

Please sign in to comment.