querysub 0.371.0 → 0.373.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/deployManager/components/ServicesListPage.tsx +1 -1
- package/src/diagnostics/logs/IndexedLogs/FilePathSelector.tsx +12 -6
- package/src/diagnostics/logs/IndexedLogs/IndexedLogs.ts +27 -17
- package/src/diagnostics/logs/IndexedLogs/LogViewer3.tsx +12 -0
- package/src/diagnostics/logs/IndexedLogs/moveIndexLogsToPublic.ts +3 -2
- package/src/diagnostics/logs/lifeCycleAnalysis/lifeCycles.tsx +11 -10
package/package.json
CHANGED
|
@@ -130,7 +130,7 @@ export class ServicesListPage extends qreact.Component {
|
|
|
130
130
|
{config.parameters.key}
|
|
131
131
|
</div>
|
|
132
132
|
<div>
|
|
133
|
-
{enabledMachineIds.length} configured {disabledMachines.length > 0 && `(+${disabledMachines.length} on disabled machines)`} {failingMachines.length > 0 && `(${failingMachines.length} failing)`} {missingMachines.length > 0 && `(${missingMachines.length} machine hasn't run service yet)`} {unknown > 0 && `(${unknown} unknown)`} • {totalLaunches} launches •
|
|
133
|
+
<span className={css.boldStyle.fontSize(14)}>{enabledMachineIds.length}</span> configured {disabledMachines.length > 0 && `(+${disabledMachines.length} on disabled machines)`} {failingMachines.length > 0 && `(${failingMachines.length} failing)`} {missingMachines.length > 0 && `(${missingMachines.length} machine hasn't run service yet)`} {unknown > 0 && `(${unknown} unknown)`} • {totalLaunches} launches •
|
|
134
134
|
Deploy: {config.parameters.deploy ? "enabled" : "disabled"}
|
|
135
135
|
</div>
|
|
136
136
|
</div>
|
|
@@ -25,6 +25,15 @@ export type FilePathsByMachine = {
|
|
|
25
25
|
errorCount: number;
|
|
26
26
|
};
|
|
27
27
|
|
|
28
|
+
function getSourceColor(sourceName: string | undefined): string | undefined {
|
|
29
|
+
if (!sourceName) return undefined;
|
|
30
|
+
const lastPart = sourceName.split("/").pop()?.toLowerCase();
|
|
31
|
+
if (lastPart === "error") return css.colorhsl(0, 80, 40);
|
|
32
|
+
if (lastPart === "warn") return css.colorhsl(40, 80, 40);
|
|
33
|
+
if (lastPart === "info") return css.colorhsl(280, 80, 40);
|
|
34
|
+
if (lastPart === "log") return css.colorhsl(200, 80, 40);
|
|
35
|
+
return undefined;
|
|
36
|
+
}
|
|
28
37
|
|
|
29
38
|
export class FilePathSelector extends qreact.Component<{
|
|
30
39
|
paths: TimeFilePathWithSize[];
|
|
@@ -136,8 +145,6 @@ export class FilePathSelector extends qreact.Component<{
|
|
|
136
145
|
<div>|</div>
|
|
137
146
|
<div>Machines: {formatNumber(grouped.length)}</div>
|
|
138
147
|
<div>|</div>
|
|
139
|
-
<div>Threads: {formatNumber(totals.uniqueThreads)}</div>
|
|
140
|
-
<div>|</div>
|
|
141
148
|
<div>Files: {formatNumber(this.props.paths.length)}</div>
|
|
142
149
|
<div>|</div>
|
|
143
150
|
<div>Pending: {formatNumber(totals.totalPending)}</div>
|
|
@@ -379,7 +386,7 @@ export class FilePathSelectorModal extends qreact.Component<{
|
|
|
379
386
|
</td>
|
|
380
387
|
<td className={css.pad2(2)}>{this.props.formatBytes(file.size)}</td>
|
|
381
388
|
<td className={css.pad2(2)}>{file.logCount !== undefined ? formatNumber(file.logCount) : <span className={css.colorhsl(40, 60, 40)}>pending</span>}</td>
|
|
382
|
-
<td className={css.pad2(2)}>{file.sourceName}</td>
|
|
389
|
+
<td className={css.pad2(2) + (getSourceColor(file.sourceName) || "")}>{file.sourceName}</td>
|
|
383
390
|
<td className={css.pad2(2)}>{file.dedupe}</td>
|
|
384
391
|
<td className={css.pad2(2)}>{formatDateTime(file.startTime)}</td>
|
|
385
392
|
<td className={css.pad2(2)}>
|
|
@@ -418,8 +425,7 @@ export class FilePathSelectorModal extends qreact.Component<{
|
|
|
418
425
|
<div className={css.vbox(5)}>
|
|
419
426
|
<div className={css.hbox(10)}>
|
|
420
427
|
<div className={css.minWidth(120)}>Machines: {formatNumber(summary.machineCount)}</div>
|
|
421
|
-
{
|
|
422
|
-
{/* <div className={css.minWidth(110)}>Threads: {formatNumber(summary.threadCount)}</div> */}
|
|
428
|
+
<div className={css.minWidth(110)}>Threads: {formatNumber(summary.threadCount)}</div>
|
|
423
429
|
<div className={css.minWidth(140)}>Files: {formatNumber(summary.fileCount)} ({formatNumber(summary.pendingCount)} pending)</div>
|
|
424
430
|
<div className={css.minWidth(120)}>Size: {this.props.formatBytes(summary.totalSize)}</div>
|
|
425
431
|
<div className={css.minWidth(100)}>Logs: {formatNumber(summary.totalLogCount)}</div>
|
|
@@ -432,7 +438,7 @@ export class FilePathSelectorModal extends qreact.Component<{
|
|
|
432
438
|
<div className={css.vbox(5)}>
|
|
433
439
|
{Array.from(bySource.entries()).map(([sourceName, stats]) => (
|
|
434
440
|
<div key={sourceName} className={css.hbox(10)}>
|
|
435
|
-
<div className={css.minWidth(240)}>{sourceName}:</div>
|
|
441
|
+
<div className={css.minWidth(240) + (getSourceColor(sourceName) || "")}>{sourceName}:</div>
|
|
436
442
|
<div className={css.minWidth(140)}>Files: {formatNumber(stats.fileCount)} ({formatNumber(stats.pendingCount)} pending)</div>
|
|
437
443
|
<div className={css.minWidth(120)}>Size: {this.props.formatBytes(stats.size)}</div>
|
|
438
444
|
<div className={css.minWidth(100)}>Logs: {formatNumber(stats.logCount)}</div>
|
|
@@ -25,6 +25,7 @@ import { blue } from "socket-function/src/formatting/logColors";
|
|
|
25
25
|
import { LimitGroup } from "../../../functional/limitProcessing";
|
|
26
26
|
import { getAllNodeIds } from "../../../-f-node-discovery/NodeDiscovery";
|
|
27
27
|
import { NodeCapabilitiesController } from "../../../-g-core-values/NodeCapabilities";
|
|
28
|
+
import { getLoggers2Async } from "../diskLogger";
|
|
28
29
|
|
|
29
30
|
export type TimeFilePathWithSize = TimeFilePath & {
|
|
30
31
|
size: number;
|
|
@@ -40,7 +41,6 @@ export class IndexedLogs<T> {
|
|
|
40
41
|
name: string,
|
|
41
42
|
maxSingleFileData?: number;
|
|
42
43
|
maxCountPerFile?: number;
|
|
43
|
-
forceUsePublicLogs?: boolean;
|
|
44
44
|
getTime: (result: T) => number | undefined;
|
|
45
45
|
}) {
|
|
46
46
|
loggerByName.set(this.config.name, this as any);
|
|
@@ -48,9 +48,10 @@ export class IndexedLogs<T> {
|
|
|
48
48
|
|
|
49
49
|
|
|
50
50
|
private static shouldRunLoop = false;
|
|
51
|
-
public static runLogMoveLoop() {
|
|
51
|
+
public static async runLogMoveLoop() {
|
|
52
52
|
IndexedLogs.shouldRunLoop = true;
|
|
53
|
-
|
|
53
|
+
let allLoggers = await getLoggers2Async();
|
|
54
|
+
for (let indexedLogs of Object.values(allLoggers)) {
|
|
54
55
|
indexedLogs.runLogMoverLoop();
|
|
55
56
|
}
|
|
56
57
|
}
|
|
@@ -91,7 +92,7 @@ export class IndexedLogs<T> {
|
|
|
91
92
|
let basePublic: Archives = getArchivesHome(getDomain());
|
|
92
93
|
// NOTE: The local disk is so fast that reading in 10 megabytes is nothing, And if we read in too small of a value, the overhead per read ends up making this take forever.
|
|
93
94
|
let extraReadSize = 1024 * 1024 * 10;
|
|
94
|
-
if (
|
|
95
|
+
if (isPublic()) {
|
|
95
96
|
basePublic = getArchivesBackblaze(getDomain());
|
|
96
97
|
// NOTE: While the latency to back plays is high, now we're reading in parallel, so it shouldn't be as big of an issue.
|
|
97
98
|
extraReadSize = 1024 * 1024 * 1;
|
|
@@ -274,8 +275,16 @@ export class IndexedLogs<T> {
|
|
|
274
275
|
forceReadPublic?: boolean;
|
|
275
276
|
}): Promise<TimeFilePathWithSize[]> {
|
|
276
277
|
let finalPaths: TimeFilePathWithSize[] = [];
|
|
278
|
+
if (config.forceReadPublic && !isPublic()) {
|
|
279
|
+
let machineNodes = await this.getMachineNodes();
|
|
280
|
+
if (machineNodes.length === 0) throw new Error(`Cannot find any public nodes to read from`);
|
|
281
|
+
return await IndexedLogShimController.nodes[machineNodes[0]].getPaths({
|
|
282
|
+
...config,
|
|
283
|
+
indexedLogsName: this.config.name,
|
|
284
|
+
});
|
|
285
|
+
}
|
|
277
286
|
|
|
278
|
-
if (
|
|
287
|
+
if (config.only !== "local" && isPublic()) {
|
|
279
288
|
let machineNodes = await this.getMachineNodes();
|
|
280
289
|
await Promise.all(machineNodes.map(async (machineNode) => {
|
|
281
290
|
try {
|
|
@@ -291,11 +300,6 @@ export class IndexedLogs<T> {
|
|
|
291
300
|
}));
|
|
292
301
|
}
|
|
293
302
|
|
|
294
|
-
// 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
|
|
295
|
-
if (!isPublic() && config.forceReadPublic) {
|
|
296
|
-
return finalPaths;
|
|
297
|
-
}
|
|
298
|
-
|
|
299
303
|
let localLogs = this.getLocalLogs();
|
|
300
304
|
let backblazeLogs = this.getPublicLogs();
|
|
301
305
|
let paths: TimeFilePath[] = [];
|
|
@@ -347,6 +351,16 @@ export class IndexedLogs<T> {
|
|
|
347
351
|
onResult: (match: T) => void;
|
|
348
352
|
onResults?: (results: IndexedLogResults) => Promise<boolean>;
|
|
349
353
|
}): Promise<IndexedLogResults> {
|
|
354
|
+
|
|
355
|
+
if (config.params.forceReadPublic && !isPublic()) {
|
|
356
|
+
let machineNodes = await this.getMachineNodes();
|
|
357
|
+
if (machineNodes.length === 0) throw new Error(`Cannot find any public nodes to read from`);
|
|
358
|
+
return await this.clientFind({
|
|
359
|
+
...config,
|
|
360
|
+
nodeId: machineNodes[0],
|
|
361
|
+
});
|
|
362
|
+
}
|
|
363
|
+
|
|
350
364
|
let startTime = Date.now();
|
|
351
365
|
let interval: NodeJS.Timeout | undefined;
|
|
352
366
|
|
|
@@ -360,7 +374,8 @@ export class IndexedLogs<T> {
|
|
|
360
374
|
let allResults = new Map<string, IndexedLogResults>();
|
|
361
375
|
let allDone: Promise<void>[] = [];
|
|
362
376
|
|
|
363
|
-
|
|
377
|
+
// Read other nodes if on a public server
|
|
378
|
+
if (config.params.only !== "local" && isPublic()) {
|
|
364
379
|
let machineNodes = await this.getMachineNodes();
|
|
365
380
|
allDone.push(...machineNodes.map(async (machineNode) => {
|
|
366
381
|
try {
|
|
@@ -385,12 +400,6 @@ export class IndexedLogs<T> {
|
|
|
385
400
|
}));
|
|
386
401
|
}
|
|
387
402
|
|
|
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
|
|
389
|
-
if (!isPublic() && config.params.forceReadPublic) {
|
|
390
|
-
await Promise.all(allDone);
|
|
391
|
-
return getFinalResults();
|
|
392
|
-
}
|
|
393
|
-
|
|
394
403
|
|
|
395
404
|
let results: IndexedLogResults = createEmptyIndexedLogResults();
|
|
396
405
|
allResults.set("", results);
|
|
@@ -588,6 +597,7 @@ export class IndexedLogs<T> {
|
|
|
588
597
|
}
|
|
589
598
|
|
|
590
599
|
await moveLogsToPublic({
|
|
600
|
+
loggerName: this.config.name,
|
|
591
601
|
forceAll,
|
|
592
602
|
localLogs: this.getLocalLogs(),
|
|
593
603
|
publicLogs: this.getPublicLogs(),
|
|
@@ -686,11 +686,23 @@ export class LogViewer3 extends qreact.Component {
|
|
|
686
686
|
checkbox
|
|
687
687
|
label="Exclude Pending Results"
|
|
688
688
|
url={excludePendingResults}
|
|
689
|
+
onChangeValue={(newValue) => {
|
|
690
|
+
if (newValue) {
|
|
691
|
+
savedPathsURL.value = "";
|
|
692
|
+
void this.loadPaths();
|
|
693
|
+
}
|
|
694
|
+
}}
|
|
689
695
|
/>
|
|
690
696
|
{!isPublic() && <InputLabelURL
|
|
691
697
|
checkbox
|
|
692
698
|
label="Read Public Logs"
|
|
693
699
|
url={readPublicLogs}
|
|
700
|
+
onChangeValue={(newValue) => {
|
|
701
|
+
if (newValue) {
|
|
702
|
+
savedPathsURL.value = "";
|
|
703
|
+
void this.loadPaths();
|
|
704
|
+
}
|
|
705
|
+
}}
|
|
694
706
|
/>}
|
|
695
707
|
<InputLabelURL
|
|
696
708
|
label="Limit"
|
|
@@ -5,12 +5,13 @@ import { getOwnThreadId } from "../../../-f-node-discovery/NodeDiscovery";
|
|
|
5
5
|
import { BufferIndex } from "./BufferIndex";
|
|
6
6
|
import { LogStreamer } from "./LogStreamer";
|
|
7
7
|
import { TimeFileTree } from "./TimeFileTree";
|
|
8
|
-
import { green, magenta } from "socket-function/src/formatting/logColors";
|
|
8
|
+
import { blue, green, magenta } from "socket-function/src/formatting/logColors";
|
|
9
9
|
import { formatNumber, formatTime } from "socket-function/src/formatting/format";
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
export async function moveLogsToPublic(config: {
|
|
14
|
+
loggerName: string;
|
|
14
15
|
publicMoveThreshold: number;
|
|
15
16
|
maxSingleFileData: number;
|
|
16
17
|
movingTimeout: number;
|
|
@@ -128,7 +129,7 @@ export async function moveLogsToPublic(config: {
|
|
|
128
129
|
|
|
129
130
|
if (!await tryToGetMoveLock()) return;
|
|
130
131
|
|
|
131
|
-
console.log(magenta(`Moving ${localPaths.length} log files to public`));
|
|
132
|
+
console.log(magenta(`Moving ${localPaths.length} log files to public (${blue(config.loggerName)})`), { loggerName: config.loggerName, localPaths });
|
|
132
133
|
|
|
133
134
|
let byStartTime = keyByArray(localPaths, x => x.startTime);
|
|
134
135
|
|
|
@@ -20,21 +20,22 @@ IMPORTANT! Now I am properly calling shutdown, so none of the streamed logs shou
|
|
|
20
20
|
|
|
21
21
|
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
2) Create lot of remote server logs
|
|
26
|
-
- Via our refresh loop
|
|
27
|
-
|
|
28
|
-
3) Ensure our moveloops are working correctly
|
|
29
|
-
|
|
30
|
-
|
|
23
|
+
3) Ensure our moveloops are working correctly, on both dev and public
|
|
31
24
|
|
|
32
25
|
|
|
33
26
|
1) Fix missing __NAME__
|
|
34
|
-
|
|
35
|
-
|
|
27
|
+
"Received PathValue for path" misses name?
|
|
28
|
+
- Maybe the missing name only happens when we rate limit?
|
|
36
29
|
|
|
30
|
+
2) Create lot of remote server logs
|
|
31
|
+
- Via our refresh loop
|
|
37
32
|
|
|
33
|
+
3) Verify search is still fast, and works correctly!
|
|
34
|
+
- Try to get a rare value in that is in the logs, but is hard to find
|
|
35
|
+
Good rare search. Checks for sending emails, which we do very rarely. If we pack in 10GB of logs after this, it will really stress our indexing system.
|
|
36
|
+
- At the moment our pending index has a good hit rate (0 false positives out of 1720). We'll see if this continues for our remote index.
|
|
37
|
+
https://127-0-0-1.querysubtest.com:7007/?hot&readPublicLogs&showingmanagement&machineview=services&managementpage=LogViewer3&searchText=Sending%20email&selectedFields=%7B%22path%22%3Atrue%7D
|
|
38
|
+
|
|
38
39
|
|
|
39
40
|
|
|
40
41
|
Rewrite error notification code
|