querysub 0.13.0 → 0.15.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/-f-node-discovery/NodeDiscovery.ts +48 -79
- package/src/-g-core-values/NodeCapabilities.ts +1 -1
- package/src/0-path-value-core/PathValueCommitter.ts +0 -1
- package/src/2-proxy/PathValueProxyWatcher.ts +9 -10
- package/src/diagnostics/NodeViewer.tsx +27 -5
- package/src/diagnostics/logs/DiskLoggerPage.tsx +5 -12
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "querysub",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.0",
|
|
4
4
|
"main": "index.js",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"note1": "note on node-forge fork, see https://github.com/digitalbazaar/forge/issues/744 for details",
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"node-forge": "https://github.com/sliftist/forge#e618181b469b07bdc70b968b0391beb8ef5fecd6",
|
|
25
25
|
"pako": "^2.1.0",
|
|
26
26
|
"preact": "^10.11.3",
|
|
27
|
-
"socket-function": "^0.
|
|
27
|
+
"socket-function": "^0.36.0",
|
|
28
28
|
"terser": "^5.31.0",
|
|
29
29
|
"typesafecss": "^0.6.3",
|
|
30
30
|
"yaml": "^2.5.0",
|
|
@@ -2,7 +2,7 @@ import { SocketFunction } from "socket-function/SocketFunction";
|
|
|
2
2
|
import { getArchives } from "../-a-archives/archives";
|
|
3
3
|
import { getDomain, isDevDebugbreak, isNoNetwork } from "../config";
|
|
4
4
|
import { measureWrap } from "socket-function/src/profiling/measure";
|
|
5
|
-
import { isNode, sha256Hash, timeInMinute, timeInSecond } from "socket-function/src/misc";
|
|
5
|
+
import { isNode, sha256Hash, throttleFunction, timeInMinute, timeInSecond } from "socket-function/src/misc";
|
|
6
6
|
import { errorToUndefined, errorToUndefinedSilent, ignoreErrors, logErrors, timeoutToUndefined, timeoutToUndefinedSilent } from "../errors";
|
|
7
7
|
import { requiresNetworkTrustHook } from "../-d-trust/NetworkTrust2";
|
|
8
8
|
import { delay, runInfinitePoll, runInfinitePollCallAtStart } from "socket-function/src/batching";
|
|
@@ -21,9 +21,9 @@ import { getPublicIP } from "../misc/networking";
|
|
|
21
21
|
|
|
22
22
|
import dns from "dns/promises";
|
|
23
23
|
import { isDefined } from "../misc";
|
|
24
|
-
import { diskLog } from "../diagnostics/logs/diskLogger";
|
|
24
|
+
import { diskLog, noDiskLogPrefix } from "../diagnostics/logs/diskLogger";
|
|
25
25
|
|
|
26
|
-
let HEARTBEAT_INTERVAL = timeInMinute *
|
|
26
|
+
let HEARTBEAT_INTERVAL = timeInMinute * 2;
|
|
27
27
|
// Interval which we check other heartbeats
|
|
28
28
|
let CHECK_INTERVAL = HEARTBEAT_INTERVAL;
|
|
29
29
|
// If the heartbeat is older than thing, it fails the dead check
|
|
@@ -37,6 +37,8 @@ let SUICIDE_HEARTBEAT_THRESHOLD = timeInMinute * 15;
|
|
|
37
37
|
|
|
38
38
|
let CLIENTSIDE_POLL_RATE = timeInMinute * 5;
|
|
39
39
|
|
|
40
|
+
let API_AUDIT_RATE = timeInSecond * 5;
|
|
41
|
+
|
|
40
42
|
let MEMORY_AUDIT_RATE = timeInMinute * 5;
|
|
41
43
|
let MEMORY_AUDIT_COUNT = 3;
|
|
42
44
|
|
|
@@ -64,6 +66,9 @@ export function getOwnNodeId(): string {
|
|
|
64
66
|
}
|
|
65
67
|
return nodeId;
|
|
66
68
|
}
|
|
69
|
+
export function getMountNodeId(): string | undefined | "" {
|
|
70
|
+
return SocketFunction.mountedNodeId;
|
|
71
|
+
}
|
|
67
72
|
export function getOwnNodeIdAssert(): string {
|
|
68
73
|
let nodeId = SocketFunction.mountedNodeId;
|
|
69
74
|
if (!nodeId) {
|
|
@@ -154,19 +159,8 @@ function addNodeIdBase(nodeId: string) {
|
|
|
154
159
|
allNodeIds2.add(nodeId);
|
|
155
160
|
onNodesChanged();
|
|
156
161
|
}
|
|
157
|
-
function removeNodeIds(nodeIds: string[]) {
|
|
158
|
-
diskLog("removeNodeIds", { nodeIds });
|
|
159
|
-
nodeIds = nodeIds.filter(nodeId => allNodeIds2.has(nodeId));
|
|
160
|
-
if (nodeIds.length === 0) return;
|
|
161
|
-
for (let nodeId of nodeIds) {
|
|
162
|
-
if (logging) {
|
|
163
|
-
console.log(red(`Removed node directly ${nodeId}`));
|
|
164
|
-
}
|
|
165
|
-
allNodeIds2.delete(nodeId);
|
|
166
|
-
}
|
|
167
|
-
onNodesChanged();
|
|
168
|
-
}
|
|
169
162
|
function setNodeIds(nodeIds: string[]) {
|
|
163
|
+
nodeIds = nodeIds.filter(x => x !== SPECIAL_NODE_ID_FOR_UNMOUNTED_NODE);
|
|
170
164
|
diskLog("setNodeIds", { nodeIds });
|
|
171
165
|
// Also try all localhost ports, if we are in dev mode
|
|
172
166
|
if (isNode() && isDevDebugbreak()) {
|
|
@@ -250,25 +244,18 @@ async function syncArchives() {
|
|
|
250
244
|
async function runHeartbeatAuditLoop() {
|
|
251
245
|
await onNodeDiscoveryReady();
|
|
252
246
|
let deadCount = new Map<string, number>();
|
|
253
|
-
|
|
247
|
+
// 90% of the normal interval, so we don't run at the same tmie as the other audit
|
|
248
|
+
await runInfinitePollCallAtStart(CHECK_INTERVAL * 0.9, async () => {
|
|
254
249
|
if (shutdown) return;
|
|
255
250
|
// Wait a bit longer, to try to prevent all nodes from synchronizing their audit times.
|
|
256
|
-
await delay(
|
|
251
|
+
await delay(CHECK_INTERVAL * Math.random() * 0.1);
|
|
257
252
|
//console.log(magenta(`Auditing node list`));
|
|
258
253
|
|
|
259
254
|
let deadTime = Date.now() - DEAD_THRESHOLD;
|
|
260
255
|
let nodeIds = await archives().find("");
|
|
261
|
-
//
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
console.log(yellow(`Found unexpected node, adding it and broadcasting it, ${nodeId}`));
|
|
265
|
-
addNodeId(nodeId);
|
|
266
|
-
for (let nodeId of allNodeIds2) {
|
|
267
|
-
if (isOwnNodeId(nodeId)) continue;
|
|
268
|
-
ignoreErrors(NodeDiscoveryController.nodes[nodeId].addNode(nodeId));
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
}
|
|
256
|
+
// We spent the money checking the node list, so we might as well update it
|
|
257
|
+
setNodeIds(nodeIds);
|
|
258
|
+
|
|
272
259
|
let removedNodeIds: string[] = [];
|
|
273
260
|
for (let nodeId of nodeIds) {
|
|
274
261
|
let lastTime = Number((await archives().get(nodeId))?.toString()) || 0;
|
|
@@ -291,62 +278,45 @@ async function runHeartbeatAuditLoop() {
|
|
|
291
278
|
}
|
|
292
279
|
}
|
|
293
280
|
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
// Broadcast to all nodes the removal
|
|
297
|
-
for (let nodeId of allNodeIds2) {
|
|
298
|
-
if (isOwnNodeId(nodeId)) continue;
|
|
299
|
-
ignoreErrors(NodeDiscoveryController.nodes[nodeId].removeNodes(removedNodeIds));
|
|
281
|
+
if (removedNodeIds.length > 0) {
|
|
282
|
+
void tellEveryoneNodesChanges();
|
|
300
283
|
}
|
|
301
284
|
});
|
|
302
285
|
}
|
|
303
286
|
|
|
304
|
-
async function
|
|
305
|
-
let
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
let hash = await errorToUndefinedSilent(NodeDiscoveryController.nodes[nodeId].getAllNodesHash());
|
|
312
|
-
if (!hash) break;
|
|
313
|
-
let ownHash = getAllNodesHash();
|
|
314
|
-
if (hash === ownHash) break;
|
|
315
|
-
await delay(stableWait);
|
|
316
|
-
let hash2 = await errorToUndefinedSilent(NodeDiscoveryController.nodes[nodeId].getAllNodesHash());
|
|
317
|
-
if (!hash2) break;
|
|
318
|
-
if (hash === hash2) {
|
|
319
|
-
console.log(yellow(`Node discovery is out of sync, syncing with disk. Told by node ${nodeId}, our hash of ${ownHash} is wrong and should be ${hash2}`));
|
|
320
|
-
return true;
|
|
321
|
-
}
|
|
322
|
-
// Otherwise, the hash changed, so... we maybe we just caught it while it was changing.
|
|
323
|
-
// Wait less time, to try to catch up with the rate of change
|
|
324
|
-
stableWait /= 2;
|
|
325
|
-
if (stableWait < timeInSecond) {
|
|
326
|
-
// It is changing so fast we better just sync with the disk
|
|
327
|
-
console.log(yellow(`Node discovery is changing fast and likely out of sync, resyncing with disk. Told by node ${nodeId}`));
|
|
328
|
-
return true;
|
|
329
|
-
}
|
|
287
|
+
async function fastMemorySync(retries = 3) {
|
|
288
|
+
let checkNode = shuffle(Array.from(allNodeIds2).filter(x => x !== getOurNodeId()), Date.now()).slice(0, MEMORY_AUDIT_COUNT).at(0);
|
|
289
|
+
if (!checkNode) return;
|
|
290
|
+
let otherNodes = await errorToUndefinedSilent(NodeDiscoveryController.nodes[checkNode].getAllNodeIds());
|
|
291
|
+
if (!otherNodes) {
|
|
292
|
+
if (retries > 0) {
|
|
293
|
+
await fastMemorySync(retries - 1);
|
|
330
294
|
}
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
297
|
+
// If they are missing nodes that's fine. We constantly have extra nodes, and have to function correctly
|
|
298
|
+
// with extra nodes. However, if we are missing nodes, we'd prefer to have them quickly, so we should
|
|
299
|
+
// sync now.
|
|
300
|
+
let missingNodes = otherNodes.filter(nodeId => !allNodeIds2.has(nodeId));
|
|
301
|
+
if (missingNodes.length > 0) {
|
|
302
|
+
console.log(yellow(`Node list is missing nodes, resyncing node`), { checkNode, missingNodes, otherNodes });
|
|
303
|
+
await syncArchives();
|
|
331
304
|
}
|
|
332
305
|
}
|
|
333
306
|
|
|
334
307
|
async function runMemoryAuditLoop() {
|
|
335
308
|
await onNodeDiscoveryReady();
|
|
336
|
-
runInfinitePoll(MEMORY_AUDIT_RATE,
|
|
337
|
-
|
|
338
|
-
// per month to do this, which... is a lot less than the server to run this will cost!
|
|
339
|
-
//if (await isOutOfSync()) {
|
|
340
|
-
await syncArchives();
|
|
341
|
-
//}
|
|
342
|
-
});
|
|
309
|
+
runInfinitePoll(MEMORY_AUDIT_RATE, syncArchives);
|
|
310
|
+
runInfinitePoll(API_AUDIT_RATE, fastMemorySync);
|
|
343
311
|
}
|
|
344
312
|
|
|
345
313
|
async function writeHeartbeat() {
|
|
346
314
|
if (shutdown) return;
|
|
347
315
|
let now = Date.now();
|
|
348
316
|
console.log(green(`Writing heartbeat ${formatDateTime(now)}`));
|
|
349
|
-
|
|
317
|
+
let nodeId = getMountNodeId();
|
|
318
|
+
if (!nodeId) return;
|
|
319
|
+
await archives().set(nodeId, Buffer.from(now + ""));
|
|
350
320
|
}
|
|
351
321
|
|
|
352
322
|
async function runMainSyncLoops(discoveryReady: PromiseObj<void>) {
|
|
@@ -491,23 +461,22 @@ export async function nodeDiscoveryShutdown() {
|
|
|
491
461
|
if (isServer()) {
|
|
492
462
|
await archives().del(getOwnNodeId());
|
|
493
463
|
}
|
|
494
|
-
|
|
495
|
-
// (but do bother to tell other nodes!)
|
|
496
|
-
await Promise.allSettled(Array.from(allNodeIds2).map(async nodeId => {
|
|
497
|
-
if (isOwnNodeId(nodeId)) return;
|
|
498
|
-
await timeoutToUndefinedSilent(timeInSecond * 5, errorToUndefinedSilent(NodeDiscoveryController.nodes[nodeId].removeNodes([getOwnNodeId()])));
|
|
499
|
-
}));
|
|
464
|
+
void tellEveryoneNodesChanges();
|
|
500
465
|
}
|
|
466
|
+
const tellEveryoneNodesChanges = throttleFunction(1000, function tellEveryoneNodesChanges() {
|
|
467
|
+
for (let nodeId of allNodeIds2) {
|
|
468
|
+
if (isOwnNodeId(nodeId)) continue;
|
|
469
|
+
ignoreErrors(NodeDiscoveryController.nodes[nodeId].resyncNodes());
|
|
470
|
+
}
|
|
471
|
+
});
|
|
501
472
|
|
|
502
473
|
|
|
503
474
|
class NodeDiscoveryControllerBase {
|
|
504
475
|
public async addNode(nodeId: string) {
|
|
505
476
|
addNodeId(nodeId);
|
|
506
477
|
}
|
|
507
|
-
public async
|
|
508
|
-
|
|
509
|
-
console.log(`remote removeNode request`, { callerId, nodeIds });
|
|
510
|
-
removeNodeIds(nodeIds);
|
|
478
|
+
public async resyncNodes() {
|
|
479
|
+
await syncArchives();
|
|
511
480
|
}
|
|
512
481
|
public async getAllNodesHash(): Promise<string> {
|
|
513
482
|
return getAllNodesHash();
|
|
@@ -529,7 +498,7 @@ const NodeDiscoveryController = SocketFunction.register(
|
|
|
529
498
|
new NodeDiscoveryControllerBase(),
|
|
530
499
|
() => ({
|
|
531
500
|
addNode: { hooks: [requiresNetworkTrustHook] },
|
|
532
|
-
|
|
501
|
+
resyncNodes: { hooks: [requiresNetworkTrustHook] },
|
|
533
502
|
getAllNodesHash: { hooks: [requiresNetworkTrustHook] },
|
|
534
503
|
// Skip client hooks, so we don't block on authentication (IdentityController), as some of these functions
|
|
535
504
|
// are needed for authentication to finish!
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
import { SocketFunction } from "socket-function/SocketFunction";
|
|
6
6
|
import { SocketRegistered } from "socket-function/SocketFunctionTypes";
|
|
7
|
-
import { errorToUndefined, errorToUndefinedSilent,
|
|
7
|
+
import { errorToUndefined, errorToUndefinedSilent, timeoutToUndefinedSilent } from "../errors";
|
|
8
8
|
import { getAllNodeIds } from "../-f-node-discovery/NodeDiscovery";
|
|
9
9
|
import { green, red, yellow } from "socket-function/src/formatting/logColors";
|
|
10
10
|
import { shuffle } from "../misc/random";
|
|
@@ -55,7 +55,6 @@ class PathValueCommitter {
|
|
|
55
55
|
// Returns true if all the writes are accepted by some node (this should almost always be the case)
|
|
56
56
|
public commitValues(values: PathValue[], predictWrites: "predictWrites" | undefined): void {
|
|
57
57
|
if (values.length === 0) return;
|
|
58
|
-
|
|
59
58
|
ActionsHistory.OnWrite(values);
|
|
60
59
|
|
|
61
60
|
let now = Date.now();
|
|
@@ -23,7 +23,7 @@ import { LOCAL_DOMAIN_PATH } from "../0-path-value-core/NodePathAuthorities";
|
|
|
23
23
|
import { registerPeriodic } from "../diagnostics/periodic";
|
|
24
24
|
import { remoteWatcher } from "../1-path-client/RemoteWatcher";
|
|
25
25
|
import { Schema2, Schema2Fncs } from "./schema2";
|
|
26
|
-
import { getDomain } from "../config";
|
|
26
|
+
import { devDebugbreak, getDomain } from "../config";
|
|
27
27
|
|
|
28
28
|
import type { CallSpec } from "../3-path-functions/PathFunctionRunner";
|
|
29
29
|
import type { FunctionMetadata } from "../3-path-functions/syncSchema";
|
|
@@ -597,15 +597,6 @@ export class PathValueProxyWatcher {
|
|
|
597
597
|
throw new Error(`Tried to write a non-local path in a "noLocks" watcher, ${watcher.debugName}, path ${pathStr}`);
|
|
598
598
|
}
|
|
599
599
|
|
|
600
|
-
if (!pathStr.startsWith(LOCAL_DOMAIN_PATH)) {
|
|
601
|
-
// Copy the value, to ensure any proxy values aren't attempted to be written
|
|
602
|
-
// to the database. A bit slower, but... it should be fine. We COULD do this
|
|
603
|
-
// later on, but this makes it easier to attribute lag and errors to the original source.
|
|
604
|
-
// - If we had a proxy, we WOULD copy it eventually, but we would copy it later,
|
|
605
|
-
// which would cause an error, because the reader wouldn't be trackable.
|
|
606
|
-
value = deepCloneCborx(value);
|
|
607
|
-
}
|
|
608
|
-
|
|
609
600
|
if (watcher.permissionsChecker) {
|
|
610
601
|
if (!watcher.permissionsChecker.checkPermissions(pathStr).allowed) {
|
|
611
602
|
if (value !== specialObjectWriteValue) {
|
|
@@ -713,6 +704,14 @@ export class PathValueProxyWatcher {
|
|
|
713
704
|
};
|
|
714
705
|
addWrites(pathStr, value);
|
|
715
706
|
} else {
|
|
707
|
+
if (!pathStr.startsWith(LOCAL_DOMAIN_PATH)) {
|
|
708
|
+
// Copy the value, to ensure any proxy values aren't attempted to be written
|
|
709
|
+
// to the database. A bit slower, but... it should be fine. We COULD do this
|
|
710
|
+
// later on, but this makes it easier to attribute lag and errors to the original source.
|
|
711
|
+
// - If we had a proxy, we WOULD copy it eventually, but we would copy it later,
|
|
712
|
+
// which would cause an error, because the reader wouldn't be trackable.
|
|
713
|
+
value = deepCloneCborx(value);
|
|
714
|
+
}
|
|
716
715
|
watcher.pendingWrites.set(pathStr, value);
|
|
717
716
|
}
|
|
718
717
|
};
|
|
@@ -32,8 +32,11 @@ import { setRecord } from "../-b-authorities/dnsAuthority";
|
|
|
32
32
|
import tls from "tls";
|
|
33
33
|
import net from "net";
|
|
34
34
|
import { ButtonSelector } from "../library-components/ButtonSelector";
|
|
35
|
-
import { assertIsManagementUser } from "./managementPages";
|
|
35
|
+
import { assertIsManagementUser, managementPageURL } from "./managementPages";
|
|
36
36
|
import { SocketRegistered } from "socket-function/SocketFunctionTypes";
|
|
37
|
+
import { ATag } from "../library-components/ATag";
|
|
38
|
+
import { filterURL, selectedNodeId } from "./logs/DiskLoggerPage";
|
|
39
|
+
import { getSyncedController } from "../library-components/SyncedController";
|
|
37
40
|
|
|
38
41
|
|
|
39
42
|
type NodeData = {
|
|
@@ -162,7 +165,7 @@ export class NodeViewer extends qreact.Component {
|
|
|
162
165
|
|
|
163
166
|
let tables: { [key: string]: NodeData[] } = {};
|
|
164
167
|
tables["PathValueServer"] = [];
|
|
165
|
-
tables["
|
|
168
|
+
tables["querysub-function"] = [];
|
|
166
169
|
tables["Querysub"] = [];
|
|
167
170
|
for (let datum of nodeDatas) {
|
|
168
171
|
if (datum.live_authorityPaths?.length) {
|
|
@@ -170,7 +173,7 @@ export class NodeViewer extends qreact.Component {
|
|
|
170
173
|
} else if (datum.live_exposedControllers?.includes("QuerysubController-6db5ef05-7563-4473-a440-2f64f03fe6ef")) {
|
|
171
174
|
tables["Querysub"].push(datum);
|
|
172
175
|
} else if (datum.live_entryPoint?.endsWith("function.js")) {
|
|
173
|
-
tables["
|
|
176
|
+
tables["querysub-function"].push(datum);
|
|
174
177
|
} else {
|
|
175
178
|
let entryName = datum.live_entryPoint?.replaceAll("\\", "/").split("/").pop() || "Unknown";
|
|
176
179
|
tables[entryName] = tables[entryName] || [];
|
|
@@ -179,7 +182,7 @@ export class NodeViewer extends qreact.Component {
|
|
|
179
182
|
}
|
|
180
183
|
|
|
181
184
|
let builtinGroups = {
|
|
182
|
-
"Default": ["buttons", "devToolsURL", "ip", "uptime", "Heap", "All Memory", "Blocking Lag", "port", "threadId", "machineId", "apiError", "live_entryPoint"],
|
|
185
|
+
"Default": ["buttons", "devToolsURL", "nodeId", "ip", "uptime", "Heap", "All Memory", "Blocking Lag", "port", "threadId", "machineId", "apiError", "live_entryPoint"],
|
|
183
186
|
};
|
|
184
187
|
// Column => group
|
|
185
188
|
let builtInGroupsLookup = new Map<string, string>();
|
|
@@ -256,6 +259,23 @@ export class NodeViewer extends qreact.Component {
|
|
|
256
259
|
);
|
|
257
260
|
},
|
|
258
261
|
},
|
|
262
|
+
nodeId: {
|
|
263
|
+
formatter: (obj) => {
|
|
264
|
+
let str = String(obj);
|
|
265
|
+
if (str.startsWith("http")) return formatValue(obj);
|
|
266
|
+
https://noproxy.querysub.com:1111/?page=test&showingmanagement&managementpage=DiskLoggerPage&nodeId=b4d19fba5f79d48c3.b68f46ffaffad0636.querysub.com%3A41863&filter=%22%5C%22__nodeId%5C%22%3A%5C%22b654f522bf3a67c49.b68f46ffaffad0636.querysub.com%3A33473%5C%22%22
|
|
267
|
+
|
|
268
|
+
return (
|
|
269
|
+
<ATag values={[
|
|
270
|
+
managementPageURL.getOverride("DiskLoggerPage"),
|
|
271
|
+
selectedNodeId.getOverride(str),
|
|
272
|
+
filterURL.getOverride(`"__nodeId":"${str}"`),
|
|
273
|
+
]}>
|
|
274
|
+
Logs
|
|
275
|
+
</ATag>
|
|
276
|
+
);
|
|
277
|
+
},
|
|
278
|
+
},
|
|
259
279
|
ip: {},
|
|
260
280
|
...x.table?.columns,
|
|
261
281
|
//capabilities: null,
|
|
@@ -500,4 +520,6 @@ export const NodeViewerController = SocketFunction.register(
|
|
|
500
520
|
// Auto expose, for getMiscInfo. This is protected via assertIsManagementUser anyways.
|
|
501
521
|
//noAutoExpose: true,
|
|
502
522
|
}
|
|
503
|
-
);
|
|
523
|
+
);
|
|
524
|
+
|
|
525
|
+
export let nodeViewerController = getSyncedController(NodeViewerController);
|
|
@@ -18,7 +18,7 @@ import { LogType } from "../errorLogs/ErrorLogCore";
|
|
|
18
18
|
import { canHaveChildren } from "socket-function/src/types";
|
|
19
19
|
import { measureBlock } from "socket-function/src/profiling/measure";
|
|
20
20
|
import { binarySearchBasic, list, sort, timeInDay, timeInHour } from "socket-function/src/misc";
|
|
21
|
-
import { NodeViewerController } from "../NodeViewer";
|
|
21
|
+
import { NodeViewerController, nodeViewerController } from "../NodeViewer";
|
|
22
22
|
import { red } from "socket-function/src/formatting/logColors";
|
|
23
23
|
import { errorMessage, formatValue, genericFormat, warnMessage } from "../../5-diagnostics/GenericFormat";
|
|
24
24
|
import { hslToRGB } from "socket-function/src/formatting/colors";
|
|
@@ -51,9 +51,9 @@ import { TimeRangeSelector } from "../../library-components/TimeRangeSelector";
|
|
|
51
51
|
module.hotreload = true;
|
|
52
52
|
module.hotreload = true;
|
|
53
53
|
|
|
54
|
-
let selectedNodeId = new URLParam("nodeId", "");
|
|
54
|
+
export let selectedNodeId = new URLParam("nodeId", "");
|
|
55
55
|
|
|
56
|
-
let filterURL = new URLParam("filter", "");
|
|
56
|
+
export let filterURL = new URLParam("filter", "");
|
|
57
57
|
let sortOldestFirst = new URLParam("oldestFirst", false);
|
|
58
58
|
let selectedFields = new URLParam("selectedFields", "");
|
|
59
59
|
|
|
@@ -426,12 +426,7 @@ const processLogs = cacheShallowConfigArgEqual((config: {
|
|
|
426
426
|
return true;
|
|
427
427
|
})).filter(x => x.length > 0);
|
|
428
428
|
function logMatches(filter: string, log: LogObj) {
|
|
429
|
-
|
|
430
|
-
if (key.toLowerCase().includes(filter)) return true;
|
|
431
|
-
if (canHaveChildren(value) && JSON.stringify(value).toLowerCase().includes(filter)) return true;
|
|
432
|
-
if (String(value).toLowerCase().includes(filter)) return true;
|
|
433
|
-
}
|
|
434
|
-
return false;
|
|
429
|
+
return JSON.stringify(log).toLowerCase().includes(filter);
|
|
435
430
|
}
|
|
436
431
|
logMatchesFilter = function logMatchesFilter(log: LogObj) {
|
|
437
432
|
return (
|
|
@@ -567,6 +562,4 @@ export const DiskLoggerController = SocketFunction.register(
|
|
|
567
562
|
}
|
|
568
563
|
);
|
|
569
564
|
|
|
570
|
-
let diskLoggerController = getSyncedController(DiskLoggerController);
|
|
571
|
-
|
|
572
|
-
let nodeViewerController = getSyncedController(NodeViewerController);
|
|
565
|
+
let diskLoggerController = getSyncedController(DiskLoggerController);
|