Skip to content
This repository was archived by the owner on Aug 2, 2025. It is now read-only.

Commit 830c36d

Browse files
committed
✨ Feat: Add container network stats and improve data fetching
This commit introduces the collection of network statistics for Docker containers, including receive and transmit rates, and total bytes. It also refactors and improves the data fetching and processing logic for container stats, including adding timestamps and improving validation. - Add `network_rx_rate`, `network_tx_rate`, `network_rx_bytes`, and `network_tx_bytes` columns to the `container_stats` table. - Update the `addContainerStats` function to include network stats and a timestamp. - Add a new function `getLastContainerStats` to retrieve the last recorded stats for a container, used for calculating rates. - Refactor `storeContainerData` to fetch and calculate network stats, including using the previous stats to calculate RX/TX rates. - Improve data validation for container stats. - Update default theme colors to be more accessible.
1 parent e4d1eb3 commit 830c36d

File tree

10 files changed

+565
-500
lines changed

10 files changed

+565
-500
lines changed

docker/docker-compose.dev.yaml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ services:
55
image: lscr.io/linuxserver/socket-proxy:latest
66
volumes:
77
- /var/run/docker.sock:/var/run/docker.sock:ro
8-
restart: never
8+
restart: no
99
read_only: true
1010
tmpfs:
1111
- /run
@@ -44,10 +44,10 @@ services:
4444
sqlite-web:
4545
container_name: sqlite-web
4646
image: ghcr.io/coleifer/sqlite-web:latest
47-
restart: never
47+
restart: no
4848
ports:
4949
- 8080:8080
5050
volumes:
51-
- /home/nik/Documents/Code-local/dockstat-project/DockStat/data:/data:ro
51+
- /home/nik/Documents/Code-local/dockstat-project/DockStat/server/data:/data:ro
5252
environment:
5353
- SQLITE_DATABASE=dockstatapi.db

src/core/database/containerStats.ts

Lines changed: 78 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -3,41 +3,89 @@ import { db } from "./database";
33
import { executeDbOperation } from "./helper";
44

55
const insert = db.prepare(`
6-
INSERT INTO container_stats (id, hostId, name, image, status, state, cpu_usage, memory_usage)
7-
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
6+
INSERT INTO container_stats (
7+
id,
8+
hostId,
9+
name,
10+
image,
11+
status,
12+
state,
13+
cpu_usage,
14+
memory_usage,
15+
network_rx_rate,
16+
network_tx_rate,
17+
network_rx_bytes,
18+
network_tx_bytes,
19+
timestamp
20+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
821
`);
922

10-
const get = db.prepare("SELECT * FROM container_stats");
23+
const getOne = db.prepare(`
24+
SELECT *
25+
FROM container_stats
26+
WHERE hostId = ?
27+
AND id = ?
28+
ORDER BY timestamp DESC
29+
LIMIT 1
30+
`);
31+
32+
const getAll = db.prepare(`
33+
SELECT *
34+
FROM container_stats
35+
`);
1136

1237
export function addContainerStats(stats: container_stats) {
13-
return executeDbOperation(
14-
"Add Container Stats",
15-
() =>
16-
insert.run(
17-
stats.id,
18-
stats.hostId,
19-
stats.name,
20-
stats.image,
21-
stats.status,
22-
stats.state,
23-
stats.cpu_usage,
24-
stats.memory_usage,
25-
),
26-
() => {
27-
if (
28-
typeof stats.id !== "string" ||
29-
typeof stats.hostId !== "number" ||
30-
typeof stats.cpu_usage !== "number" ||
31-
typeof stats.memory_usage !== "number"
32-
) {
33-
throw new TypeError("Invalid container stats parameters");
34-
}
35-
},
36-
);
38+
return executeDbOperation(
39+
"Add Container Stats",
40+
() =>
41+
insert.run(
42+
stats.id,
43+
stats.hostId,
44+
stats.name,
45+
stats.image,
46+
stats.status,
47+
stats.state,
48+
stats.cpu_usage,
49+
stats.memory_usage || 0,
50+
stats.network_rx_rate,
51+
stats.network_tx_rate,
52+
stats.network_rx_bytes,
53+
stats.network_tx_bytes,
54+
stats.timestamp || new Date().toISOString(),
55+
),
56+
() => {
57+
if (
58+
typeof stats.id !== "string" ||
59+
typeof stats.hostId !== "number" ||
60+
typeof stats.name !== "string" ||
61+
typeof stats.image !== "string" ||
62+
typeof stats.status !== "string" ||
63+
typeof stats.state !== "string" ||
64+
typeof stats.cpu_usage !== "number" ||
65+
typeof stats.memory_usage !== "number" ||
66+
typeof stats.network_rx_rate !== "number" ||
67+
typeof stats.network_tx_rate !== "number" ||
68+
typeof stats.network_rx_bytes !== "number" ||
69+
typeof stats.network_tx_bytes !== "number"
70+
) {
71+
throw new TypeError("Invalid container stats parameters");
72+
}
73+
},
74+
);
3775
}
3876

