@appkit/llamacpp-cli 1.4.1 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +21 -0
- package/MONITORING-ACCURACY-FIX.md +199 -0
- package/PER-PROCESS-METRICS.md +190 -0
- package/README.md +136 -1
- package/dist/cli.js +21 -4
- package/dist/cli.js.map +1 -1
- package/dist/commands/create.d.ts.map +1 -1
- package/dist/commands/create.js +12 -3
- package/dist/commands/create.js.map +1 -1
- package/dist/commands/monitor.d.ts +2 -0
- package/dist/commands/monitor.d.ts.map +1 -0
- package/dist/commands/monitor.js +126 -0
- package/dist/commands/monitor.js.map +1 -0
- package/dist/commands/ps.d.ts +3 -1
- package/dist/commands/ps.d.ts.map +1 -1
- package/dist/commands/ps.js +75 -5
- package/dist/commands/ps.js.map +1 -1
- package/dist/commands/server-show.d.ts.map +1 -1
- package/dist/commands/server-show.js +10 -3
- package/dist/commands/server-show.js.map +1 -1
- package/dist/commands/start.d.ts.map +1 -1
- package/dist/commands/start.js +14 -2
- package/dist/commands/start.js.map +1 -1
- package/dist/lib/history-manager.d.ts +46 -0
- package/dist/lib/history-manager.d.ts.map +1 -0
- package/dist/lib/history-manager.js +157 -0
- package/dist/lib/history-manager.js.map +1 -0
- package/dist/lib/metrics-aggregator.d.ts +40 -0
- package/dist/lib/metrics-aggregator.d.ts.map +1 -0
- package/dist/lib/metrics-aggregator.js +211 -0
- package/dist/lib/metrics-aggregator.js.map +1 -0
- package/dist/lib/system-collector.d.ts +80 -0
- package/dist/lib/system-collector.d.ts.map +1 -0
- package/dist/lib/system-collector.js +311 -0
- package/dist/lib/system-collector.js.map +1 -0
- package/dist/tui/HistoricalMonitorApp.d.ts +5 -0
- package/dist/tui/HistoricalMonitorApp.d.ts.map +1 -0
- package/dist/tui/HistoricalMonitorApp.js +490 -0
- package/dist/tui/HistoricalMonitorApp.js.map +1 -0
- package/dist/tui/MonitorApp.d.ts +4 -0
- package/dist/tui/MonitorApp.d.ts.map +1 -0
- package/dist/tui/MonitorApp.js +315 -0
- package/dist/tui/MonitorApp.js.map +1 -0
- package/dist/tui/MultiServerMonitorApp.d.ts +4 -0
- package/dist/tui/MultiServerMonitorApp.d.ts.map +1 -0
- package/dist/tui/MultiServerMonitorApp.js +712 -0
- package/dist/tui/MultiServerMonitorApp.js.map +1 -0
- package/dist/types/history-types.d.ts +30 -0
- package/dist/types/history-types.d.ts.map +1 -0
- package/dist/types/history-types.js +11 -0
- package/dist/types/history-types.js.map +1 -0
- package/dist/types/monitor-types.d.ts +123 -0
- package/dist/types/monitor-types.d.ts.map +1 -0
- package/dist/types/monitor-types.js +3 -0
- package/dist/types/monitor-types.js.map +1 -0
- package/dist/types/server-config.d.ts +1 -0
- package/dist/types/server-config.d.ts.map +1 -1
- package/dist/types/server-config.js.map +1 -1
- package/dist/utils/downsample-utils.d.ts +35 -0
- package/dist/utils/downsample-utils.d.ts.map +1 -0
- package/dist/utils/downsample-utils.js +107 -0
- package/dist/utils/downsample-utils.js.map +1 -0
- package/dist/utils/file-utils.d.ts +6 -0
- package/dist/utils/file-utils.d.ts.map +1 -1
- package/dist/utils/file-utils.js +38 -0
- package/dist/utils/file-utils.js.map +1 -1
- package/dist/utils/process-utils.d.ts +35 -2
- package/dist/utils/process-utils.d.ts.map +1 -1
- package/dist/utils/process-utils.js +220 -25
- package/dist/utils/process-utils.js.map +1 -1
- package/docs/images/.gitkeep +1 -0
- package/package.json +5 -1
- package/src/cli.ts +21 -4
- package/src/commands/create.ts +14 -4
- package/src/commands/monitor.ts +110 -0
- package/src/commands/ps.ts +88 -5
- package/src/commands/server-show.ts +10 -3
- package/src/commands/start.ts +15 -2
- package/src/lib/history-manager.ts +172 -0
- package/src/lib/metrics-aggregator.ts +257 -0
- package/src/lib/system-collector.ts +315 -0
- package/src/tui/HistoricalMonitorApp.ts +548 -0
- package/src/tui/MonitorApp.ts +386 -0
- package/src/tui/MultiServerMonitorApp.ts +792 -0
- package/src/types/history-types.ts +39 -0
- package/src/types/monitor-types.ts +162 -0
- package/src/types/server-config.ts +1 -0
- package/src/utils/downsample-utils.ts +128 -0
- package/src/utils/file-utils.ts +40 -0
- package/src/utils/process-utils.ts +243 -25
- package/test-load.sh +100 -0
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.HistoryManager = void 0;
|
|
4
|
+
const promises_1 = require("fs/promises");
|
|
5
|
+
const path_1 = require("path");
|
|
6
|
+
const os_1 = require("os");
|
|
7
|
+
const history_types_js_1 = require("../types/history-types.js");
|
|
8
|
+
class HistoryManager {
|
|
9
|
+
constructor(serverId) {
|
|
10
|
+
this.MAX_AGE_MS = 24 * 60 * 60 * 1000; // 24 hours
|
|
11
|
+
this.serverId = serverId;
|
|
12
|
+
this.historyDir = (0, path_1.join)((0, os_1.homedir)(), '.llamacpp', 'history');
|
|
13
|
+
this.historyPath = (0, path_1.join)(this.historyDir, `${serverId}.json`);
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Append a new snapshot to history (with auto-pruning)
|
|
17
|
+
*/
|
|
18
|
+
async appendSnapshot(serverMetrics, systemMetrics) {
|
|
19
|
+
try {
|
|
20
|
+
// Ensure history directory exists
|
|
21
|
+
await (0, promises_1.mkdir)(this.historyDir, { recursive: true });
|
|
22
|
+
// Load existing history
|
|
23
|
+
const historyData = await this.loadHistoryData();
|
|
24
|
+
// Create new snapshot
|
|
25
|
+
const snapshot = {
|
|
26
|
+
timestamp: Date.now(),
|
|
27
|
+
server: {
|
|
28
|
+
healthy: serverMetrics.healthy,
|
|
29
|
+
uptime: serverMetrics.uptime,
|
|
30
|
+
activeSlots: serverMetrics.activeSlots,
|
|
31
|
+
idleSlots: serverMetrics.idleSlots,
|
|
32
|
+
totalSlots: serverMetrics.totalSlots,
|
|
33
|
+
avgPromptSpeed: serverMetrics.avgPromptSpeed,
|
|
34
|
+
avgGenerateSpeed: serverMetrics.avgGenerateSpeed,
|
|
35
|
+
processMemory: serverMetrics.processMemory,
|
|
36
|
+
processCpuUsage: serverMetrics.processCpuUsage,
|
|
37
|
+
},
|
|
38
|
+
system: systemMetrics ? {
|
|
39
|
+
gpuUsage: systemMetrics.gpuUsage,
|
|
40
|
+
cpuUsage: systemMetrics.cpuUsage,
|
|
41
|
+
aneUsage: systemMetrics.aneUsage,
|
|
42
|
+
temperature: systemMetrics.temperature,
|
|
43
|
+
memoryUsed: systemMetrics.memoryUsed,
|
|
44
|
+
memoryTotal: systemMetrics.memoryTotal,
|
|
45
|
+
} : undefined,
|
|
46
|
+
};
|
|
47
|
+
// Append new snapshot
|
|
48
|
+
historyData.snapshots.push(snapshot);
|
|
49
|
+
// Prune old snapshots (keep only last 24h)
|
|
50
|
+
historyData.snapshots = this.pruneOldSnapshots(historyData.snapshots, this.MAX_AGE_MS);
|
|
51
|
+
// Atomic write: write to temp file in same directory, then rename
|
|
52
|
+
// This prevents read collisions during concurrent access
|
|
53
|
+
// IMPORTANT: temp file MUST be in same directory as destination for rename to work across filesystems
|
|
54
|
+
const tempPath = (0, path_1.join)(this.historyDir, `.${this.serverId}-${Date.now()}.tmp`);
|
|
55
|
+
await (0, promises_1.writeFile)(tempPath, JSON.stringify(historyData, null, 2), 'utf-8');
|
|
56
|
+
await (0, promises_1.rename)(tempPath, this.historyPath);
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
// Silent failure - don't interrupt monitoring
|
|
60
|
+
// Don't throw - just return silently to avoid polluting console
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Load all snapshots within specified time window
|
|
66
|
+
*/
|
|
67
|
+
async loadHistory(windowHours) {
|
|
68
|
+
// Retry logic for file I/O collisions during concurrent read/write
|
|
69
|
+
const maxRetries = 3;
|
|
70
|
+
let lastError = null;
|
|
71
|
+
for (let attempt = 0; attempt < maxRetries; attempt++) {
|
|
72
|
+
try {
|
|
73
|
+
const historyData = await this.loadHistoryData();
|
|
74
|
+
return this.filterByTimeWindow(historyData.snapshots, windowHours);
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
lastError = error;
|
|
78
|
+
// Wait briefly before retry (exponential backoff)
|
|
79
|
+
if (attempt < maxRetries - 1) {
|
|
80
|
+
await new Promise(resolve => setTimeout(resolve, 50 * Math.pow(2, attempt)));
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
// All retries failed - throw error so it can be handled upstream
|
|
85
|
+
throw new Error(`Failed to load history after ${maxRetries} attempts: ${lastError?.message || 'Unknown error'}`);
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Load history for specific time window type
|
|
89
|
+
*/
|
|
90
|
+
async loadHistoryByWindow(window) {
|
|
91
|
+
return this.loadHistory(history_types_js_1.TIME_WINDOW_HOURS[window]);
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Get file path for server history
|
|
95
|
+
*/
|
|
96
|
+
getHistoryPath() {
|
|
97
|
+
return this.historyPath;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Check if history file exists
|
|
101
|
+
*/
|
|
102
|
+
async hasHistory() {
|
|
103
|
+
try {
|
|
104
|
+
await (0, promises_1.access)(this.historyPath);
|
|
105
|
+
return true;
|
|
106
|
+
}
|
|
107
|
+
catch {
|
|
108
|
+
return false;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Clear all history for server
|
|
113
|
+
*/
|
|
114
|
+
async clearHistory() {
|
|
115
|
+
const emptyHistory = {
|
|
116
|
+
serverId: this.serverId,
|
|
117
|
+
snapshots: [],
|
|
118
|
+
};
|
|
119
|
+
await (0, promises_1.mkdir)(this.historyDir, { recursive: true });
|
|
120
|
+
// Atomic write - temp file in same directory as destination
|
|
121
|
+
const tempPath = (0, path_1.join)(this.historyDir, `.${this.serverId}-${Date.now()}.tmp`);
|
|
122
|
+
await (0, promises_1.writeFile)(tempPath, JSON.stringify(emptyHistory, null, 2), 'utf-8');
|
|
123
|
+
await (0, promises_1.rename)(tempPath, this.historyPath);
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Load full history data from file
|
|
127
|
+
*/
|
|
128
|
+
async loadHistoryData() {
|
|
129
|
+
try {
|
|
130
|
+
const content = await (0, promises_1.readFile)(this.historyPath, 'utf-8');
|
|
131
|
+
return JSON.parse(content);
|
|
132
|
+
}
|
|
133
|
+
catch (error) {
|
|
134
|
+
// File doesn't exist or is corrupted, return empty history
|
|
135
|
+
return {
|
|
136
|
+
serverId: this.serverId,
|
|
137
|
+
snapshots: [],
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Prune snapshots older than maxAge
|
|
143
|
+
*/
|
|
144
|
+
pruneOldSnapshots(snapshots, maxAgeMs) {
|
|
145
|
+
const cutoff = Date.now() - maxAgeMs;
|
|
146
|
+
return snapshots.filter(s => s.timestamp >= cutoff);
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Filter snapshots by time window
|
|
150
|
+
*/
|
|
151
|
+
filterByTimeWindow(snapshots, windowHours) {
|
|
152
|
+
const cutoff = Date.now() - (windowHours * 60 * 60 * 1000);
|
|
153
|
+
return snapshots.filter(s => s.timestamp >= cutoff);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
exports.HistoryManager = HistoryManager;
|
|
157
|
+
//# sourceMappingURL=history-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"history-manager.js","sourceRoot":"","sources":["../../src/lib/history-manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { ServerConfig } from '../types/server-config.js';
|
|
2
|
+
import { ServerMetrics, MonitorData } from '../types/monitor-types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Aggregates metrics from llama.cpp server API endpoints
|
|
5
|
+
* Combines server health, slot status, and model properties
|
|
6
|
+
*/
|
|
7
|
+
export declare class MetricsAggregator {
|
|
8
|
+
private serverUrl;
|
|
9
|
+
private timeout;
|
|
10
|
+
private previousSlots;
|
|
11
|
+
constructor(server: ServerConfig, timeout?: number);
|
|
12
|
+
/**
|
|
13
|
+
* Fetch data from llama.cpp API with timeout
|
|
14
|
+
*/
|
|
15
|
+
private fetchWithTimeout;
|
|
16
|
+
/**
|
|
17
|
+
* Get server health status
|
|
18
|
+
*/
|
|
19
|
+
private getHealth;
|
|
20
|
+
/**
|
|
21
|
+
* Get server properties (model info, context size, etc.)
|
|
22
|
+
*/
|
|
23
|
+
private getProps;
|
|
24
|
+
/**
|
|
25
|
+
* Get active slots information with calculated tok/s
|
|
26
|
+
*/
|
|
27
|
+
private getSlots;
|
|
28
|
+
/**
|
|
29
|
+
* Aggregate all server metrics
|
|
30
|
+
* @param server - Server configuration
|
|
31
|
+
* @param processMemory - Optional pre-fetched process memory (for batch collection)
|
|
32
|
+
* @param processCpuUsage - Optional pre-fetched process CPU usage (for batch collection)
|
|
33
|
+
*/
|
|
34
|
+
collectServerMetrics(server: ServerConfig, processMemory?: number | null, processCpuUsage?: number | null): Promise<ServerMetrics>;
|
|
35
|
+
/**
|
|
36
|
+
* Collect complete monitoring data (server + system metrics)
|
|
37
|
+
*/
|
|
38
|
+
collectMonitorData(server: ServerConfig, updateInterval?: number): Promise<MonitorData>;
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=metrics-aggregator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metrics-aggregator.d.ts","sourceRoot":"","sources":["../../src/lib/metrics-aggregator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,EAAE,aAAa,EAAY,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAKjF;;;GAGG;AACH,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,aAAa,CAAoE;gBAE7E,MAAM,EAAE,YAAY,EAAE,OAAO,GAAE,MAAa;IAOxD;;OAEG;YACW,gBAAgB;IA0B9B;;OAEG;YACW,SAAS;IAKvB;;OAEG;YACW,QAAQ;IAItB;;OAEG;YACW,QAAQ;IAyDtB;;;;;OAKG;IACG,oBAAoB,CACxB,MAAM,EAAE,YAAY,EACpB,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,EAC7B,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,GAC9B,OAAO,CAAC,aAAa,CAAC;IAmGzB;;OAEG;IACG,kBAAkB,CACtB,MAAM,EAAE,YAAY,EACpB,cAAc,GAAE,MAAa,GAC5B,OAAO,CAAC,WAAW,CAAC;CAexB"}
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MetricsAggregator = void 0;
|
|
4
|
+
const status_checker_js_1 = require("./status-checker.js");
|
|
5
|
+
const system_collector_js_1 = require("./system-collector.js");
|
|
6
|
+
const process_utils_js_1 = require("../utils/process-utils.js");
|
|
7
|
+
/**
|
|
8
|
+
* Aggregates metrics from llama.cpp server API endpoints
|
|
9
|
+
* Combines server health, slot status, and model properties
|
|
10
|
+
*/
|
|
11
|
+
class MetricsAggregator {
|
|
12
|
+
constructor(server, timeout = 5000) {
|
|
13
|
+
this.previousSlots = new Map();
|
|
14
|
+
// Handle null host (legacy configs) by defaulting to 127.0.0.1
|
|
15
|
+
const host = server.host || '127.0.0.1';
|
|
16
|
+
this.serverUrl = `http://${host}:${server.port}`;
|
|
17
|
+
this.timeout = timeout;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Fetch data from llama.cpp API with timeout
|
|
21
|
+
*/
|
|
22
|
+
async fetchWithTimeout(endpoint, customTimeout) {
|
|
23
|
+
try {
|
|
24
|
+
const controller = new AbortController();
|
|
25
|
+
const timeoutMs = customTimeout ?? this.timeout;
|
|
26
|
+
const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
|
|
27
|
+
const response = await fetch(`${this.serverUrl}${endpoint}`, {
|
|
28
|
+
signal: controller.signal,
|
|
29
|
+
});
|
|
30
|
+
clearTimeout(timeoutId);
|
|
31
|
+
if (!response.ok) {
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
return await response.json();
|
|
35
|
+
}
|
|
36
|
+
catch (err) {
|
|
37
|
+
// Network error, timeout, or parse error
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Get server health status
|
|
43
|
+
*/
|
|
44
|
+
async getHealth() {
|
|
45
|
+
const health = await this.fetchWithTimeout('/health');
|
|
46
|
+
return health !== null && health.status === 'ok';
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Get server properties (model info, context size, etc.)
|
|
50
|
+
*/
|
|
51
|
+
async getProps() {
|
|
52
|
+
return await this.fetchWithTimeout('/props');
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Get active slots information with calculated tok/s
|
|
56
|
+
*/
|
|
57
|
+
async getSlots() {
|
|
58
|
+
const data = await this.fetchWithTimeout('/slots');
|
|
59
|
+
if (!data || !Array.isArray(data)) {
|
|
60
|
+
return [];
|
|
61
|
+
}
|
|
62
|
+
const now = Date.now();
|
|
63
|
+
return data.map((slot) => {
|
|
64
|
+
const slotId = slot.id;
|
|
65
|
+
const n_decoded = slot.next_token?.[0]?.n_decoded || 0;
|
|
66
|
+
const isProcessing = slot.is_processing;
|
|
67
|
+
// Calculate tokens per second by comparing with previous poll
|
|
68
|
+
let predicted_per_second;
|
|
69
|
+
if (isProcessing && n_decoded > 0) {
|
|
70
|
+
const previous = this.previousSlots.get(slotId);
|
|
71
|
+
if (previous && previous.n_decoded < n_decoded) {
|
|
72
|
+
const tokensGenerated = n_decoded - previous.n_decoded;
|
|
73
|
+
const timeElapsed = (now - previous.timestamp) / 1000; // Convert to seconds
|
|
74
|
+
if (timeElapsed > 0) {
|
|
75
|
+
predicted_per_second = tokensGenerated / timeElapsed;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
// Store current state for next comparison
|
|
79
|
+
this.previousSlots.set(slotId, { n_decoded, timestamp: now });
|
|
80
|
+
}
|
|
81
|
+
else if (!isProcessing) {
|
|
82
|
+
// Clear history when slot becomes idle
|
|
83
|
+
this.previousSlots.delete(slotId);
|
|
84
|
+
}
|
|
85
|
+
return {
|
|
86
|
+
id: slotId,
|
|
87
|
+
state: isProcessing ? 'processing' : 'idle',
|
|
88
|
+
n_prompt_tokens: slot.n_prompt_tokens,
|
|
89
|
+
n_decoded,
|
|
90
|
+
n_ctx: slot.n_ctx || 0,
|
|
91
|
+
timings: predicted_per_second
|
|
92
|
+
? {
|
|
93
|
+
prompt_n: 0,
|
|
94
|
+
prompt_ms: 0,
|
|
95
|
+
prompt_per_token_ms: 0,
|
|
96
|
+
prompt_per_second: 0,
|
|
97
|
+
predicted_n: n_decoded,
|
|
98
|
+
predicted_ms: 0,
|
|
99
|
+
predicted_per_token_ms: 0,
|
|
100
|
+
predicted_per_second,
|
|
101
|
+
}
|
|
102
|
+
: undefined,
|
|
103
|
+
};
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Aggregate all server metrics
|
|
108
|
+
* @param server - Server configuration
|
|
109
|
+
* @param processMemory - Optional pre-fetched process memory (for batch collection)
|
|
110
|
+
* @param processCpuUsage - Optional pre-fetched process CPU usage (for batch collection)
|
|
111
|
+
*/
|
|
112
|
+
async collectServerMetrics(server, processMemory, processCpuUsage) {
|
|
113
|
+
const now = Date.now();
|
|
114
|
+
// Check basic server status first
|
|
115
|
+
const status = await status_checker_js_1.statusChecker.checkServer(server);
|
|
116
|
+
// Calculate uptime if server is running and has lastStarted
|
|
117
|
+
let uptime;
|
|
118
|
+
if (status.isRunning && server.lastStarted) {
|
|
119
|
+
const startTime = new Date(server.lastStarted).getTime();
|
|
120
|
+
const uptimeSeconds = Math.floor((now - startTime) / 1000);
|
|
121
|
+
const hours = Math.floor(uptimeSeconds / 3600);
|
|
122
|
+
const minutes = Math.floor((uptimeSeconds % 3600) / 60);
|
|
123
|
+
const seconds = uptimeSeconds % 60;
|
|
124
|
+
uptime = `${hours}h ${minutes}m ${seconds}s`;
|
|
125
|
+
}
|
|
126
|
+
// If server not running, return minimal data
|
|
127
|
+
if (!status.isRunning) {
|
|
128
|
+
return {
|
|
129
|
+
server,
|
|
130
|
+
healthy: false,
|
|
131
|
+
modelLoaded: false,
|
|
132
|
+
modelName: server.modelName,
|
|
133
|
+
contextSize: server.ctxSize,
|
|
134
|
+
totalSlots: 0,
|
|
135
|
+
activeSlots: 0,
|
|
136
|
+
idleSlots: 0,
|
|
137
|
+
slots: [],
|
|
138
|
+
timestamp: now,
|
|
139
|
+
stale: false,
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
// Fetch detailed metrics in parallel
|
|
143
|
+
// If processMemory/CPU were pre-fetched (batch mode), use them; otherwise fetch individually
|
|
144
|
+
const [healthy, props, slots, fetchedMemory, fetchedCpu] = await Promise.all([
|
|
145
|
+
this.getHealth(),
|
|
146
|
+
this.getProps(),
|
|
147
|
+
this.getSlots(),
|
|
148
|
+
processMemory !== undefined
|
|
149
|
+
? Promise.resolve(processMemory)
|
|
150
|
+
: (server.pid ? (0, process_utils_js_1.getProcessMemory)(server.pid) : Promise.resolve(null)),
|
|
151
|
+
processCpuUsage !== undefined
|
|
152
|
+
? Promise.resolve(processCpuUsage)
|
|
153
|
+
: (server.pid ? (0, process_utils_js_1.getProcessCpu)(server.pid) : Promise.resolve(null)),
|
|
154
|
+
]);
|
|
155
|
+
// Calculate slot statistics
|
|
156
|
+
const activeSlots = slots.filter((s) => s.state === 'processing').length;
|
|
157
|
+
const idleSlots = slots.filter((s) => s.state === 'idle').length;
|
|
158
|
+
const totalSlots = props?.total_slots || slots.length;
|
|
159
|
+
// Calculate average speeds (only from processing slots)
|
|
160
|
+
const processingSlots = slots.filter((s) => s.state === 'processing' && s.timings);
|
|
161
|
+
const avgPromptSpeed = processingSlots.length > 0
|
|
162
|
+
? processingSlots.reduce((sum, s) => sum + (s.timings?.prompt_per_second || 0), 0) / processingSlots.length
|
|
163
|
+
: undefined;
|
|
164
|
+
const avgGenerateSpeed = processingSlots.length > 0
|
|
165
|
+
? processingSlots.reduce((sum, s) => sum + (s.timings?.predicted_per_second || 0), 0) / processingSlots.length
|
|
166
|
+
: undefined;
|
|
167
|
+
// Calculate total memory (CPU + Metal GPU memory if available)
|
|
168
|
+
let totalMemory = fetchedMemory ?? undefined;
|
|
169
|
+
if (totalMemory !== undefined && server.metalMemoryMB) {
|
|
170
|
+
// Add Metal memory (convert MB to bytes)
|
|
171
|
+
totalMemory += server.metalMemoryMB * 1024 * 1024;
|
|
172
|
+
}
|
|
173
|
+
return {
|
|
174
|
+
server,
|
|
175
|
+
healthy,
|
|
176
|
+
uptime,
|
|
177
|
+
modelLoaded: props !== null,
|
|
178
|
+
modelName: server.modelName,
|
|
179
|
+
contextSize: props?.default_generation_settings?.n_ctx || server.ctxSize,
|
|
180
|
+
totalSlots,
|
|
181
|
+
activeSlots,
|
|
182
|
+
idleSlots,
|
|
183
|
+
slots,
|
|
184
|
+
avgPromptSpeed,
|
|
185
|
+
avgGenerateSpeed,
|
|
186
|
+
processMemory: totalMemory,
|
|
187
|
+
processCpuUsage: fetchedCpu ?? undefined,
|
|
188
|
+
timestamp: now,
|
|
189
|
+
stale: false,
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Collect complete monitoring data (server + system metrics)
|
|
194
|
+
*/
|
|
195
|
+
async collectMonitorData(server, updateInterval = 2000) {
|
|
196
|
+
// Collect server and system metrics in parallel
|
|
197
|
+
const [serverMetrics, systemMetrics] = await Promise.all([
|
|
198
|
+
this.collectServerMetrics(server),
|
|
199
|
+
system_collector_js_1.systemCollector.collectSystemMetrics(),
|
|
200
|
+
]);
|
|
201
|
+
return {
|
|
202
|
+
server: serverMetrics,
|
|
203
|
+
system: systemMetrics,
|
|
204
|
+
lastUpdated: new Date(),
|
|
205
|
+
updateInterval,
|
|
206
|
+
consecutiveFailures: 0,
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
exports.MetricsAggregator = MetricsAggregator;
|
|
211
|
+
//# sourceMappingURL=metrics-aggregator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metrics-aggregator.js","sourceRoot":"","sources":["../../src/lib/metrics-aggregator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { SystemMetrics } from '../types/monitor-types.js';
|
|
2
|
+
/**
|
|
3
|
+
* System metrics collector using macmon (optional) and vm_stat (fallback)
|
|
4
|
+
* Provides GPU, CPU, ANE, and memory metrics on macOS
|
|
5
|
+
*/
|
|
6
|
+
export declare class SystemCollector {
|
|
7
|
+
private macmonPath;
|
|
8
|
+
private macmonAvailable;
|
|
9
|
+
private lastSystemMetrics;
|
|
10
|
+
private lastCollectionTime;
|
|
11
|
+
private readonly CACHE_TTL_MS;
|
|
12
|
+
private collectingLock;
|
|
13
|
+
private pCoreCount;
|
|
14
|
+
private eCoreCount;
|
|
15
|
+
private totalCores;
|
|
16
|
+
constructor(macmonPath?: string);
|
|
17
|
+
/**
|
|
18
|
+
* Get CPU core counts for weighted average calculation
|
|
19
|
+
*/
|
|
20
|
+
private initializeCoreCount;
|
|
21
|
+
/**
|
|
22
|
+
* Check if macmon is available
|
|
23
|
+
*/
|
|
24
|
+
private checkMacmonAvailability;
|
|
25
|
+
/**
|
|
26
|
+
* Parse macmon JSON output
|
|
27
|
+
* Expected format from 'macmon pipe':
|
|
28
|
+
* {
|
|
29
|
+
* "gpu_usage": [count, percentage],
|
|
30
|
+
* "pcpu_usage": [count, percentage],
|
|
31
|
+
* "ecpu_usage": [count, percentage],
|
|
32
|
+
* "ane_power": number,
|
|
33
|
+
* "temp": {"cpu_temp_avg": number, "gpu_temp_avg": number}
|
|
34
|
+
* }
|
|
35
|
+
*/
|
|
36
|
+
private parseMacmonJson;
|
|
37
|
+
/**
|
|
38
|
+
* Collect macmon metrics (GPU, CPU, ANE)
|
|
39
|
+
* Uses 'macmon pipe' which outputs one JSON line per update
|
|
40
|
+
* Spawns macmon, reads one line, and kills it to prevent process leaks
|
|
41
|
+
*/
|
|
42
|
+
private getMacmonMetrics;
|
|
43
|
+
/**
|
|
44
|
+
* Parse vm_stat output for memory metrics
|
|
45
|
+
* Expected format:
|
|
46
|
+
* Pages free: 123456.
|
|
47
|
+
* Pages active: 234567.
|
|
48
|
+
* Pages inactive: 345678.
|
|
49
|
+
* Pages speculative: 45678.
|
|
50
|
+
* Pages throttled: 0.
|
|
51
|
+
* Pages wired down: 123456.
|
|
52
|
+
* Pages purgeable count: 0.
|
|
53
|
+
* "Translation faults": 12345678.
|
|
54
|
+
* Pages copy-on-write: 123456.
|
|
55
|
+
* ...
|
|
56
|
+
*/
|
|
57
|
+
private parseVmStatOutput;
|
|
58
|
+
/**
|
|
59
|
+
* Get total system memory from sysctl
|
|
60
|
+
* Returns installed RAM size in bytes
|
|
61
|
+
*/
|
|
62
|
+
private getTotalMemory;
|
|
63
|
+
/**
|
|
64
|
+
* Collect vm_stat memory metrics + total system memory from sysctl
|
|
65
|
+
*/
|
|
66
|
+
private getMemoryMetrics;
|
|
67
|
+
/**
|
|
68
|
+
* Collect all system metrics
|
|
69
|
+
* Attempts macmon first (GPU/CPU/ANE), always gets memory from vm_stat + sysctl
|
|
70
|
+
* Caches results for 4s to prevent spawning multiple macmon processes
|
|
71
|
+
*/
|
|
72
|
+
collectSystemMetrics(): Promise<SystemMetrics>;
|
|
73
|
+
/**
|
|
74
|
+
* Internal method to actually collect system metrics
|
|
75
|
+
* Called by collectSystemMetrics with caching/locking
|
|
76
|
+
*/
|
|
77
|
+
private doCollectSystemMetrics;
|
|
78
|
+
}
|
|
79
|
+
export declare const systemCollector: SystemCollector;
|
|
80
|
+
//# sourceMappingURL=system-collector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"system-collector.d.ts","sourceRoot":"","sources":["../../src/lib/system-collector.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAE1D;;;GAGG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,eAAe,CAAwB;IAC/C,OAAO,CAAC,iBAAiB,CAA8B;IACvD,OAAO,CAAC,kBAAkB,CAAa;IACvC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAQ;IACrC,OAAO,CAAC,cAAc,CAAuC;IAC7D,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,UAAU,CAAa;gBAEnB,UAAU,GAAE,MAAmC;IAK3D;;OAEG;YACW,mBAAmB;IA4BjC;;OAEG;YACW,uBAAuB;IAerC;;;;;;;;;;OAUG;IACH,OAAO,CAAC,eAAe;IAiDvB;;;;OAIG;YACW,gBAAgB;IA2B9B;;;;;;;;;;;;;OAaG;IACH,OAAO,CAAC,iBAAiB;IA6BzB;;;OAGG;YACW,cAAc;IAS5B;;OAEG;YACW,gBAAgB;IAmB9B;;;;OAIG;IACG,oBAAoB,IAAI,OAAO,CAAC,aAAa,CAAC;IA0BpD;;;OAGG;YACW,sBAAsB;CAkCrC;AAGD,eAAO,MAAM,eAAe,iBAAwB,CAAC"}
|