tinytsdk 0.2.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/README.md +130 -0
- package/dist/client.d.ts +58 -0
- package/dist/index.cjs.js +382 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.esm.js +355 -0
- package/dist/proto.d.ts +111 -0
- package/dist/react/MetricsBar.d.ts +13 -0
- package/dist/react/MetricsPanel.d.ts +8 -0
- package/dist/react/TinyTrackProvider.d.ts +30 -0
- package/dist/react/dashboard/Dashboard.d.ts +11 -0
- package/dist/react/dashboard/Sparkline.d.ts +10 -0
- package/dist/react/dashboard/TimeSeriesChart.d.ts +12 -0
- package/dist/react/dashboard/Timeline.d.ts +13 -0
- package/dist/react/dashboard/utils.d.ts +16 -0
- package/dist/react/index.d.ts +13 -0
- package/dist/react/theme.d.ts +111 -0
- package/dist/react.cjs.js +1217 -0
- package/dist/react.esm.js +1203 -0
- package/dist/stories/Dashboard.stories.d.ts +9 -0
- package/dist/stories/MetricsBar.stories.d.ts +12 -0
- package/dist/stories/MetricsPanel.stories.d.ts +8 -0
- package/dist/stories/MockProvider.d.ts +20 -0
- package/dist/stories/TimeSeriesChart.stories.d.ts +12 -0
- package/dist/stories/Timeline.stories.d.ts +11 -0
- package/package.json +76 -0
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TinyTrack binary protocol parser (v1 + v2).
|
|
3
|
+
*
|
|
4
|
+
* Wire format (big-endian):
|
|
5
|
+
* [magic:1][version:1][type:1][length:2][timestamp:4][checksum:1] + payload
|
|
6
|
+
*
|
|
7
|
+
* tt_metrics payload (52 bytes, little-endian packed struct):
|
|
8
|
+
* timestamp:8 cpu:2 mem:2 net_rx:4 net_tx:4
|
|
9
|
+
* load1:2 load5:2 load15:2 nr_running:4 nr_total:4
|
|
10
|
+
* du_usage:2 du_total:8 du_free:8
|
|
11
|
+
*/
|
|
12
|
+
const PROTO_MAGIC = 0xaa;
|
|
13
|
+
const HEADER_SIZE = 10;
|
|
14
|
+
// Packet types
|
|
15
|
+
const PKT_METRICS = 0x01;
|
|
16
|
+
const PKT_CONFIG = 0x02;
|
|
17
|
+
const PKT_CMD = 0x04;
|
|
18
|
+
const PKT_ACK = 0x05;
|
|
19
|
+
const PKT_HISTORY_REQ = 0x10;
|
|
20
|
+
const PKT_HISTORY_RESP = 0x11;
|
|
21
|
+
const PKT_SUBSCRIBE = 0x12;
|
|
22
|
+
const PKT_RING_STATS = 0x13;
|
|
23
|
+
const PKT_SYS_INFO = 0x14;
|
|
24
|
+
// Ring levels
|
|
25
|
+
const RING_L1 = 0x01;
|
|
26
|
+
const RING_L2 = 0x02;
|
|
27
|
+
const RING_L3 = 0x03;
|
|
28
|
+
// Commands
|
|
29
|
+
const CMD_SET_INTERVAL = 0x01;
|
|
30
|
+
const CMD_GET_SNAPSHOT = 0x03;
|
|
31
|
+
const CMD_GET_RING_STATS = 0x10;
|
|
32
|
+
const CMD_GET_SYS_INFO = 0x11;
|
|
33
|
+
const CMD_START = 0x12;
|
|
34
|
+
const CMD_STOP = 0x13;
|
|
35
|
+
/** Parse the 10-byte header. Returns null if buffer is too short or magic is wrong. */
|
|
36
|
+
function parseHeader(buf, offset = 0) {
|
|
37
|
+
if (buf.byteLength - offset < HEADER_SIZE)
|
|
38
|
+
return null;
|
|
39
|
+
const v = new DataView(buf, offset);
|
|
40
|
+
if (v.getUint8(0) !== PROTO_MAGIC)
|
|
41
|
+
return null;
|
|
42
|
+
const version = v.getUint8(1);
|
|
43
|
+
const type = v.getUint8(2);
|
|
44
|
+
const length = v.getUint16(3, false); // big-endian
|
|
45
|
+
const timestamp = v.getUint32(5, false);
|
|
46
|
+
if (buf.byteLength - offset < HEADER_SIZE + length)
|
|
47
|
+
return null;
|
|
48
|
+
return {
|
|
49
|
+
type,
|
|
50
|
+
version,
|
|
51
|
+
timestamp,
|
|
52
|
+
payload: new DataView(buf, offset + HEADER_SIZE, length),
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
/** Parse PKT_METRICS payload (52 bytes, little-endian). */
|
|
56
|
+
function parseMetrics(p) {
|
|
57
|
+
// uint64 LE: lo word at offset 0, hi word at offset 4
|
|
58
|
+
const tsLo = p.getUint32(0, true);
|
|
59
|
+
const tsHi = p.getUint32(4, true);
|
|
60
|
+
const timestamp = tsHi * 0x100000000 + tsLo;
|
|
61
|
+
return {
|
|
62
|
+
timestamp,
|
|
63
|
+
cpu: p.getUint16(8, true),
|
|
64
|
+
mem: p.getUint16(10, true),
|
|
65
|
+
netRx: p.getUint32(12, true),
|
|
66
|
+
netTx: p.getUint32(16, true),
|
|
67
|
+
load1: p.getUint16(20, true),
|
|
68
|
+
load5: p.getUint16(22, true),
|
|
69
|
+
load15: p.getUint16(24, true),
|
|
70
|
+
nrRunning: p.getUint32(26, true),
|
|
71
|
+
nrTotal: p.getUint32(30, true),
|
|
72
|
+
duUsage: p.getUint16(34, true),
|
|
73
|
+
duTotal: readUint64LE(p, 36),
|
|
74
|
+
duFree: readUint64LE(p, 44),
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
/** Parse PKT_CONFIG payload (5 bytes). */
|
|
78
|
+
function parseConfig(p) {
|
|
79
|
+
return {
|
|
80
|
+
intervalMs: p.getUint32(0, false),
|
|
81
|
+
alertsEnabled: p.getUint8(4) !== 0,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
/** Parse PKT_ACK payload (2 bytes). */
|
|
85
|
+
function parseAck(p) {
|
|
86
|
+
return { cmdType: p.getUint8(0), status: p.getUint8(1) };
|
|
87
|
+
}
|
|
88
|
+
/** Parse PKT_STATS payload (75 bytes = 3 × 25). */
|
|
89
|
+
function parseStats(p) {
|
|
90
|
+
return {
|
|
91
|
+
l1: parseRingStat(p, 0),
|
|
92
|
+
l2: parseRingStat(p, 29),
|
|
93
|
+
l3: parseRingStat(p, 58),
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
/** Parse PKT_HISTORY_RESP payload. */
|
|
97
|
+
function parseHistoryResp(p) {
|
|
98
|
+
const level = p.getUint8(0);
|
|
99
|
+
const count = p.getUint16(1, false);
|
|
100
|
+
const flags = p.getUint8(3);
|
|
101
|
+
const samples = [];
|
|
102
|
+
for (let i = 0; i < count; i++) {
|
|
103
|
+
const off = 4 + i * 52;
|
|
104
|
+
samples.push(parseMetrics(new DataView(p.buffer, p.byteOffset + off, 52)));
|
|
105
|
+
}
|
|
106
|
+
return { level, count, last: (flags & 0x01) !== 0, samples };
|
|
107
|
+
}
|
|
108
|
+
/** Parse PKT_SYS_INFO payload (168 bytes). */
|
|
109
|
+
function parseSysInfo(p) {
|
|
110
|
+
const dec = new TextDecoder();
|
|
111
|
+
const hostname = dec.decode(new Uint8Array(p.buffer, p.byteOffset, 64)).replace(/\0.*/, '');
|
|
112
|
+
const osType = dec.decode(new Uint8Array(p.buffer, p.byteOffset + 64, 64)).replace(/\0.*/, '');
|
|
113
|
+
return {
|
|
114
|
+
hostname,
|
|
115
|
+
osType,
|
|
116
|
+
uptimeSec: readUint64BE(p, 128), // server: htobe64
|
|
117
|
+
slotsL1: p.getUint32(136, false), // server: htonl (BE)
|
|
118
|
+
slotsL2: p.getUint32(140, false),
|
|
119
|
+
slotsL3: p.getUint32(144, false),
|
|
120
|
+
intervalMs: p.getUint32(148, false),
|
|
121
|
+
aggL2Ms: p.getUint32(152, false),
|
|
122
|
+
aggL3Ms: p.getUint32(156, false),
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
// ---------------------------------------------------------------------------
|
|
126
|
+
// Command builders
|
|
127
|
+
// ---------------------------------------------------------------------------
|
|
128
|
+
function buildCmd(cmdType, arg = 0) {
|
|
129
|
+
const buf = new ArrayBuffer(HEADER_SIZE + 9);
|
|
130
|
+
const h = new DataView(buf);
|
|
131
|
+
const ts = Math.floor(Date.now() / 1000);
|
|
132
|
+
h.setUint8(0, PROTO_MAGIC);
|
|
133
|
+
h.setUint8(1, 0x01); // v1
|
|
134
|
+
h.setUint8(2, PKT_CMD);
|
|
135
|
+
h.setUint16(3, 9, false);
|
|
136
|
+
h.setUint32(5, ts, false);
|
|
137
|
+
h.setUint8(9, calcChecksum(h));
|
|
138
|
+
// payload
|
|
139
|
+
h.setUint8(10, cmdType);
|
|
140
|
+
h.setUint32(11, arg, false);
|
|
141
|
+
return buf;
|
|
142
|
+
}
|
|
143
|
+
function buildHistoryReq(level, maxCount = 0, fromTs = 0, toTs = 0) {
|
|
144
|
+
const buf = new ArrayBuffer(HEADER_SIZE + 19);
|
|
145
|
+
const h = new DataView(buf);
|
|
146
|
+
const ts = Math.floor(Date.now() / 1000);
|
|
147
|
+
h.setUint8(0, PROTO_MAGIC);
|
|
148
|
+
h.setUint8(1, 0x02); // v2
|
|
149
|
+
h.setUint8(2, PKT_HISTORY_REQ);
|
|
150
|
+
h.setUint16(3, 19, false);
|
|
151
|
+
h.setUint32(5, ts, false);
|
|
152
|
+
h.setUint8(9, calcChecksum(h));
|
|
153
|
+
// payload: level(1) from_ts(8) to_ts(8) max_count(2)
|
|
154
|
+
h.setUint8(10, level);
|
|
155
|
+
writeUint64BE(h, 11, fromTs);
|
|
156
|
+
writeUint64BE(h, 19, toTs);
|
|
157
|
+
h.setUint16(27, maxCount, false);
|
|
158
|
+
return buf;
|
|
159
|
+
}
|
|
160
|
+
function buildSubscribe(level, intervalMs = 0) {
|
|
161
|
+
const buf = new ArrayBuffer(HEADER_SIZE + 6);
|
|
162
|
+
const h = new DataView(buf);
|
|
163
|
+
const ts = Math.floor(Date.now() / 1000);
|
|
164
|
+
h.setUint8(0, PROTO_MAGIC);
|
|
165
|
+
h.setUint8(1, 0x02);
|
|
166
|
+
h.setUint8(2, PKT_SUBSCRIBE);
|
|
167
|
+
h.setUint16(3, 6, false);
|
|
168
|
+
h.setUint32(5, ts, false);
|
|
169
|
+
h.setUint8(9, calcChecksum(h));
|
|
170
|
+
h.setUint8(10, level);
|
|
171
|
+
h.setUint32(11, intervalMs, false);
|
|
172
|
+
h.setUint8(15, 0);
|
|
173
|
+
return buf;
|
|
174
|
+
}
|
|
175
|
+
// ---------------------------------------------------------------------------
|
|
176
|
+
// Helpers
|
|
177
|
+
// ---------------------------------------------------------------------------
|
|
178
|
+
function calcChecksum(h) {
|
|
179
|
+
let cs = 0;
|
|
180
|
+
for (let i = 0; i < 9; i++)
|
|
181
|
+
cs ^= h.getUint8(i);
|
|
182
|
+
return cs;
|
|
183
|
+
}
|
|
184
|
+
function parseRingStat(p, off) {
|
|
185
|
+
return {
|
|
186
|
+
level: p.getUint8(off),
|
|
187
|
+
capacity: p.getUint32(off + 1, false), // htonl (BE)
|
|
188
|
+
head: p.getUint32(off + 5, false), // htonl (BE)
|
|
189
|
+
filled: p.getUint32(off + 9, false), // htonl (BE)
|
|
190
|
+
firstTs: readUint64LE(p, off + 13), // no hton, native LE
|
|
191
|
+
lastTs: readUint64LE(p, off + 21), // no hton, native LE
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
function readUint64LE(v, off) {
|
|
195
|
+
const lo = v.getUint32(off, true);
|
|
196
|
+
const hi = v.getUint32(off + 4, true);
|
|
197
|
+
return hi * 0x100000000 + lo;
|
|
198
|
+
}
|
|
199
|
+
function readUint64BE(v, off) {
|
|
200
|
+
const hi = v.getUint32(off, false);
|
|
201
|
+
const lo = v.getUint32(off + 4, false);
|
|
202
|
+
return hi * 0x100000000 + lo;
|
|
203
|
+
}
|
|
204
|
+
function writeUint64BE(v, off, val) {
|
|
205
|
+
const hi = Math.floor(val / 0x100000000);
|
|
206
|
+
const lo = val >>> 0;
|
|
207
|
+
v.setUint32(off, hi, false);
|
|
208
|
+
v.setUint32(off + 4, lo, false);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* TinyTrackClient — WebSocket client for the tinytrack gateway.
|
|
213
|
+
*
|
|
214
|
+
* Usage:
|
|
215
|
+
* const client = new TinyTrackClient('ws://localhost:4026');
|
|
216
|
+
* client.on('metrics', m => console.log(m.cpu / 100, '%'));
|
|
217
|
+
* client.connect();
|
|
218
|
+
*/
|
|
219
|
+
class TinyTrackClient {
|
|
220
|
+
constructor(url, opts = {}) {
|
|
221
|
+
var _a, _b, _c, _d;
|
|
222
|
+
this.ws = null;
|
|
223
|
+
this.listeners = new Map();
|
|
224
|
+
this.retries = 0;
|
|
225
|
+
this._closed = false;
|
|
226
|
+
// Normalise: strip trailing path, we'll append opts.path
|
|
227
|
+
this.url = url.replace(/\/websocket\/?$/, '');
|
|
228
|
+
this.opts = {
|
|
229
|
+
reconnect: (_a = opts.reconnect) !== null && _a !== void 0 ? _a : true,
|
|
230
|
+
reconnectDelay: (_b = opts.reconnectDelay) !== null && _b !== void 0 ? _b : 2000,
|
|
231
|
+
maxRetries: (_c = opts.maxRetries) !== null && _c !== void 0 ? _c : 0,
|
|
232
|
+
path: (_d = opts.path) !== null && _d !== void 0 ? _d : '/websocket',
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
// ---------------------------------------------------------------------------
|
|
236
|
+
// Lifecycle
|
|
237
|
+
// ---------------------------------------------------------------------------
|
|
238
|
+
connect() {
|
|
239
|
+
this._closed = false;
|
|
240
|
+
this._open();
|
|
241
|
+
return this;
|
|
242
|
+
}
|
|
243
|
+
disconnect() {
|
|
244
|
+
var _a;
|
|
245
|
+
this._closed = true;
|
|
246
|
+
(_a = this.ws) === null || _a === void 0 ? void 0 : _a.close();
|
|
247
|
+
this.ws = null;
|
|
248
|
+
}
|
|
249
|
+
get connected() {
|
|
250
|
+
var _a;
|
|
251
|
+
return ((_a = this.ws) === null || _a === void 0 ? void 0 : _a.readyState) === WebSocket.OPEN;
|
|
252
|
+
}
|
|
253
|
+
// ---------------------------------------------------------------------------
|
|
254
|
+
// Commands
|
|
255
|
+
// ---------------------------------------------------------------------------
|
|
256
|
+
getSnapshot() {
|
|
257
|
+
this._send(buildCmd(CMD_GET_SNAPSHOT));
|
|
258
|
+
}
|
|
259
|
+
getStats() {
|
|
260
|
+
this._send(buildCmd(CMD_GET_RING_STATS));
|
|
261
|
+
}
|
|
262
|
+
getSysInfo() {
|
|
263
|
+
this._send(buildCmd(CMD_GET_SYS_INFO));
|
|
264
|
+
}
|
|
265
|
+
setInterval(ms) {
|
|
266
|
+
this._send(buildCmd(CMD_SET_INTERVAL, ms));
|
|
267
|
+
}
|
|
268
|
+
start() {
|
|
269
|
+
this._send(buildCmd(CMD_START));
|
|
270
|
+
}
|
|
271
|
+
stop() {
|
|
272
|
+
this._send(buildCmd(CMD_STOP));
|
|
273
|
+
}
|
|
274
|
+
getHistory(level, maxCount = 60, fromTs = 0, toTs = 0) {
|
|
275
|
+
this._send(buildHistoryReq(level, maxCount, fromTs, toTs));
|
|
276
|
+
}
|
|
277
|
+
subscribe(level, intervalMs = 0) {
|
|
278
|
+
this._send(buildSubscribe(level, intervalMs));
|
|
279
|
+
}
|
|
280
|
+
// ---------------------------------------------------------------------------
|
|
281
|
+
// Events
|
|
282
|
+
// ---------------------------------------------------------------------------
|
|
283
|
+
on(event, fn) {
|
|
284
|
+
if (!this.listeners.has(event))
|
|
285
|
+
this.listeners.set(event, new Set());
|
|
286
|
+
this.listeners.get(event).add(fn);
|
|
287
|
+
return this;
|
|
288
|
+
}
|
|
289
|
+
off(event, fn) {
|
|
290
|
+
var _a;
|
|
291
|
+
(_a = this.listeners.get(event)) === null || _a === void 0 ? void 0 : _a.delete(fn);
|
|
292
|
+
return this;
|
|
293
|
+
}
|
|
294
|
+
// ---------------------------------------------------------------------------
|
|
295
|
+
// Private
|
|
296
|
+
// ---------------------------------------------------------------------------
|
|
297
|
+
_open() {
|
|
298
|
+
const wsUrl = this.url + this.opts.path;
|
|
299
|
+
const ws = new WebSocket(wsUrl);
|
|
300
|
+
ws.binaryType = 'arraybuffer';
|
|
301
|
+
this.ws = ws;
|
|
302
|
+
ws.onopen = () => {
|
|
303
|
+
this.retries = 0;
|
|
304
|
+
this._emit('open');
|
|
305
|
+
};
|
|
306
|
+
ws.onclose = (e) => {
|
|
307
|
+
this._emit('close', e.code, e.reason);
|
|
308
|
+
if (!this._closed && this.opts.reconnect) {
|
|
309
|
+
const max = this.opts.maxRetries;
|
|
310
|
+
if (max === 0 || this.retries < max) {
|
|
311
|
+
this.retries++;
|
|
312
|
+
setTimeout(() => this._open(), this.opts.reconnectDelay);
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
};
|
|
316
|
+
ws.onerror = (e) => this._emit('error', e);
|
|
317
|
+
ws.onmessage = (e) => {
|
|
318
|
+
const frame = parseHeader(e.data);
|
|
319
|
+
if (!frame)
|
|
320
|
+
return;
|
|
321
|
+
switch (frame.type) {
|
|
322
|
+
case PKT_METRICS:
|
|
323
|
+
this._emit('metrics', parseMetrics(frame.payload));
|
|
324
|
+
break;
|
|
325
|
+
case PKT_CONFIG:
|
|
326
|
+
this._emit('config', parseConfig(frame.payload));
|
|
327
|
+
break;
|
|
328
|
+
case PKT_ACK:
|
|
329
|
+
this._emit('ack', parseAck(frame.payload));
|
|
330
|
+
break;
|
|
331
|
+
case PKT_RING_STATS:
|
|
332
|
+
this._emit('stats', parseStats(frame.payload));
|
|
333
|
+
break;
|
|
334
|
+
case PKT_HISTORY_RESP:
|
|
335
|
+
this._emit('history', parseHistoryResp(frame.payload));
|
|
336
|
+
break;
|
|
337
|
+
case PKT_SYS_INFO:
|
|
338
|
+
this._emit('sysinfo', parseSysInfo(frame.payload));
|
|
339
|
+
break;
|
|
340
|
+
}
|
|
341
|
+
};
|
|
342
|
+
}
|
|
343
|
+
_send(buf) {
|
|
344
|
+
var _a;
|
|
345
|
+
if (((_a = this.ws) === null || _a === void 0 ? void 0 : _a.readyState) === WebSocket.OPEN) {
|
|
346
|
+
this.ws.send(buf);
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
_emit(event, ...args) {
|
|
350
|
+
var _a;
|
|
351
|
+
(_a = this.listeners.get(event)) === null || _a === void 0 ? void 0 : _a.forEach((fn) => fn(...args));
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
export { CMD_GET_RING_STATS, CMD_GET_SNAPSHOT, CMD_GET_SYS_INFO, CMD_SET_INTERVAL, CMD_START, CMD_STOP, PKT_ACK, PKT_CONFIG, PKT_HISTORY_RESP, PKT_METRICS, PKT_RING_STATS, PKT_SYS_INFO, RING_L1, RING_L2, RING_L3, TinyTrackClient, buildCmd, buildHistoryReq, buildSubscribe, parseAck, parseConfig, parseHeader, parseHistoryResp, parseMetrics, parseStats, parseSysInfo };
|
package/dist/proto.d.ts
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TinyTrack binary protocol parser (v1 + v2).
|
|
3
|
+
*
|
|
4
|
+
* Wire format (big-endian):
|
|
5
|
+
* [magic:1][version:1][type:1][length:2][timestamp:4][checksum:1] + payload
|
|
6
|
+
*
|
|
7
|
+
* tt_metrics payload (52 bytes, little-endian packed struct):
|
|
8
|
+
* timestamp:8 cpu:2 mem:2 net_rx:4 net_tx:4
|
|
9
|
+
* load1:2 load5:2 load15:2 nr_running:4 nr_total:4
|
|
10
|
+
* du_usage:2 du_total:8 du_free:8
|
|
11
|
+
*/
|
|
12
|
+
export declare const PROTO_MAGIC = 170;
|
|
13
|
+
export declare const HEADER_SIZE = 10;
|
|
14
|
+
export declare const PKT_METRICS = 1;
|
|
15
|
+
export declare const PKT_CONFIG = 2;
|
|
16
|
+
export declare const PKT_ALERT = 3;
|
|
17
|
+
export declare const PKT_CMD = 4;
|
|
18
|
+
export declare const PKT_ACK = 5;
|
|
19
|
+
export declare const PKT_HISTORY_REQ = 16;
|
|
20
|
+
export declare const PKT_HISTORY_RESP = 17;
|
|
21
|
+
export declare const PKT_SUBSCRIBE = 18;
|
|
22
|
+
export declare const PKT_RING_STATS = 19;
|
|
23
|
+
export declare const PKT_SYS_INFO = 20;
|
|
24
|
+
export declare const RING_L1 = 1;
|
|
25
|
+
export declare const RING_L2 = 2;
|
|
26
|
+
export declare const RING_L3 = 3;
|
|
27
|
+
export declare const CMD_SET_INTERVAL = 1;
|
|
28
|
+
export declare const CMD_SET_ALERTS = 2;
|
|
29
|
+
export declare const CMD_GET_SNAPSHOT = 3;
|
|
30
|
+
export declare const CMD_GET_RING_STATS = 16;
|
|
31
|
+
export declare const CMD_GET_SYS_INFO = 17;
|
|
32
|
+
export declare const CMD_START = 18;
|
|
33
|
+
export declare const CMD_STOP = 19;
|
|
34
|
+
export declare const ACK_OK = 0;
|
|
35
|
+
export declare const ACK_ERROR = 1;
|
|
36
|
+
export interface TtMetrics {
|
|
37
|
+
timestamp: number;
|
|
38
|
+
cpu: number;
|
|
39
|
+
mem: number;
|
|
40
|
+
netRx: number;
|
|
41
|
+
netTx: number;
|
|
42
|
+
load1: number;
|
|
43
|
+
load5: number;
|
|
44
|
+
load15: number;
|
|
45
|
+
nrRunning: number;
|
|
46
|
+
nrTotal: number;
|
|
47
|
+
duUsage: number;
|
|
48
|
+
duTotal: number;
|
|
49
|
+
duFree: number;
|
|
50
|
+
}
|
|
51
|
+
export interface TtConfig {
|
|
52
|
+
intervalMs: number;
|
|
53
|
+
alertsEnabled: boolean;
|
|
54
|
+
}
|
|
55
|
+
export interface TtAck {
|
|
56
|
+
cmdType: number;
|
|
57
|
+
status: number;
|
|
58
|
+
}
|
|
59
|
+
export interface TtRingStat {
|
|
60
|
+
level: number;
|
|
61
|
+
capacity: number;
|
|
62
|
+
head: number;
|
|
63
|
+
filled: number;
|
|
64
|
+
firstTs: number;
|
|
65
|
+
lastTs: number;
|
|
66
|
+
}
|
|
67
|
+
export interface TtStats {
|
|
68
|
+
l1: TtRingStat;
|
|
69
|
+
l2: TtRingStat;
|
|
70
|
+
l3: TtRingStat;
|
|
71
|
+
}
|
|
72
|
+
export interface TtSysInfo {
|
|
73
|
+
hostname: string;
|
|
74
|
+
osType: string;
|
|
75
|
+
uptimeSec: number;
|
|
76
|
+
slotsL1: number;
|
|
77
|
+
slotsL2: number;
|
|
78
|
+
slotsL3: number;
|
|
79
|
+
intervalMs: number;
|
|
80
|
+
aggL2Ms: number;
|
|
81
|
+
aggL3Ms: number;
|
|
82
|
+
}
|
|
83
|
+
export interface TtHistoryResp {
|
|
84
|
+
level: number;
|
|
85
|
+
count: number;
|
|
86
|
+
last: boolean;
|
|
87
|
+
samples: TtMetrics[];
|
|
88
|
+
}
|
|
89
|
+
export interface TtFrame {
|
|
90
|
+
type: number;
|
|
91
|
+
version: number;
|
|
92
|
+
timestamp: number;
|
|
93
|
+
payload: DataView;
|
|
94
|
+
}
|
|
95
|
+
/** Parse the 10-byte header. Returns null if buffer is too short or magic is wrong. */
|
|
96
|
+
export declare function parseHeader(buf: ArrayBuffer, offset?: number): TtFrame | null;
|
|
97
|
+
/** Parse PKT_METRICS payload (52 bytes, little-endian). */
|
|
98
|
+
export declare function parseMetrics(p: DataView): TtMetrics;
|
|
99
|
+
/** Parse PKT_CONFIG payload (5 bytes). */
|
|
100
|
+
export declare function parseConfig(p: DataView): TtConfig;
|
|
101
|
+
/** Parse PKT_ACK payload (2 bytes). */
|
|
102
|
+
export declare function parseAck(p: DataView): TtAck;
|
|
103
|
+
/** Parse PKT_STATS payload (75 bytes = 3 × 25). */
|
|
104
|
+
export declare function parseStats(p: DataView): TtStats;
|
|
105
|
+
/** Parse PKT_HISTORY_RESP payload. */
|
|
106
|
+
export declare function parseHistoryResp(p: DataView): TtHistoryResp;
|
|
107
|
+
/** Parse PKT_SYS_INFO payload (168 bytes). */
|
|
108
|
+
export declare function parseSysInfo(p: DataView): TtSysInfo;
|
|
109
|
+
export declare function buildCmd(cmdType: number, arg?: number): ArrayBuffer;
|
|
110
|
+
export declare function buildHistoryReq(level: number, maxCount?: number, fromTs?: number, toTs?: number): ArrayBuffer;
|
|
111
|
+
export declare function buildSubscribe(level: number, intervalMs?: number): ArrayBuffer;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { CSSProperties } from 'react';
|
|
2
|
+
import { TtTheme } from './theme.js';
|
|
3
|
+
export interface MetricsBarProps {
|
|
4
|
+
className?: string;
|
|
5
|
+
style?: CSSProperties;
|
|
6
|
+
showDisk?: boolean;
|
|
7
|
+
showNet?: boolean;
|
|
8
|
+
/** Override theme tokens */
|
|
9
|
+
theme?: Partial<TtTheme>;
|
|
10
|
+
/** Force mobile layout (auto-detected if not set) */
|
|
11
|
+
compact?: boolean;
|
|
12
|
+
}
|
|
13
|
+
export declare function MetricsBar({ className, style, showDisk, showNet, theme: themeProp, compact, }: MetricsBarProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { CSSProperties } from 'react';
|
|
2
|
+
import { TtTheme } from './theme.js';
|
|
3
|
+
export interface MetricsPanelProps {
|
|
4
|
+
className?: string;
|
|
5
|
+
style?: CSSProperties;
|
|
6
|
+
theme?: Partial<TtTheme>;
|
|
7
|
+
}
|
|
8
|
+
export declare function MetricsPanel({ className, style, theme: themeProp }: MetricsPanelProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
import { TinyTrackClient, TtMetrics, TtConfig, TtStats, TtSysInfo } from '../client.js';
|
|
3
|
+
interface TinyTrackContextValue {
|
|
4
|
+
client: TinyTrackClient | null;
|
|
5
|
+
connected: boolean;
|
|
6
|
+
sysinfo: TtSysInfo | null;
|
|
7
|
+
streaming: boolean;
|
|
8
|
+
setStreaming: (v: boolean) => void;
|
|
9
|
+
}
|
|
10
|
+
declare const TinyTrackContext: import("react").Context<TinyTrackContextValue>;
|
|
11
|
+
export { TinyTrackContext };
|
|
12
|
+
export interface TinyTrackProviderProps {
|
|
13
|
+
url: string;
|
|
14
|
+
children: ReactNode;
|
|
15
|
+
reconnect?: boolean;
|
|
16
|
+
reconnectDelay?: number;
|
|
17
|
+
}
|
|
18
|
+
export declare function TinyTrackProvider({ url, children, reconnect, reconnectDelay }: TinyTrackProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
19
|
+
export declare function useTinyTrack(): TinyTrackContextValue;
|
|
20
|
+
export declare function useMetrics(): {
|
|
21
|
+
client: TinyTrackClient | null;
|
|
22
|
+
connected: boolean;
|
|
23
|
+
metrics: TtMetrics | null;
|
|
24
|
+
config: TtConfig | null;
|
|
25
|
+
stats: TtStats | null;
|
|
26
|
+
sysinfo: TtSysInfo | null;
|
|
27
|
+
streaming: boolean;
|
|
28
|
+
setStreaming: (v: boolean) => void;
|
|
29
|
+
};
|
|
30
|
+
export declare function useHistory(maxSamples?: number): TtMetrics[];
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { CSSProperties } from 'react';
|
|
2
|
+
import { TtTheme } from '../theme.js';
|
|
3
|
+
export type DashboardMode = 'compact' | 'expanded';
|
|
4
|
+
export interface DashboardProps {
|
|
5
|
+
mode?: DashboardMode;
|
|
6
|
+
historySize?: number;
|
|
7
|
+
className?: string;
|
|
8
|
+
style?: CSSProperties;
|
|
9
|
+
theme?: Partial<TtTheme>;
|
|
10
|
+
}
|
|
11
|
+
export declare function Dashboard({ mode: modeProp, historySize, className, style, theme: themeProp }: DashboardProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
interface SparklineProps {
|
|
2
|
+
data: number[];
|
|
3
|
+
max?: number;
|
|
4
|
+
width?: number;
|
|
5
|
+
height?: number;
|
|
6
|
+
color?: string;
|
|
7
|
+
fill?: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function Sparkline({ data, max, width, height, color, fill, }: SparklineProps): import("react/jsx-runtime").JSX.Element | null;
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { CSSProperties } from 'react';
|
|
2
|
+
import { TtTheme } from '../theme.js';
|
|
3
|
+
export interface TimeSeriesChartProps {
|
|
4
|
+
metric: 'cpu' | 'mem' | 'load' | 'net' | 'disk';
|
|
5
|
+
level?: number;
|
|
6
|
+
maxSamples?: number;
|
|
7
|
+
height?: number;
|
|
8
|
+
className?: string;
|
|
9
|
+
style?: CSSProperties;
|
|
10
|
+
theme?: Partial<TtTheme>;
|
|
11
|
+
}
|
|
12
|
+
export declare function TimeSeriesChart({ metric, level, maxSamples, height, className, style, theme: themeProp, }: TimeSeriesChartProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { CSSProperties } from 'react';
|
|
2
|
+
import { TtTheme } from '../theme.js';
|
|
3
|
+
export type TimelineMetric = 'cpu' | 'mem' | 'load' | 'net' | 'disk';
|
|
4
|
+
export interface TimelineProps {
|
|
5
|
+
/** Which metric to visualise. Default: 'cpu' */
|
|
6
|
+
metric?: TimelineMetric;
|
|
7
|
+
/** Height of each ring row in px. Default: 40 */
|
|
8
|
+
rowHeight?: number;
|
|
9
|
+
className?: string;
|
|
10
|
+
style?: CSSProperties;
|
|
11
|
+
theme?: Partial<TtTheme>;
|
|
12
|
+
}
|
|
13
|
+
export declare function Timeline({ metric, rowHeight, className, style, theme: themeProp }: TimelineProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { TtMetrics } from '../../client.js';
|
|
2
|
+
export declare function fmtPct(val: number): string;
|
|
3
|
+
export declare function fmtBytes(bytes: number): string;
|
|
4
|
+
export declare function fmtLoad(val: number): string;
|
|
5
|
+
export declare function fmtUptime(nowMs: number, firstTs: number): string;
|
|
6
|
+
/** Build a simple ASCII bar: ▓▓▓░░░ */
|
|
7
|
+
export declare function bar(pct: number, width?: number): string;
|
|
8
|
+
/** Load trend: compare 1m vs 15m to detect rising/falling */
|
|
9
|
+
export type LoadTrend = 'rising' | 'falling' | 'stable';
|
|
10
|
+
export declare function loadTrend(m: TtMetrics): LoadTrend;
|
|
11
|
+
export interface Alert {
|
|
12
|
+
id: string;
|
|
13
|
+
label: string;
|
|
14
|
+
level: 'warn' | 'crit' | 'ok';
|
|
15
|
+
}
|
|
16
|
+
export declare function detectAlerts(m: TtMetrics, prev: TtMetrics | null): Alert[];
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export { TinyTrackProvider, TinyTrackContext, useTinyTrack, useMetrics, useHistory } from './TinyTrackProvider.js';
|
|
2
|
+
export { MetricsPanel } from './MetricsPanel.js';
|
|
3
|
+
export { MetricsBar } from './MetricsBar.js';
|
|
4
|
+
export { Dashboard } from './dashboard/Dashboard.js';
|
|
5
|
+
export { TimeSeriesChart } from './dashboard/TimeSeriesChart.js';
|
|
6
|
+
export { Timeline } from './dashboard/Timeline.js';
|
|
7
|
+
export { ThemeProvider, useTheme, THEMES } from './theme.js';
|
|
8
|
+
export type { DashboardProps, DashboardMode } from './dashboard/Dashboard.js';
|
|
9
|
+
export type { TimeSeriesChartProps } from './dashboard/TimeSeriesChart.js';
|
|
10
|
+
export type { TimelineProps, TimelineMetric } from './dashboard/Timeline.js';
|
|
11
|
+
export type { MetricsPanelProps } from './MetricsPanel.js';
|
|
12
|
+
export type { MetricsBarProps } from './MetricsBar.js';
|
|
13
|
+
export type { TtTheme, ThemePreset, ThemeProviderProps } from './theme.js';
|