3977
export function getContainerStats(): container_stats[] {
40-
return executeDbOperation("Get Container Stats", () =>
41-
get.all(),
42-
) as container_stats[];
78+
return executeDbOperation("Get All Container Stats", () =>
79+
getAll.all(),
80+
) as container_stats[];
81+
}
82+
83+
export function getLastContainerStats(
84+
hostId: number,
85+
containerId: string,
86+
): container_stats | undefined {
87+
return executeDbOperation(
88+
"Get Last Container Stat",
89+
() => getOne.get(hostId, containerId) as container_stats,
90+
);
4391
}

src/core/database/database.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,11 @@ export function init() {
8484
status TEXT NOT NULL,
8585
state TEXT NOT NULL,
8686
cpu_usage FLOAT NOT NULL,
87-
memory_usage,
87+
memory_usage FLOAT NOT NULL,
88+
network_rx_rate NUMBER NOT NULL,
89+
network_tx_rate NUMBER NOT NULL,
90+
network_rx_bytes NUMBER NOT NULL,
91+
network_tx_bytes NUMBER NOT NULL,
8892
timestamp DATETIME DEFAULT CURRENT_TIMESTAMP
8993
);
9094
@@ -118,23 +122,23 @@ export function init() {
118122
--gradient-from: #1e293b;
119123
--gradient-to: #334155;
120124
--border: #334155;
121-
--border-accent: rgba(129, 140, 249, 0.3);
125+
--border-accent: #818cf94d;
122126
--text-primary: #f8fafc;
123127
--text-secondary: #94a3b8;
124128
--text-tertiary: #64748b;
125129
--state-success: #4ade80;
126130
--state-warning: #facc15;
127131
--state-error: #f87171;
128132
--state-info: #38bdf8;
129-
--shadow-glow: 0 0 15px rgba(129, 140, 249, 0.5);
133+
--shadow-glow: 0 0 15px #818cf980;
130134
--background-gradient: linear-gradient(145deg, #0f172a 0%, #1e293b 100%);
131135
}
132136
`;
133137

134138
if (themeRows.count === 0) {
135139
db.prepare(
136140
"INSERT INTO themes (name, creator, vars, tags) VALUES (?,?,?,?)",
137-
).run("default", "Its4Nik", defaultCss, "[default]");
141+
).run("default", "Its4Nik", defaultCss, "default, dark");
138142
}
139143

140144
const configRow = db

src/core/database/themes.ts

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,34 @@
11
import type { Theme } from "~/typings/database";
2+
import { logger } from "../utils/logger";
23
import { db } from "./database";
34
import { executeDbOperation } from "./helper";
4-
import { logger } from "../utils/logger";
55

66
const stmt = {
7-
insert: db.prepare(`
7+
insert: db.prepare(`
88
INSERT INTO themes (name, creator, vars, tags) VALUES (?, ?, ?, ?)
99
`),
10-
remove: db.prepare("DELETE FROM themes WHERE name = ?"),
11-
read: db.prepare("SELECT * FROM themes WHERE name = ?"),
12-
readAll: db.prepare("SELECT * FROM themes"),
10+
remove: db.prepare("DELETE FROM themes WHERE name = ?"),
11+
read: db.prepare("SELECT * FROM themes WHERE name = ?"),
12+
readAll: db.prepare("SELECT * FROM themes"),
1313
};
1414

1515
export function getThemes() {
16-
return executeDbOperation("Get Themes", () => stmt.readAll.all()) as Theme[];
16+
return executeDbOperation("Get Themes", () => stmt.readAll.all()) as Theme[];
1717
}
1818

1919
export function addTheme({ name, creator, vars, tags }: Theme) {
20-
return executeDbOperation("Save Theme", () =>
21-
stmt.insert.run(name, creator, vars, tags.toString()),
22-
);
20+
return executeDbOperation("Save Theme", () =>
21+
stmt.insert.run(name, creator, vars, tags.toString()),
22+
);
2323
}
2424
export function getSpecificTheme(name: string): Theme {
25-
return executeDbOperation(
26-
"Getting specific Theme",
27-
() => stmt.read.get(name) as Theme,
28-
);
25+
return executeDbOperation(
26+
"Getting specific Theme",
27+
() => stmt.read.get(name) as Theme,
28+
);
2929
}
3030

3131
export function deleteTheme(name: string) {
32-
logger.debug(`Removing ${name} from themes `);
33-
return executeDbOperation("Remove Theme", () => stmt.remove.run(name));
32+
logger.debug(`Removing ${name} from themes `);
33+
return executeDbOperation("Remove Theme", () => stmt.remove.run(name));
3434
}

0 commit comments

Comments
 (0)