querysub 0.45.0 → 0.50.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/package.json +2 -2
- package/src/-0-hooks/hooks.ts +83 -0
- package/src/-a-archives/archivesBackBlaze.ts +1 -1
- package/src/0-path-value-core/NodePathAuthorities.ts +5 -0
- package/src/0-path-value-core/archiveLocks/ArchiveLocks2.ts +12 -12
- package/src/0-path-value-core/debugLogs.ts +6 -15
- package/src/0-path-value-core/pathValueCore.ts +53 -17
- package/src/2-proxy/PathValueProxyWatcher.ts +18 -10
- package/src/2-proxy/archiveMoveHarness.ts +7 -7
- package/src/2-proxy/garbageCollection.ts +6 -6
- package/src/4-dom/qreact.tsx +8 -1
- package/src/4-querysub/Querysub.ts +9 -4
- package/src/5-diagnostics/GenericFormat.tsx +92 -1
- package/src/5-diagnostics/Table.tsx +7 -12
- package/src/5-diagnostics/TimeGrouper.tsx +24 -15
- package/src/5-diagnostics/memoryValueAudit.ts +7 -10
- package/src/5-diagnostics/nodeMetadata.ts +92 -44
- package/src/5-diagnostics/synchronousLagTracking.ts +1 -1
- package/src/diagnostics/NodeViewer.tsx +3 -4
- package/src/diagnostics/logs/DiskLoggerPage.tsx +28 -12
- package/src/diagnostics/logs/diskLogger.ts +9 -0
- package/src/diagnostics/trackResources.ts +2 -2
- package/src/diagnostics/watchdog.ts +19 -8
- package/src/library-components/TimeRangeSelector.tsx +1 -1
|
@@ -68,6 +68,7 @@ let endTimeURL = new URLParam("endTime", undefined as number | undefined);
|
|
|
68
68
|
|
|
69
69
|
let inspectTimeURL = new URLParam("inspectTime", "");
|
|
70
70
|
|
|
71
|
+
|
|
71
72
|
export class DiskLoggerPage extends qreact.Component {
|
|
72
73
|
state = t.state({
|
|
73
74
|
downloadFilesHash: t.string,
|
|
@@ -118,14 +119,14 @@ export class DiskLoggerPage extends qreact.Component {
|
|
|
118
119
|
let startTime = Number(startTimeURL.value) || (Date.now() - timeInDay);
|
|
119
120
|
let endTime = Number(endTimeURL.value) || (Date.now() + timeInDay);
|
|
120
121
|
const controller = diskLoggerController(getBrowserUrlNode());
|
|
121
|
-
let
|
|
122
|
+
let allFiles: (LogFile & { nodeId: string })[] = [];
|
|
122
123
|
let loadingCount = 0;
|
|
123
124
|
|
|
124
125
|
for (let nodeId of selectedNodesIds) {
|
|
125
126
|
try {
|
|
126
127
|
let newFiles = controller.getRemoteLogFiles(nodeId);
|
|
127
128
|
if (newFiles) {
|
|
128
|
-
|
|
129
|
+
allFiles.push(...newFiles.map(x => ({ ...x, nodeId })));
|
|
129
130
|
} else {
|
|
130
131
|
loadingCount++;
|
|
131
132
|
}
|
|
@@ -133,19 +134,29 @@ export class DiskLoggerPage extends qreact.Component {
|
|
|
133
134
|
console.log("Error reading files", nodeId, e);
|
|
134
135
|
}
|
|
135
136
|
}
|
|
136
|
-
|
|
137
|
-
|
|
137
|
+
//files = files.filter(file => file.startTime <= endTime && file.endTime >= startTime);
|
|
138
|
+
// File to fix some broken files
|
|
139
|
+
allFiles = allFiles.filter(file => file.startTime >= +new Date("1980"));
|
|
138
140
|
let buffers: Buffer[] = [];
|
|
139
141
|
|
|
140
142
|
let firstTime = Number.MAX_SAFE_INTEGER;
|
|
141
143
|
let lastTime = Number.MIN_SAFE_INTEGER;
|
|
142
144
|
|
|
143
|
-
let filesHash = JSON.stringify(
|
|
145
|
+
let filesHash = JSON.stringify(allFiles.map(x => x.path));
|
|
146
|
+
let fileSizeSum = 0;
|
|
147
|
+
let fileCount = 0;
|
|
148
|
+
|
|
149
|
+
let selectedFiles: (LogFile & { nodeId: string })[] = [];
|
|
144
150
|
|
|
145
|
-
for (let file of
|
|
151
|
+
for (let file of allFiles) {
|
|
146
152
|
try {
|
|
147
153
|
if (file.startTime < firstTime) firstTime = file.startTime;
|
|
148
154
|
if (file.endTime > lastTime) lastTime = file.endTime;
|
|
155
|
+
if (file.startTime > endTime) continue;
|
|
156
|
+
if (file.endTime < startTime) continue;
|
|
157
|
+
selectedFiles.push(file);
|
|
158
|
+
fileCount++;
|
|
159
|
+
fileSizeSum += file.size;
|
|
149
160
|
if (filesHash !== this.state.downloadFilesHash) {
|
|
150
161
|
loadingCount++;
|
|
151
162
|
continue;
|
|
@@ -164,7 +175,7 @@ export class DiskLoggerPage extends qreact.Component {
|
|
|
164
175
|
if (firstTime === Number.MAX_SAFE_INTEGER) firstTime = startTime;
|
|
165
176
|
if (lastTime === Number.MIN_SAFE_INTEGER) lastTime = endTime;
|
|
166
177
|
|
|
167
|
-
let logs: LogObj[] = loadingCount ? [] : parseLogBufferCached(JSON.stringify(
|
|
178
|
+
let logs: LogObj[] = loadingCount ? [] : parseLogBufferCached(JSON.stringify(allFiles), buffers);
|
|
168
179
|
|
|
169
180
|
const defaultFields = ["time", "type", "actions", "param0"];
|
|
170
181
|
let selectedValues = selectedFields.value.split("|").filter(x => x);
|
|
@@ -292,11 +303,11 @@ export class DiskLoggerPage extends qreact.Component {
|
|
|
292
303
|
options={nodeIds.map(({ nodeId, entryPoint }) => ({ value: nodeId, label: `${nodeId} (${entryPoint.replaceAll("\\", "/").split("/").pop()})` }))}
|
|
293
304
|
/>
|
|
294
305
|
<div className={css.fontSize(28).boldStyle}>
|
|
295
|
-
{selectedNodesIds.length} nodes, {
|
|
306
|
+
{selectedNodesIds.length} nodes, {fileCount}/{allFiles.length} files, filtered logs {formatNumber(filteredCount)} / {formatNumber(totalCount)}
|
|
296
307
|
</div>
|
|
297
308
|
<ShowMore maxHeight={40}>
|
|
298
309
|
<div class={css.vbox(4)}>
|
|
299
|
-
{
|
|
310
|
+
{selectedFiles.map(file =>
|
|
300
311
|
<div class={css.hbox(4)}>
|
|
301
312
|
<span>{formatNumber(file.size)}B</span>
|
|
302
313
|
<span>{formatDateTime(file.startTime)} - {formatDateTime(file.endTime)}</span>
|
|
@@ -309,9 +320,11 @@ export class DiskLoggerPage extends qreact.Component {
|
|
|
309
320
|
<button onClick={() => {
|
|
310
321
|
this.state.downloadFilesHash = filesHash;
|
|
311
322
|
}}>
|
|
312
|
-
Download Files
|
|
323
|
+
Download Files ({formatNumber(fileSizeSum)}B)
|
|
313
324
|
</button>
|
|
314
|
-
</div>
|
|
325
|
+
</div>
|
|
326
|
+
|| loadingCount > 0 && <h1 className={css.hsl(210, 75, 75).pad2(10, 2)}>Downloading {loadingCount} file(s)</h1>
|
|
327
|
+
}
|
|
315
328
|
{!inspectTime && <>
|
|
316
329
|
<TimeRangeSelector
|
|
317
330
|
start={startTimeURL} end={endTimeURL}
|
|
@@ -367,7 +380,6 @@ export class DiskLoggerPage extends qreact.Component {
|
|
|
367
380
|
number
|
|
368
381
|
/>
|
|
369
382
|
)}
|
|
370
|
-
{loadingCount > 0 && <h1>Loading {loadingCount} files</h1>}
|
|
371
383
|
<Table {...table} initialLimit={30} />
|
|
372
384
|
{!!inspectTime && (
|
|
373
385
|
<InputLabel
|
|
@@ -398,6 +410,7 @@ const parseLogBufferCached = measureWrap(function parseLogBufferCached(hash: str
|
|
|
398
410
|
cached.lastAccess = Date.now();
|
|
399
411
|
return cached.logs;
|
|
400
412
|
}
|
|
413
|
+
console.log(`Parsing buffers ${buffers.length}`);
|
|
401
414
|
let logs = buffers.map(x => parseLogBuffer(x)).flat();
|
|
402
415
|
let size = buffers.map(x => x.length).reduce((a, b) => a + b, 0);
|
|
403
416
|
remainingCacheSize -= size;
|
|
@@ -411,6 +424,7 @@ const parseLogBufferCached = measureWrap(function parseLogBufferCached(hash: str
|
|
|
411
424
|
logs,
|
|
412
425
|
lastAccess: Date.now()
|
|
413
426
|
});
|
|
427
|
+
console.log(`Parsed buffers ${buffers.length} into logs ${logs.length}`);
|
|
414
428
|
return logs;
|
|
415
429
|
});
|
|
416
430
|
|
|
@@ -430,6 +444,7 @@ const processLogs = cacheShallowConfigArgEqual((config: {
|
|
|
430
444
|
filteredCount: number;
|
|
431
445
|
} => {
|
|
432
446
|
return measureBlock(function processLogs() {
|
|
447
|
+
console.log(`Processing logs ${config.logs.length}`);
|
|
433
448
|
let { logs, order, filter, startTime, endTime, inspectTime, selectedFields } = config;
|
|
434
449
|
logs = logs.slice();
|
|
435
450
|
let totalCount = logs.length;
|
|
@@ -543,6 +558,7 @@ const processLogs = cacheShallowConfigArgEqual((config: {
|
|
|
543
558
|
table.columns[key] = {};
|
|
544
559
|
}
|
|
545
560
|
|
|
561
|
+
console.log(`Processed logs ${logs.length}`);
|
|
546
562
|
return { table, allFields: fields, totalCount, filteredCount };
|
|
547
563
|
});
|
|
548
564
|
}, 10);
|
|
@@ -126,9 +126,12 @@ export async function getLogBuffer(path: string): Promise<Buffer | undefined> {
|
|
|
126
126
|
return buffer;
|
|
127
127
|
}
|
|
128
128
|
export function parseLogBuffer(buffer: Buffer): LogObj[] {
|
|
129
|
+
let time = Date.now();
|
|
130
|
+
console.log(`Parsing buffer ${buffer.length}`);
|
|
129
131
|
let pos = 0;
|
|
130
132
|
let logs: LogObj[] = [];
|
|
131
133
|
const newLine = "\n".charCodeAt(0);
|
|
134
|
+
let lastLoggedPos = 0;
|
|
132
135
|
while (pos < buffer.length) {
|
|
133
136
|
let end = buffer.indexOf(newLine, pos);
|
|
134
137
|
if (end === -1) {
|
|
@@ -139,7 +142,13 @@ export function parseLogBuffer(buffer: Buffer): LogObj[] {
|
|
|
139
142
|
logs.push(JSON.parse(line));
|
|
140
143
|
} catch { }
|
|
141
144
|
pos = end + 1;
|
|
145
|
+
if (pos - lastLoggedPos > 1_000_000) {
|
|
146
|
+
console.log(`Parsed ${pos} of ${buffer.length}`);
|
|
147
|
+
lastLoggedPos = pos;
|
|
148
|
+
}
|
|
142
149
|
}
|
|
150
|
+
time = Date.now() - time;
|
|
151
|
+
console.log(`Parsed ${pos} of ${buffer.length} ${formatNumber(time)}`);
|
|
143
152
|
return logs;
|
|
144
153
|
}
|
|
145
154
|
|
|
@@ -5,7 +5,7 @@ import { blue } from "socket-function/src/formatting/logColors";
|
|
|
5
5
|
import { isNode } from "socket-function/src/misc";
|
|
6
6
|
import { registerPeriodic } from "./periodic";
|
|
7
7
|
import { registerMeasureInfo } from "socket-function/src/profiling/measure";
|
|
8
|
-
import { logNodeStateStats } from "
|
|
8
|
+
import { logNodeStateStats } from "../-0-hooks/hooks";
|
|
9
9
|
|
|
10
10
|
let resources: {
|
|
11
11
|
name: string;
|
|
@@ -80,7 +80,7 @@ function logResourcesNow() {
|
|
|
80
80
|
} else {
|
|
81
81
|
for (let resource of resourcesWithCounts) {
|
|
82
82
|
if (resource.count === 0) continue;
|
|
83
|
-
logNodeStateStats(resource.name, formatNumber
|
|
83
|
+
logNodeStateStats(resource.name, formatNumber, resource.count);
|
|
84
84
|
}
|
|
85
85
|
}
|
|
86
86
|
}
|
|
@@ -7,23 +7,25 @@ import { registerPeriodic } from "./periodic";
|
|
|
7
7
|
import { getOwnMachineId } from "../-a-auth/certs";
|
|
8
8
|
import { SocketFunction } from "socket-function/SocketFunction";
|
|
9
9
|
import { logDisk } from "./logs/diskLogger";
|
|
10
|
-
import { addStatPeriodic, addStatSumPeriodic, addTimeProfileDistribution, registerNodeMetadata } from "../5-diagnostics/nodeMetadata";
|
|
11
10
|
import { formatPercent, formatTime } from "socket-function/src/formatting/format";
|
|
11
|
+
import { pathWatcher } from "../0-path-value-core/pathValueCore";
|
|
12
|
+
import { addStatPeriodic, addStatSumPeriodic, addTimeProfileDistribution, registerNodeMetadata } from "../-0-hooks/hooks";
|
|
12
13
|
|
|
13
14
|
let lastProfile: MeasureProfile | undefined;
|
|
14
15
|
|
|
15
|
-
addStatPeriodic(
|
|
16
|
-
"% Profiled",
|
|
17
|
-
() => {
|
|
16
|
+
addStatPeriodic({
|
|
17
|
+
title: "% Profiled",
|
|
18
|
+
getValue: () => {
|
|
18
19
|
if (!lastProfile) return 0;
|
|
19
20
|
let entries = Object.values(lastProfile.entries);
|
|
20
21
|
if (entries.length === 0) return 0;
|
|
21
22
|
const timeProfiled = lastProfile.endTime - lastProfile.startTime;
|
|
23
|
+
|
|
22
24
|
let timeActive = entries.map(x => x.ownTime.sum).reduce((a, b) => a + b, 0);
|
|
23
25
|
return timeActive / timeProfiled;
|
|
24
26
|
},
|
|
25
|
-
formatPercent,
|
|
26
|
-
);
|
|
27
|
+
format: formatPercent,
|
|
28
|
+
});
|
|
27
29
|
registerNodeMetadata({
|
|
28
30
|
columnName: "Top Profiled",
|
|
29
31
|
getValue() {
|
|
@@ -31,6 +33,7 @@ registerNodeMetadata({
|
|
|
31
33
|
let entries = Object.values(lastProfile.entries);
|
|
32
34
|
if (entries.length === 0) return "";
|
|
33
35
|
const timeProfiled = lastProfile.endTime - lastProfile.startTime;
|
|
36
|
+
|
|
34
37
|
let rootSums = new Map<string, number>();
|
|
35
38
|
for (let entry of entries) {
|
|
36
39
|
let name = entry.name.split("|")[0];
|
|
@@ -42,8 +45,16 @@ registerNodeMetadata({
|
|
|
42
45
|
},
|
|
43
46
|
});
|
|
44
47
|
addTimeProfileDistribution("Network Calls", () => SocketFunction.harvestCallTimes());
|
|
45
|
-
addStatPeriodic(
|
|
46
|
-
|
|
48
|
+
addStatPeriodic({
|
|
49
|
+
title: "Pending Net Calls",
|
|
50
|
+
getValue: () => SocketFunction.getPendingCallCount(),
|
|
51
|
+
});
|
|
52
|
+
addStatSumPeriodic({
|
|
53
|
+
title: "Failed Net Calls",
|
|
54
|
+
getValue: () => SocketFunction.harvestFailedCallCount(),
|
|
55
|
+
});
|
|
56
|
+
addTimeProfileDistribution("Syncing", () => pathWatcher.debug_harvestSyncTimes());
|
|
57
|
+
|
|
47
58
|
|
|
48
59
|
function endEllipsis(str: string, maxLength: number) {
|
|
49
60
|
if (str.length <= maxLength) return str;
|