querysub 0.367.0 → 0.369.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 +1 -1
- package/src/-f-node-discovery/NodeDiscovery.ts +4 -0
- package/src/diagnostics/logs/IndexedLogs/IndexedLogs.ts +31 -19
- package/src/diagnostics/logs/IndexedLogs/LogViewer3.tsx +11 -7
- package/src/diagnostics/logs/IndexedLogs/TimeFileTree.ts +4 -4
- package/src/diagnostics/logs/lifeCycleAnalysis/lifeCycles.tsx +2 -0
package/package.json
CHANGED
|
@@ -109,6 +109,10 @@ export function isOwnNodeId(nodeId: string): boolean {
|
|
|
109
109
|
return false;
|
|
110
110
|
}
|
|
111
111
|
|
|
112
|
+
export function isNodeIdOnOwnMachineId(nodeId: string): boolean {
|
|
113
|
+
return certs.getMachineId(nodeId) === getOwnMachineId() || nodeId.startsWith("127-0-0-1.");
|
|
114
|
+
}
|
|
115
|
+
|
|
112
116
|
let nodeOverrides: string[] | undefined;
|
|
113
117
|
let beforeGetNodeAllId = async () => { };
|
|
114
118
|
export async function getAllNodeIds() {
|
|
@@ -12,7 +12,7 @@ import { ArchivesMemoryCacheStats, createArchivesMemoryCache } from "../../../-a
|
|
|
12
12
|
import { registerShutdownHandler } from "../../periodic";
|
|
13
13
|
import { measureBlock, measureFnc } from "socket-function/src/profiling/measure";
|
|
14
14
|
import { isNode } from "typesafecss";
|
|
15
|
-
import { getOwnMachineId } from "../../../-f-node-discovery/NodeDiscovery";
|
|
15
|
+
import { getOwnMachineId, isNodeIdOnOwnMachineId, isOwnNodeId } from "../../../-f-node-discovery/NodeDiscovery";
|
|
16
16
|
import { TimeFilePath, TimeFileTree } from "./TimeFileTree";
|
|
17
17
|
import { LogStreamer } from "./LogStreamer";
|
|
18
18
|
import { moveLogsToPublic } from "./moveIndexLogsToPublic";
|
|
@@ -226,10 +226,11 @@ export class IndexedLogs<T> {
|
|
|
226
226
|
|
|
227
227
|
private machineNodeCache = new Map<string, string>();
|
|
228
228
|
private async getMachineNodes(): Promise<string[]> {
|
|
229
|
-
let ownMachineId = getOwnMachineId();
|
|
230
229
|
let nodeIds = await getAllNodeIds();
|
|
230
|
+
nodeIds = nodeIds.filter(x => !isNodeIdOnOwnMachineId(x));
|
|
231
231
|
let byMachineId = keyByArray(nodeIds, x => getMachineId(x));
|
|
232
|
-
|
|
232
|
+
|
|
233
|
+
let nextCache = new Map<string, string>();
|
|
233
234
|
|
|
234
235
|
await Promise.all(Array.from(byMachineId.entries()).map(async ([machineId, nodeIds]) => {
|
|
235
236
|
let added = false;
|
|
@@ -239,12 +240,12 @@ export class IndexedLogs<T> {
|
|
|
239
240
|
if (!hasLogger) return false;
|
|
240
241
|
// NOTE: Prefer to do the searching on the move logs service. However, if it's not available, any service can do searching. It just might lag that server...
|
|
241
242
|
if (preferredOnly) {
|
|
242
|
-
let entryPoint = await NodeCapabilitiesController.nodes[nodeId].getEntryPoint();
|
|
243
|
-
if (!entryPoint
|
|
243
|
+
let entryPoint = await timeoutToUndefinedSilent(2500, NodeCapabilitiesController.nodes[nodeId].getEntryPoint());
|
|
244
|
+
if (!entryPoint?.includes("movelogs")) return false;
|
|
244
245
|
}
|
|
245
246
|
added = true;
|
|
246
247
|
|
|
247
|
-
|
|
248
|
+
nextCache.set(machineId, nodeId);
|
|
248
249
|
return true;
|
|
249
250
|
};
|
|
250
251
|
let cached = this.machineNodeCache.get(machineId);
|
|
@@ -261,6 +262,7 @@ export class IndexedLogs<T> {
|
|
|
261
262
|
}
|
|
262
263
|
}));
|
|
263
264
|
|
|
265
|
+
this.machineNodeCache = nextCache;
|
|
264
266
|
return Array.from(this.machineNodeCache.values());
|
|
265
267
|
}
|
|
266
268
|
|
|
@@ -298,21 +300,28 @@ export class IndexedLogs<T> {
|
|
|
298
300
|
let backblazeLogs = this.getPublicLogs();
|
|
299
301
|
let paths: TimeFilePath[] = [];
|
|
300
302
|
|
|
303
|
+
let promises: Promise<void>[] = [];
|
|
304
|
+
|
|
301
305
|
if (config.only !== "public") {
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
306
|
+
promises.push((async () => {
|
|
307
|
+
let localPaths = await new TimeFileTree(localLogs).findAllPaths({
|
|
308
|
+
startTime: config.startTime,
|
|
309
|
+
endTime: config.endTime,
|
|
310
|
+
});
|
|
311
|
+
paths.push(...localPaths);
|
|
312
|
+
})());
|
|
307
313
|
}
|
|
308
314
|
|
|
309
315
|
if (config.only !== "local") {
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
316
|
+
promises.push((async () => {
|
|
317
|
+
let backblazePaths = await new TimeFileTree(backblazeLogs).findAllPaths({
|
|
318
|
+
startTime: config.startTime,
|
|
319
|
+
endTime: config.endTime,
|
|
320
|
+
});
|
|
321
|
+
paths.push(...backblazePaths);
|
|
322
|
+
})());
|
|
315
323
|
}
|
|
324
|
+
await Promise.all(promises);
|
|
316
325
|
|
|
317
326
|
// Bake in the size to ensure more cache hits (without this, every single access will always result in a file/remote call).
|
|
318
327
|
let pathsWithSize = await Promise.all(paths.map(async (path): Promise<TimeFilePathWithSize> => {
|
|
@@ -351,12 +360,16 @@ export class IndexedLogs<T> {
|
|
|
351
360
|
let allResults = new Map<string, IndexedLogResults>();
|
|
352
361
|
let allDone: Promise<void>[] = [];
|
|
353
362
|
|
|
354
|
-
if (
|
|
363
|
+
if (config.params.only !== "local" && (config.params.forceReadPublic || isPublic())) {
|
|
355
364
|
let machineNodes = await this.getMachineNodes();
|
|
356
365
|
allDone.push(...machineNodes.map(async (machineNode) => {
|
|
357
366
|
try {
|
|
358
367
|
let resultObj = await this.clientFind({
|
|
359
368
|
...config,
|
|
369
|
+
params: {
|
|
370
|
+
...config.params,
|
|
371
|
+
only: "local",
|
|
372
|
+
},
|
|
360
373
|
nodeId: machineNode,
|
|
361
374
|
onResult(match) {
|
|
362
375
|
config.onResult(match);
|
|
@@ -374,6 +387,7 @@ export class IndexedLogs<T> {
|
|
|
374
387
|
|
|
375
388
|
// If we're forcefully reading from the public server, but we're not public, the code above will be the only code which adds to results
|
|
376
389
|
if (!isPublic() && config.params.forceReadPublic) {
|
|
390
|
+
await Promise.all(allDone);
|
|
377
391
|
return getFinalResults();
|
|
378
392
|
}
|
|
379
393
|
|
|
@@ -696,7 +710,6 @@ class IndexedLogClient {
|
|
|
696
710
|
indexedLogsName: string;
|
|
697
711
|
result: unknown;
|
|
698
712
|
}) {
|
|
699
|
-
if (isNode()) return;
|
|
700
713
|
let indexedLogs = loggerByName.get(config.indexedLogsName);
|
|
701
714
|
if (!indexedLogs) throw new Error(`Indexed logs ${config.indexedLogsName} not found`);
|
|
702
715
|
indexedLogs.onFindResult({
|
|
@@ -709,7 +722,6 @@ class IndexedLogClient {
|
|
|
709
722
|
indexedLogsName: string;
|
|
710
723
|
results: IndexedLogResults;
|
|
711
724
|
}): Promise<boolean> {
|
|
712
|
-
if (isNode()) return true;
|
|
713
725
|
let indexedLogs = loggerByName.get(config.indexedLogsName);
|
|
714
726
|
if (!indexedLogs) throw new Error(`Indexed logs ${config.indexedLogsName} not found`);
|
|
715
727
|
return await indexedLogs.onResults({
|
|
@@ -25,6 +25,7 @@ import { errorToUndefined } from "../../../errors";
|
|
|
25
25
|
import { IndexedLogResults, createEmptyIndexedLogResults, mergeIndexedLogResults } from "./BufferIndexHelpers";
|
|
26
26
|
import { TimeFilePath } from "./TimeFileTree";
|
|
27
27
|
import { isPublic } from "../../../config";
|
|
28
|
+
import { Zip } from "../../../zip";
|
|
28
29
|
|
|
29
30
|
let searchText = new URLParam("searchText", "");
|
|
30
31
|
let excludePendingResults = new URLParam("excludePendingResults", false);
|
|
@@ -76,7 +77,7 @@ export class LogViewer3 extends qreact.Component {
|
|
|
76
77
|
let paths: TimeFilePathWithSize[] = [];
|
|
77
78
|
if (savedPathsURL.value) {
|
|
78
79
|
const compressed = Buffer.from(savedPathsURL.value, "base64");
|
|
79
|
-
const decompressed =
|
|
80
|
+
const decompressed = Zip.gunzipSync(compressed);
|
|
80
81
|
paths = JSON.parse(decompressed.toString("utf8"));
|
|
81
82
|
} else {
|
|
82
83
|
paths = this.state.paths;
|
|
@@ -95,7 +96,7 @@ export class LogViewer3 extends qreact.Component {
|
|
|
95
96
|
freezePaths() {
|
|
96
97
|
const json = JSON.stringify(this.state.paths);
|
|
97
98
|
const buffer = Buffer.from(json, "utf8");
|
|
98
|
-
const compressed =
|
|
99
|
+
const compressed = Zip.gzipSync(buffer, 9);
|
|
99
100
|
savedPathsURL.value = compressed.toString("base64");
|
|
100
101
|
}
|
|
101
102
|
|
|
@@ -342,6 +343,8 @@ export class LogViewer3 extends qreact.Component {
|
|
|
342
343
|
|
|
343
344
|
Querysub.commitLocal(() => {
|
|
344
345
|
this.state.loadingPaths = true;
|
|
346
|
+
this.state.results = [];
|
|
347
|
+
this.state.stats = undefined;
|
|
345
348
|
});
|
|
346
349
|
|
|
347
350
|
let loggers = await getLoggers2Async();
|
|
@@ -364,15 +367,15 @@ export class LogViewer3 extends qreact.Component {
|
|
|
364
367
|
let allPaths: TimeFilePathWithSize[] = [];
|
|
365
368
|
let range = Querysub.localRead(() => getTimeRange());
|
|
366
369
|
|
|
367
|
-
|
|
370
|
+
await Promise.all(selectedLoggers.map(async (logger) => {
|
|
368
371
|
let paths = await logger.clientGetPaths({
|
|
369
372
|
startTime: range.startTime,
|
|
370
373
|
endTime: range.endTime,
|
|
371
|
-
only: excludePendingResults.value ? "
|
|
374
|
+
only: excludePendingResults.value ? "public" : undefined,
|
|
372
375
|
forceReadPublic: readPublicLogs.value,
|
|
373
376
|
});
|
|
374
377
|
allPaths.push(...paths);
|
|
375
|
-
}
|
|
378
|
+
}));
|
|
376
379
|
sort(allPaths, x => -x.startTime);
|
|
377
380
|
|
|
378
381
|
Querysub.commitLocal(() => {
|
|
@@ -679,7 +682,6 @@ export class LogViewer3 extends qreact.Component {
|
|
|
679
682
|
return (
|
|
680
683
|
<div className={css.vbox(20).pad2(20).fillBoth}>
|
|
681
684
|
<div className={css.hbox(20)}>
|
|
682
|
-
<div>Log Viewer 3</div>
|
|
683
685
|
<InputLabelURL
|
|
684
686
|
checkbox
|
|
685
687
|
label="Exclude Pending Results"
|
|
@@ -740,7 +742,9 @@ export class LogViewer3 extends qreact.Component {
|
|
|
740
742
|
</Button>
|
|
741
743
|
<TimeRangeSelector />
|
|
742
744
|
</div>
|
|
743
|
-
{!isPublic() && readPublicLogs.value && <
|
|
745
|
+
{!isPublic() && readPublicLogs.value && <div className={css.fontSize(40).pad2(12, 6).hsl(280, 40, 50).colorhsl(0, 0, 100).boldStyle}>
|
|
746
|
+
Reading public logs
|
|
747
|
+
</div>}
|
|
744
748
|
|
|
745
749
|
<div className={css.hbox(10).fillWidth}>
|
|
746
750
|
<InputLabelURL
|
|
@@ -156,12 +156,12 @@ export class TimeFileTree {
|
|
|
156
156
|
// Find all days in this month
|
|
157
157
|
const days = await this.archives.find(monthFolder + "/", { shallow: true, type: "folders" });
|
|
158
158
|
|
|
159
|
-
|
|
159
|
+
await Promise.all(days.map(async (dayFolder) => {
|
|
160
160
|
// dayFolder is a full path like "2024/01/15"
|
|
161
161
|
const day = parseInt(dayFolder.split("/").at(-1) || "", 10);
|
|
162
162
|
|
|
163
163
|
if (isNaN(day) || day < 1 || day > 31) {
|
|
164
|
-
|
|
164
|
+
return;
|
|
165
165
|
}
|
|
166
166
|
|
|
167
167
|
// Check if this day is in range
|
|
@@ -169,7 +169,7 @@ export class TimeFileTree {
|
|
|
169
169
|
const dayEndDate = new Date(Date.UTC(year, month - 1, day, 23, 59, 59, 999));
|
|
170
170
|
|
|
171
171
|
if (dayEndDate.getTime() < config.startTime || dayDate.getTime() > config.endTime) {
|
|
172
|
-
|
|
172
|
+
return;
|
|
173
173
|
}
|
|
174
174
|
|
|
175
175
|
// Find all log files in this day
|
|
@@ -187,7 +187,7 @@ export class TimeFileTree {
|
|
|
187
187
|
results.push(decoded);
|
|
188
188
|
}
|
|
189
189
|
}
|
|
190
|
-
}
|
|
190
|
+
}));
|
|
191
191
|
}
|
|
192
192
|
}
|
|
193
193
|
|