querysub 0.42.0 → 0.44.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 +60 -60
- package/src/-a-archives/archivesBackBlaze.ts +3 -0
- package/src/-g-core-values/NodeCapabilities.ts +6 -4
- package/src/0-path-value-core/NodePathAuthorities.ts +24 -2
- package/src/0-path-value-core/pathValueCore.ts +2221 -2216
- package/src/2-proxy/PathValueProxyWatcher.ts +41 -3
- package/src/3-path-functions/PathFunctionRunner.ts +19 -6
- package/src/3-path-functions/pathFunctionLoader.ts +7 -1
- package/src/4-querysub/QuerysubController.ts +0 -10
- package/src/5-diagnostics/GenericFormat.tsx +3 -1
- package/src/5-diagnostics/TimeGrouper.tsx +2 -0
- package/src/5-diagnostics/nodeMetadata.ts +137 -11
- package/src/diagnostics/NodeViewer.tsx +19 -8
- package/src/diagnostics/logs/DiskLoggerPage.tsx +46 -20
- package/src/diagnostics/logs/diskLogger.ts +44 -13
- package/src/diagnostics/periodic.ts +2 -2
- package/src/diagnostics/trackResources.ts +4 -3
- package/src/diagnostics/watchdog.ts +20 -6
- package/src/library-components/Input.tsx +1 -1
- package/src/zip.ts +9 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
import { batchFunction, runInfinitePoll } from "socket-function/src/batching";
|
|
2
|
+
import { batchFunction, runInfinitePoll, runInfinitePollCallAtStart } from "socket-function/src/batching";
|
|
3
3
|
import { nextId, timeInDay, timeInHour } from "socket-function/src/misc";
|
|
4
4
|
import { getStorageDir, getStorageFolder } from "../../fs";
|
|
5
5
|
import fs from "fs";
|
|
@@ -8,6 +8,8 @@ import { SizeLimiter } from "../SizeLimiter";
|
|
|
8
8
|
import { SocketFunction } from "socket-function/SocketFunction";
|
|
9
9
|
import { isNode } from "typesafecss";
|
|
10
10
|
import { logGitHashes } from "./logGitHashes";
|
|
11
|
+
import { Zip } from "../../zip";
|
|
12
|
+
import { formatNumber } from "socket-function/src/formatting/format";
|
|
11
13
|
|
|
12
14
|
if (isNode()) {
|
|
13
15
|
// Delayed setup, as we depend on diskLogger early, and we don't want to force high level
|
|
@@ -105,6 +107,7 @@ export type LogFile = {
|
|
|
105
107
|
export async function getLogFiles(): Promise<LogFile[]> {
|
|
106
108
|
let files = await fs.promises.readdir(folder);
|
|
107
109
|
let paths = files.map(file => folder + file);
|
|
110
|
+
paths = paths.filter(x => x.endsWith(".log") || x.endsWith(".zip"));
|
|
108
111
|
let objs = paths.map(decodeLogFileName);
|
|
109
112
|
for (let obj of objs) {
|
|
110
113
|
try {
|
|
@@ -214,7 +217,8 @@ function packageLogObj(args: unknown[]): LogObj {
|
|
|
214
217
|
|
|
215
218
|
function decodeLogFileName(path: string): LogFile {
|
|
216
219
|
let name = path.split("/").pop()!;
|
|
217
|
-
let
|
|
220
|
+
let withoutExt = name.split(".").slice(0, -1).join(".");
|
|
221
|
+
let [start, end] = withoutExt.split("-").map(Number);
|
|
218
222
|
return {
|
|
219
223
|
startTime: start,
|
|
220
224
|
endTime: end,
|
|
@@ -231,7 +235,16 @@ const logBase = batchFunction({ delay: 0 }, async function logBase(logObjList: L
|
|
|
231
235
|
|
|
232
236
|
let byLogPath = new Map<string, LogObj[]>();
|
|
233
237
|
for (let log of logs) {
|
|
234
|
-
|
|
238
|
+
function createLogFileName(logObj: LogObj): LogFile {
|
|
239
|
+
let start = Math.floor(logObj.time / LOG_FILE_DURATION) * LOG_FILE_DURATION;
|
|
240
|
+
let startTime = start;
|
|
241
|
+
let endTime = start + LOG_FILE_DURATION;
|
|
242
|
+
let name = startTime + "-" + endTime + ".log";
|
|
243
|
+
let path = folder + name;
|
|
244
|
+
let logFile: LogFile = { startTime, endTime, name, path, size: 0, };
|
|
245
|
+
return logFile;
|
|
246
|
+
}
|
|
247
|
+
let logFile = createLogFileName(log);
|
|
235
248
|
let list = byLogPath.get(logFile.path);
|
|
236
249
|
if (!list) {
|
|
237
250
|
list = [];
|
|
@@ -268,18 +281,9 @@ const logBase = batchFunction({ delay: 0 }, async function logBase(logObjList: L
|
|
|
268
281
|
}
|
|
269
282
|
});
|
|
270
283
|
|
|
271
|
-
function getLogFileName(logObj: LogObj): LogFile {
|
|
272
|
-
let start = Math.floor(logObj.time / LOG_FILE_DURATION) * LOG_FILE_DURATION;
|
|
273
|
-
let startTime = start;
|
|
274
|
-
let endTime = start + LOG_FILE_DURATION;
|
|
275
|
-
let name = startTime + "-" + endTime + ".log";
|
|
276
|
-
let path = folder + name;
|
|
277
|
-
let logFile: LogFile = { startTime, endTime, name, path, size: 0, };
|
|
278
|
-
return logFile;
|
|
279
|
-
}
|
|
280
284
|
|
|
281
285
|
if (isNode()) {
|
|
282
|
-
runInfinitePoll(timeInHour, async function
|
|
286
|
+
runInfinitePoll(timeInHour, async function compressLogs() {
|
|
283
287
|
// Maintain our size restrictions
|
|
284
288
|
let logFiles = await fs.promises.readdir(folder);
|
|
285
289
|
let objs: { time: number; bytes: number; path: string; }[] = [];
|
|
@@ -293,6 +297,33 @@ if (isNode()) {
|
|
|
293
297
|
await fs.promises.unlink(file.path);
|
|
294
298
|
}
|
|
295
299
|
});
|
|
300
|
+
// Wait a random time, so we hopefully don't synchronize with any other services on this machine
|
|
301
|
+
runInfinitePoll(timeInHour + (1 + Math.random()), async function compressOldLogs() {
|
|
302
|
+
let logFiles = await fs.promises.readdir(folder);
|
|
303
|
+
let compressTime = Date.now() - LOG_FILE_DURATION * 2;
|
|
304
|
+
let filesCompressed = 0;
|
|
305
|
+
for (let file of logFiles) {
|
|
306
|
+
if (!file.endsWith(".log")) continue;
|
|
307
|
+
if (filesCompressed === 0) {
|
|
308
|
+
console.log("Compressing old logs");
|
|
309
|
+
}
|
|
310
|
+
filesCompressed++;
|
|
311
|
+
let path = folder + file;
|
|
312
|
+
if (decodeLogFileName(path).endTime > compressTime) continue;
|
|
313
|
+
let basePath = path.split(".").slice(0, -1).join(".");
|
|
314
|
+
let buffer = await fs.promises.readFile(path);
|
|
315
|
+
let beforeSize = buffer.length;
|
|
316
|
+
buffer = await Zip.gzip(buffer);
|
|
317
|
+
console.log(`Compressed ${file} from ${formatNumber(beforeSize)}B to ${formatNumber(buffer.length)}B`);
|
|
318
|
+
let tempPath = basePath + Math.random() + ".temp";
|
|
319
|
+
await fs.promises.writeFile(tempPath, buffer);
|
|
320
|
+
await fs.promises.rename(tempPath, basePath + ".zip");
|
|
321
|
+
await fs.promises.unlink(path);
|
|
322
|
+
}
|
|
323
|
+
if (filesCompressed > 0) {
|
|
324
|
+
console.log(`Compressed ${filesCompressed} old log files`);
|
|
325
|
+
}
|
|
326
|
+
});
|
|
296
327
|
}
|
|
297
328
|
|
|
298
329
|
/*
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { runInfinitePoll, runInfinitePollCallAtStart } from "socket-function/src/batching";
|
|
2
|
-
import { isNode } from "socket-function/src/misc";
|
|
2
|
+
import { isNode, timeInMinute } from "socket-function/src/misc";
|
|
3
3
|
import { logErrors } from "../errors";
|
|
4
4
|
import debugbreak from "debugbreak";
|
|
5
5
|
import { nodeDiscoveryShutdown } from "../-f-node-discovery/NodeDiscovery";
|
|
@@ -22,7 +22,7 @@ function logAll() {
|
|
|
22
22
|
}
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
logErrors(runInfinitePollCallAtStart(
|
|
25
|
+
logErrors(runInfinitePollCallAtStart(timeInMinute * 5, logAll));
|
|
26
26
|
|
|
27
27
|
async function shutdown() {
|
|
28
28
|
const { authorityStorage } = await import("../0-path-value-core/pathValueCore");
|
|
@@ -64,6 +64,10 @@ function getBufferUsage() {
|
|
|
64
64
|
}
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
+
registerDynamicResource("Heap", getUsedHeapSize);
|
|
68
|
+
registerDynamicResource("Buffers", getBufferUsage);
|
|
69
|
+
registerDynamicResource("All Memory", getHeapSize);
|
|
70
|
+
|
|
67
71
|
function logResourcesNow() {
|
|
68
72
|
let resourcesWithCounts = resources.map(resource => ({ ...resource, count: resource.getCount() }));
|
|
69
73
|
resourcesWithCounts.sort((a, b) => b.count - a.count);
|
|
@@ -74,9 +78,6 @@ function logResourcesNow() {
|
|
|
74
78
|
console.log(` ${resource.name}: ${formatNumber(resource.count)}`);
|
|
75
79
|
}
|
|
76
80
|
} else {
|
|
77
|
-
logNodeStateStats("Heap", formatNumber)(getUsedHeapSize());
|
|
78
|
-
logNodeStateStats("Buffers", formatNumber)(getBufferUsage());
|
|
79
|
-
logNodeStateStats("All Memory", formatNumber)(getHeapSize());
|
|
80
81
|
for (let resource of resourcesWithCounts) {
|
|
81
82
|
if (resource.count === 0) continue;
|
|
82
83
|
logNodeStateStats(resource.name, formatNumber)(resource.count);
|
|
@@ -7,20 +7,30 @@ 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 { registerNodeMetadata } from "../5-diagnostics/nodeMetadata";
|
|
11
|
-
import { formatPercent } from "socket-function/src/formatting/format";
|
|
10
|
+
import { addStatPeriodic, addStatSumPeriodic, addTimeProfileDistribution, registerNodeMetadata } from "../5-diagnostics/nodeMetadata";
|
|
11
|
+
import { formatPercent, formatTime } from "socket-function/src/formatting/format";
|
|
12
12
|
|
|
13
13
|
let lastProfile: MeasureProfile | undefined;
|
|
14
14
|
|
|
15
|
+
addStatPeriodic(
|
|
16
|
+
"% Profiled",
|
|
17
|
+
() => {
|
|
18
|
+
if (!lastProfile) return 0;
|
|
19
|
+
let entries = Object.values(lastProfile.entries);
|
|
20
|
+
if (entries.length === 0) return 0;
|
|
21
|
+
const timeProfiled = lastProfile.endTime - lastProfile.startTime;
|
|
22
|
+
let timeActive = entries.map(x => x.ownTime.sum).reduce((a, b) => a + b, 0);
|
|
23
|
+
return timeActive / timeProfiled;
|
|
24
|
+
},
|
|
25
|
+
formatPercent,
|
|
26
|
+
);
|
|
15
27
|
registerNodeMetadata({
|
|
16
|
-
columnName: "
|
|
28
|
+
columnName: "Top Profiled",
|
|
17
29
|
getValue() {
|
|
18
30
|
if (!lastProfile) return "";
|
|
19
31
|
let entries = Object.values(lastProfile.entries);
|
|
20
32
|
if (entries.length === 0) return "";
|
|
21
33
|
const timeProfiled = lastProfile.endTime - lastProfile.startTime;
|
|
22
|
-
let timeActive = entries.map(x => x.ownTime.sum).reduce((a, b) => a + b, 0);
|
|
23
|
-
let frac = timeActive / timeProfiled;
|
|
24
34
|
let rootSums = new Map<string, number>();
|
|
25
35
|
for (let entry of entries) {
|
|
26
36
|
let name = entry.name.split("|")[0];
|
|
@@ -28,9 +38,13 @@ registerNodeMetadata({
|
|
|
28
38
|
rootSums.set(name, sum + entry.ownTime.sum);
|
|
29
39
|
}
|
|
30
40
|
let most = sort(Array.from(rootSums.entries()), x => -x[1])[0];
|
|
31
|
-
return `${
|
|
41
|
+
return `${endEllipsis(most[0], 26)} = ${formatPercent(most[1] / timeProfiled)}`;
|
|
32
42
|
},
|
|
33
43
|
});
|
|
44
|
+
addTimeProfileDistribution("Network Calls", () => SocketFunction.harvestCallTimes());
|
|
45
|
+
addStatPeriodic("Pending Net Calls", () => SocketFunction.getPendingCallCount());
|
|
46
|
+
addStatSumPeriodic("Failed Net Calls", () => SocketFunction.harvestFailedCallCount());
|
|
47
|
+
|
|
34
48
|
function endEllipsis(str: string, maxLength: number) {
|
|
35
49
|
if (str.length <= maxLength) return str;
|
|
36
50
|
return "..." + str.slice(-(maxLength - 3));
|
package/src/zip.ts
CHANGED
|
@@ -61,6 +61,15 @@ export class Zip {
|
|
|
61
61
|
}
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
+
@measureFnc
|
|
65
|
+
public static gunzipSync(buffer: Buffer): Buffer {
|
|
66
|
+
if (isNode()) {
|
|
67
|
+
return Buffer.from(zlib.gunzipSync(buffer));
|
|
68
|
+
} else {
|
|
69
|
+
return Buffer.from(pako.inflate(buffer));
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
64
73
|
@measureFnc
|
|
65
74
|
public static async gunzipBatch(buffers: Buffer[]): Promise<Buffer[]> {
|
|
66
75
|
let time = Date.now();
|