querysub 0.356.0 → 0.358.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/.cursorrules +9 -0
- package/bin/movelogs.js +4 -0
- package/package.json +13 -6
- package/scripts/postinstall.js +23 -0
- package/src/-a-archives/archiveCache.ts +10 -12
- package/src/-a-archives/archives.ts +29 -0
- package/src/-a-archives/archivesBackBlaze.ts +60 -12
- package/src/-a-archives/archivesDisk.ts +39 -13
- package/src/-a-archives/archivesLimitedCache.ts +21 -0
- package/src/-a-archives/archivesMemoryCache.ts +374 -0
- package/src/-a-archives/archivesPrivateFileSystem.ts +22 -0
- package/src/-g-core-values/NodeCapabilities.ts +3 -0
- package/src/0-path-value-core/auditLogs.ts +5 -1
- package/src/0-path-value-core/pathValueCore.ts +7 -7
- package/src/4-dom/qreact.tsx +1 -0
- package/src/4-querysub/Querysub.ts +1 -5
- package/src/config.ts +5 -0
- package/src/deployManager/components/MachineDetailPage.tsx +43 -2
- package/src/deployManager/components/MachinesListPage.tsx +10 -2
- package/src/deployManager/machineApplyMainCode.ts +3 -3
- package/src/deployManager/machineSchema.ts +39 -0
- package/src/diagnostics/MachineThreadInfo.tsx +235 -0
- package/src/diagnostics/NodeViewer.tsx +5 -3
- package/src/diagnostics/logs/FastArchiveAppendable.ts +79 -42
- package/src/diagnostics/logs/FastArchiveController.ts +102 -63
- package/src/diagnostics/logs/FastArchiveViewer.tsx +36 -8
- package/src/diagnostics/logs/IndexedLogs/BufferIndex.ts +462 -0
- package/src/diagnostics/logs/IndexedLogs/BufferIndexCPP.cpp +327 -0
- package/src/diagnostics/logs/IndexedLogs/BufferIndexCPP.d.ts +18 -0
- package/src/diagnostics/logs/IndexedLogs/BufferIndexCPP.js +1 -0
- package/src/diagnostics/logs/IndexedLogs/BufferIndexHelpers.ts +222 -0
- package/src/diagnostics/logs/IndexedLogs/BufferIndexLogsOptimizationConstants.ts +22 -0
- package/src/diagnostics/logs/IndexedLogs/BufferIndexWAT.wat +1145 -0
- package/src/diagnostics/logs/IndexedLogs/BufferIndexWAT.wat.d.ts +178 -0
- package/src/diagnostics/logs/IndexedLogs/BufferListStreamer.ts +208 -0
- package/src/diagnostics/logs/IndexedLogs/BufferUnitIndex.ts +716 -0
- package/src/diagnostics/logs/IndexedLogs/BufferUnitSet.ts +146 -0
- package/src/diagnostics/logs/IndexedLogs/FilePathSelector.tsx +569 -0
- package/src/diagnostics/logs/IndexedLogs/FindProgressTracker.ts +45 -0
- package/src/diagnostics/logs/IndexedLogs/IndexedLogs.ts +685 -0
- package/src/diagnostics/logs/IndexedLogs/LogStreamer.ts +47 -0
- package/src/diagnostics/logs/IndexedLogs/LogViewer3.tsx +901 -0
- package/src/diagnostics/logs/IndexedLogs/TimeFileTree.ts +236 -0
- package/src/diagnostics/logs/IndexedLogs/binding.gyp +23 -0
- package/src/diagnostics/logs/IndexedLogs/moveIndexLogsToPublic.ts +251 -0
- package/src/diagnostics/logs/IndexedLogs/moveLogsEntry.ts +10 -0
- package/src/diagnostics/logs/LogViewer2.tsx +120 -55
- package/src/diagnostics/logs/TimeRangeSelector.tsx +5 -2
- package/src/diagnostics/logs/diskLogger.ts +32 -48
- package/src/diagnostics/logs/errorNotifications/ErrorNotificationController.ts +3 -2
- package/src/diagnostics/logs/errorNotifications/errorDigests.tsx +1 -0
- package/src/diagnostics/logs/errorNotifications2/errorNotifications2.ts +0 -0
- package/src/diagnostics/logs/lifeCycleAnalysis/LifeCyclePages.tsx +150 -0
- package/src/diagnostics/logs/lifeCycleAnalysis/lifeCycles.tsx +150 -15
- package/src/diagnostics/logs/lifeCycleAnalysis/test.ts +0 -0
- package/src/diagnostics/logs/lifeCycleAnalysis/test.wat +106 -0
- package/src/diagnostics/logs/lifeCycleAnalysis/test.wat.d.ts +2 -0
- package/src/diagnostics/logs/lifeCycleAnalysis/testHoist.ts +5 -0
- package/src/diagnostics/logs/logViewerExtractField.ts +2 -3
- package/src/diagnostics/managementPages.tsx +10 -0
- package/src/diagnostics/trackResources.ts +1 -1
- package/src/functional/limitProcessing.ts +39 -0
- package/src/misc/lz4_wasm_nodejs.d.ts +34 -0
- package/src/misc/lz4_wasm_nodejs.js +178 -0
- package/src/misc/lz4_wasm_nodejs_bg.js +94 -0
- package/src/misc/lz4_wasm_nodejs_bg.wasm +0 -0
- package/src/misc/lz4_wasm_nodejs_bg.wasm.d.ts +15 -0
- package/src/storage/CompressedStream.ts +13 -0
- package/src/storage/LZ4.ts +32 -0
- package/src/storage/ZSTD.ts +10 -0
- package/src/wat/watCompiler.ts +1716 -0
- package/src/wat/watGrammar.pegjs +93 -0
- package/src/wat/watHandler.ts +179 -0
- package/src/wat/watInstructions.txt +707 -0
- package/src/zip.ts +3 -89
- package/src/diagnostics/logs/lifeCycleAnalysis/spec.md +0 -125
|
@@ -1,16 +1,151 @@
|
|
|
1
|
-
//todonext
|
|
2
|
-
// Welp... no logs are showing up. That's a problem..
|
|
3
|
-
// Ah, okay, we don't store logs locally. Because... we only log to backblaze? Alright, fair enough...
|
|
4
1
|
/*
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
-
|
|
14
|
-
-
|
|
15
|
-
|
|
16
|
-
|
|
2
|
+
todonext
|
|
3
|
+
|
|
4
|
+
OKAY! CORE CONCEPTS
|
|
5
|
+
- Index needs to be fast searched, so it's uncompressed form has to be small
|
|
6
|
+
- Nesting compression is fine, as long as it's small enough that each search decompresses very little
|
|
7
|
+
- The enemy is storing every single position, we get around this by:
|
|
8
|
+
- In-exact matches, only storing block indexes.
|
|
9
|
+
- Requires full search to verify, but... in practice has low false hit rate
|
|
10
|
+
- Input key (unit) is only inexact matched.
|
|
11
|
+
- Input query almost always has more than 1 byte of uniqueness. This means if even part is only 50% accurate, we can still get very high hit rates (8 bytes means 255/256 hit rate!)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
todonext
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
IMPORTANT! Now I am properly calling shutdown, so none of the streamed logs should ever break. The code should be waiting until everything's fully flushed before it allows the shutdown handler to finish running. If we see any more errors, we need to investigate them.
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
4) Make it easy to enable or disable an entire server, regardless of what services are on it.
|
|
23
|
+
- This is annoying, but it would be very useful. I think the apply loop can probably figure it out. We should probably ask the AI to do it. I'm sure it'll fuck it up, but it'll give us a start at least. And we can also just tell it, okay, find the actual code that we're going to need to change, but not change it, and just keep and maybe even have it put a comment there. And then we just keep doing that until we're absolutely certain that we found every place that we need to change to make this work. And then the AI might be able to help with the refactor.
|
|
24
|
+
3) Start the servers again, and deploy all of our code
|
|
25
|
+
|
|
26
|
+
2) Create lot of remote server logs
|
|
27
|
+
- Via our refresh loop
|
|
28
|
+
|
|
29
|
+
2.0) SUPPORT reading pending from multiple servers
|
|
30
|
+
- The main controller has to find a node on each other machine, and call it. Only one node per machine though, so it shouldn't be too difficult.
|
|
31
|
+
- We'll cache the last node per machine that we picked.
|
|
32
|
+
- If the cache value doesn't exist, or if it doesn't work, if it throws an error when we try to verify it works, then we'll call a function to get the entry point on all of the nodes for that machine
|
|
33
|
+
- After we receive the first result, we'll wait at least a second so we get some more results, and then we'll prioritize the one that's the function endpoint, which will end in function.js.
|
|
34
|
+
|
|
35
|
+
2) Add a UI toggle to read public logs (only shows up on a non-public server though, as otherwise it wouldn't make sense)
|
|
36
|
+
- Basically, just changes the code we're reading from multiple servers to select public servers instead, and then, of course, skip ourselves.
|
|
37
|
+
|
|
38
|
+
3) Verify true remote reads are reasonable fast
|
|
39
|
+
|
|
40
|
+
3) Deploy service for movelogs
|
|
41
|
+
0) Run move logs in function runner, in development, just so we don't get too far behind
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
1) Fix missing __NAME__
|
|
48
|
+
"Received PathValue for path" misses name?
|
|
49
|
+
- Maybe the missing name only happens when we rate limit?
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
Rewrite error notification code
|
|
55
|
+
THINK about how to do a somewhat generic logs => derived thing, as... we will need the exact same thing for life cycles!
|
|
56
|
+
- Maybe make it generic immediately? Having it abstracted it kind of nice for development anyways...
|
|
57
|
+
- New service that manages it, instead of doing it on demand
|
|
58
|
+
- It asks everyone to send it error logs
|
|
59
|
+
- Stores cached error logs => { unsuppressed logs, suppressionSummary }
|
|
60
|
+
- Unsuppressed logs only for suppression which is old enough.
|
|
61
|
+
- Only when logs are old enough.
|
|
62
|
+
- Stores in memory with all suppressionSummaries
|
|
63
|
+
AND, the only watcher will be the watcher service. You can't get recent errors, or any errors, without going through one of those
|
|
64
|
+
NO dev errors. They are usually red-herrings anyways... and we should just be using public servers for regular usage
|
|
65
|
+
- And we still have dev logs we can check if to see if an error happened locally
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
Remove all old LogViewer/FastArchiveAppendable code
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
0) Add LZ4 compression to socket-function by default
|
|
73
|
+
- Allow setting "compress" to "none" or "lz4" or "zip" or "zip0" or "zip3", etc, for levels.
|
|
74
|
+
- default is "lz4"
|
|
75
|
+
- REQUIRES feature checking the remote, to make sure it is new enough to accept this.
|
|
76
|
+
- A generic thing which gets the version is probably fine.
|
|
77
|
+
- LZ4 compression is fast enough that this should cause basically no overhead, and in many cases greatly reduce the bandwidth (which will increase the speed).
|
|
78
|
+
- We're gonna have to investigate how we're sending buffers anyway. I think this should be easy, but we
|
|
79
|
+
0.1) Verify the size distance with some local testing
|
|
80
|
+
- ALSO, verify the processing overhead is acceptable.
|
|
81
|
+
1) Deploy, which SHOULD be backwards compatible with everything?
|
|
82
|
+
|
|
83
|
+
*/
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
// todonext;
|
|
90
|
+
// Hmm... so... should we index it, so we can search it? HMM... I think we might want to?
|
|
91
|
+
// - Although the searches might get a bit complicated...
|
|
92
|
+
// - I think we need to limit lifecycle lengths? Hmm... as otherwise we need a lot in memory at once?
|
|
93
|
+
// - We could always do it based on size, so if we have too many logs the max time length is less
|
|
94
|
+
// 7) Decide how we're going to store it, and setup the controller
|
|
95
|
+
// 8) Get the AI to set up some basic UI to manage it.
|
|
96
|
+
// - For now, we'll run the phases one after the other. Controlled by the caller. Caching is going to come much later.
|
|
97
|
+
// - The first phase I think we can run when we receive the logs directly. This will make progress nice. And then the second phase will run automatically in the finish function. We'll have to add additional progress for that, which shouldn't be too difficult.
|
|
98
|
+
// - Having the finish function fork off into an async is probably fine, although we will have to expose the cancellation promise to the finish function?
|
|
99
|
+
// - Or do we even need cancellation? Are we ever going to even keep this code? So if we have a server precaching the values, we still need the pending values to be parsed somewhere. Hmm... That's annoying. Are we just not going to use fast archives for this?
|
|
100
|
+
// - MAYBE We can have the Fast Archives support external caching, so it'll give us the name of the file, and we'll tell it if it's cached or not. Actually, it can give us the name of all the files, and we'll tell it if we have a cached result for it. And if we do, we'll load the cache result, and it won't do any of the parsing of that file.
|
|
101
|
+
// 9) Stress test it, by automating something to load a page repeatedly (which should cause a lot of path logs). We should try at least 10K page refreshes, and nothing should break...
|
|
102
|
+
// - If my estimates are correct, and a page load of a large book results in ~5K logs, that will use ~2.5MB of uncompressed space, (~100KB compressed). Which... is acceptable. 10K page loads is 1GB, so a million would cost 1 USD/month to store. AND that's if we keep storing all audits in the logs, which we don't really have to do...
|
|
103
|
+
// - Processing it, on the other hand, will be kind of slow. Looks like we decompress about ten MB a second. But... there's not much we can do about that... unless... we searched on the compressed data directly? Hmm... or at least optimized based on it.
|
|
104
|
+
// 10) Add log file overview page, so we can keep an eye on the size of logs
|
|
105
|
+
// 10.1) Start storing the log count in the log file names
|
|
106
|
+
// - WHICH, requires breaking all of our old logs, but... that's not too big of deal
|
|
107
|
+
// - ONLY for the non-pending logs
|
|
108
|
+
// 11) Pull requests our lz4-wasm code. It's purely AI generated, but it might be of some interest.
|
|
109
|
+
// - As in, supporting streaming and decoding from a stream
|
|
110
|
+
// - REMEMBER to delete all of our test files and test code, and also really clean up the pull request before we make it.
|
|
111
|
+
/*
|
|
112
|
+
Two phases, and second phase has limitted, as some of our life cycles might explode quadratically.
|
|
113
|
+
*/
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
// logs => life cycle related => life cycle group by key => life cycle list, with each one being expandable
|
|
117
|
+
|
|
118
|
+
// Searching in previous state
|
|
119
|
+
// Using variables from logs?
|
|
120
|
+
// Using variables from lifecycle?
|
|
121
|
+
// The FORM we match will be pretty much always the same (not depending on variables). If we absolutely need to we can do some late filtering in the second phase, but I don't think we'll need to. However the life cycle it becomes a part of, that will depend on the state.
|
|
122
|
+
// OH! The start lifecycle entry will create a lifecycle, THEN we match. The later matches might not be as restrictive as the start life cycle. SOO...
|
|
123
|
+
// start = [path, clientId]
|
|
124
|
+
// watch = [path]
|
|
125
|
+
// AND SO, This is what we can do to kind of expand our paths. So really, it's more of a debug thing, where the start is something that provides a key for what we're debugging. And then after it, we'll have different lines which can match whichever data we want.
|
|
126
|
+
// - The only restriction is the other lines have to happen after the start and before the end.
|
|
127
|
+
// - The end will be the first end matched as well
|
|
128
|
+
// - AND Optionally, you can make it so that the start ends the previous one
|
|
129
|
+
// - And you can also just not provide an end. There's no reason the life cycle needs to end.
|
|
130
|
+
// - I think technically if you add a start and it keeps triggering and you don't tell it that it should end the previous one, then there'll be a lot of overlapping and some of the life cycles will get quite large. But we can handle that by throttling and lazy evaluation, so it shouldn't actually be an issue.
|
|
131
|
+
// todonext;
|
|
132
|
+
// // Okay, so it's looking like the first thing we're going to do is match the start, and then once we find the start, if we want to expand that life cycle, then we do a second phase search.
|
|
133
|
+
// todonext;
|
|
134
|
+
// // HMM... So actually what kind of variables do we need? I guess if we want to map between IDs. But then can't we just Match some line That gives us the mapping. And then, presumably, that'll be early on in the life cycle....
|
|
135
|
+
// todonext;
|
|
136
|
+
// // OH! Okay, so we want to allow some logs in the life cycle to match before the start? But that's all. They just match before the start. And I think we have to define how long they can match before the start. Obviously, we can't search forever. And then they're just normal lines after that. They can set life cycle variables, and we can access life cycle variables.
|
|
137
|
+
// todonext;
|
|
138
|
+
// // Yes, so... The variables are going to be a lot simple. It's just the lifecycle will have variables associated with it, which lines in the life cycle can set.
|
|
139
|
+
// todonext;
|
|
140
|
+
// // Let's not have any regex parsing either. Lifecycles entries can just say, I care about these variables and we expect them to be a part of the log object, and then we add them to the lifecycle.
|
|
141
|
+
// // - Which is really more for UI organization, as we can say these are important. And prevents the bug of some random log having to have happen to having a thread ID, but we have a thread ID and we mean the client thread ID, etc., etc. We just make it explicit per line, and then we don't run into that bug ever.
|
|
142
|
+
|
|
143
|
+
// TODO: Eventually, if we need it, we can have entries find other life cycles, either matching many, the latest, etc, and take variables from them PURELY FOR DISPLAY PURPOSES. But right at this moment, that's not needed.
|
|
144
|
+
|
|
145
|
+
type LifeCycle = {
|
|
146
|
+
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
type LifeCycleEntry = {
|
|
150
|
+
|
|
151
|
+
};
|
|
File without changes
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
(module
|
|
2
|
+
;; Import memory from JavaScript (with memory64 support for >4GB).
|
|
3
|
+
;; Callers use allocateBuffer(exports, size) from supportWat.ts to
|
|
4
|
+
;; request scratch regions; memory will be grown automatically as needed.
|
|
5
|
+
(import "env" "memory" (memory i64 1))
|
|
6
|
+
|
|
7
|
+
;; Export the heap base so the allocator knows where static data ends.
|
|
8
|
+
;; With no static data section here, the heap starts at byte 0.
|
|
9
|
+
(global (export "__heap_base") i32 (i32.const 0))
|
|
10
|
+
|
|
11
|
+
;; Add function: adds two i32 integers
|
|
12
|
+
(func $add (param $a i32) (param $b i32) (result i32)
|
|
13
|
+
local.get $a
|
|
14
|
+
local.get $b
|
|
15
|
+
i32.add
|
|
16
|
+
)
|
|
17
|
+
(export "add" (func $add))
|
|
18
|
+
|
|
19
|
+
;; Multiply function: multiplies two i32 integers
|
|
20
|
+
(func $multiply (param $a i32) (param $b i32) (result i32)
|
|
21
|
+
local.get $a
|
|
22
|
+
local.get $b
|
|
23
|
+
i32.mul
|
|
24
|
+
)
|
|
25
|
+
(export "multiply" (func $multiply))
|
|
26
|
+
|
|
27
|
+
;; stddev(offset: i32, count: i32) -> f64
|
|
28
|
+
;;
|
|
29
|
+
;; Computes the population standard deviation of `count` f64 values
|
|
30
|
+
;; stored contiguously in memory starting at byte `offset`.
|
|
31
|
+
;; Each value occupies 8 bytes (little-endian IEEE 754 double).
|
|
32
|
+
;; Returns 0.0 when count == 0.
|
|
33
|
+
(func $stddev (param $offset i32) (param $count i32) (result f64)
|
|
34
|
+
(local $i i32)
|
|
35
|
+
(local $sum f64)
|
|
36
|
+
(local $mean f64)
|
|
37
|
+
(local $diff f64)
|
|
38
|
+
(local $variance_sum f64)
|
|
39
|
+
|
|
40
|
+
;; Guard: return 0 if count == 0
|
|
41
|
+
(if (i32.eqz (local.get $count))
|
|
42
|
+
(then (return (f64.const 0)))
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
;; Pass 1: compute sum
|
|
46
|
+
(local.set $i (i32.const 0))
|
|
47
|
+
(local.set $sum (f64.const 0))
|
|
48
|
+
(block $break1
|
|
49
|
+
(loop $loop1
|
|
50
|
+
(br_if $break1 (i32.ge_u (local.get $i) (local.get $count)))
|
|
51
|
+
(local.set $sum
|
|
52
|
+
(f64.add
|
|
53
|
+
(local.get $sum)
|
|
54
|
+
(f64.load
|
|
55
|
+
(i32.add
|
|
56
|
+
(local.get $offset)
|
|
57
|
+
(i32.mul (local.get $i) (i32.const 8))
|
|
58
|
+
)
|
|
59
|
+
)
|
|
60
|
+
)
|
|
61
|
+
)
|
|
62
|
+
(local.set $i (i32.add (local.get $i) (i32.const 1)))
|
|
63
|
+
(br $loop1)
|
|
64
|
+
)
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
;; mean = sum / count
|
|
68
|
+
(local.set $mean
|
|
69
|
+
(f64.div (local.get $sum) (f64.convert_i32_u (local.get $count)))
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
;; Pass 2: compute sum of squared deviations
|
|
73
|
+
(local.set $i (i32.const 0))
|
|
74
|
+
(local.set $variance_sum (f64.const 0))
|
|
75
|
+
(block $break2
|
|
76
|
+
(loop $loop2
|
|
77
|
+
(br_if $break2 (i32.ge_u (local.get $i) (local.get $count)))
|
|
78
|
+
(local.set $diff
|
|
79
|
+
(f64.sub
|
|
80
|
+
(f64.load
|
|
81
|
+
(i32.add
|
|
82
|
+
(local.get $offset)
|
|
83
|
+
(i32.mul (local.get $i) (i32.const 8))
|
|
84
|
+
)
|
|
85
|
+
)
|
|
86
|
+
(local.get $mean)
|
|
87
|
+
)
|
|
88
|
+
)
|
|
89
|
+
(local.set $variance_sum
|
|
90
|
+
(f64.add
|
|
91
|
+
(local.get $variance_sum)
|
|
92
|
+
(f64.mul (local.get $diff) (local.get $diff))
|
|
93
|
+
)
|
|
94
|
+
)
|
|
95
|
+
(local.set $i (i32.add (local.get $i) (i32.const 1)))
|
|
96
|
+
(br $loop2)
|
|
97
|
+
)
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
;; return sqrt(variance_sum / count)
|
|
101
|
+
(f64.sqrt
|
|
102
|
+
(f64.div (local.get $variance_sum) (f64.convert_i32_u (local.get $count)))
|
|
103
|
+
)
|
|
104
|
+
)
|
|
105
|
+
(export "stddev" (func $stddev))
|
|
106
|
+
)
|
|
@@ -2,7 +2,7 @@ import { ScanFnc } from "./FastArchiveViewer";
|
|
|
2
2
|
|
|
3
3
|
export function createLogViewerExtractField(
|
|
4
4
|
fieldName: string,
|
|
5
|
-
onFieldValue: (value: string) => void,
|
|
5
|
+
onFieldValue: (value: string, unpackedSize: number) => void,
|
|
6
6
|
): ScanFnc {
|
|
7
7
|
let fieldNameBuffer = Buffer.from(`${JSON.stringify(fieldName)}:"`);
|
|
8
8
|
let quoteChar = Buffer.from(`"`)[0];
|
|
@@ -19,7 +19,7 @@ export function createLogViewerExtractField(
|
|
|
19
19
|
let start = i + j + 1;
|
|
20
20
|
for (let k = start; k < posEnd; k++) {
|
|
21
21
|
if (data[k] === quoteChar) {
|
|
22
|
-
onFieldValue(data.slice(start, k).toString());
|
|
22
|
+
onFieldValue(data.slice(start, k).toString(), posEnd - start);
|
|
23
23
|
break;
|
|
24
24
|
}
|
|
25
25
|
if (data[k] === escapeChar) {
|
|
@@ -31,7 +31,6 @@ export function createLogViewerExtractField(
|
|
|
31
31
|
}
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
|
-
onFieldValue("");
|
|
35
34
|
return false;
|
|
36
35
|
};
|
|
37
36
|
}
|
|
@@ -91,6 +91,16 @@ export async function registerManagementPages2(config: {
|
|
|
91
91
|
componentName: "LogViewer2",
|
|
92
92
|
getModule: () => import("./logs/LogViewer2"),
|
|
93
93
|
});
|
|
94
|
+
inputPages.push({
|
|
95
|
+
title: "Logs3",
|
|
96
|
+
componentName: "LogViewer3",
|
|
97
|
+
getModule: () => import("./logs/IndexedLogs/LogViewer3"),
|
|
98
|
+
});
|
|
99
|
+
inputPages.push({
|
|
100
|
+
title: "Life Cycles",
|
|
101
|
+
componentName: "LifeCyclePages",
|
|
102
|
+
getModule: () => import("./logs/lifeCycleAnalysis/LifeCyclePages"),
|
|
103
|
+
});
|
|
94
104
|
inputPages.push({
|
|
95
105
|
title: "Error Digests",
|
|
96
106
|
componentName: "ErrorDigestPage",
|
|
@@ -86,7 +86,7 @@ function logResourcesNow() {
|
|
|
86
86
|
}
|
|
87
87
|
|
|
88
88
|
registerMeasureInfo(() => {
|
|
89
|
-
return
|
|
89
|
+
return `MEM ${formatNumber(getUsedHeapSize())}B+${formatNumber(getBufferUsage())}B/${formatNumber(getHeapSize())}B `;
|
|
90
90
|
});
|
|
91
91
|
|
|
92
92
|
registerPeriodic(logResourcesNow);
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { measureFnc } from "socket-function/src/profiling/measure";
|
|
2
|
+
import { MaybePromise } from "socket-function/src/types";
|
|
3
|
+
|
|
4
|
+
export class LimitGroup {
|
|
5
|
+
/** We have processing sections. In each section, if we exceed the current maximum wait, then any new processing will be told that it needs to wait. And then at the end of the section we wait wait time. This can be zero, which is fine, and we'll should wait enough time for networking, etc to run. */
|
|
6
|
+
constructor(public config: {
|
|
7
|
+
maxTimePerBeforeWait: number;
|
|
8
|
+
waitTime: number;
|
|
9
|
+
}) { }
|
|
10
|
+
|
|
11
|
+
private sectionStartTime: number | undefined = undefined;
|
|
12
|
+
private afterSectionResolvers: (() => void)[] = [];
|
|
13
|
+
|
|
14
|
+
@measureFnc
|
|
15
|
+
public wait(): MaybePromise<void> {
|
|
16
|
+
if (this.sectionStartTime === undefined) {
|
|
17
|
+
this.sectionStartTime = Date.now();
|
|
18
|
+
setTimeout(async () => {
|
|
19
|
+
await new Promise(resolve => setTimeout(resolve, this.config.waitTime));
|
|
20
|
+
|
|
21
|
+
this.sectionStartTime = undefined;
|
|
22
|
+
const resolvers = this.afterSectionResolvers;
|
|
23
|
+
this.afterSectionResolvers = [];
|
|
24
|
+
for (const resolve of resolvers) {
|
|
25
|
+
resolve();
|
|
26
|
+
}
|
|
27
|
+
}, 0);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const elapsed = Date.now() - this.sectionStartTime;
|
|
31
|
+
if (elapsed >= this.config.maxTimePerBeforeWait) {
|
|
32
|
+
return new Promise<void>((resolve) => {
|
|
33
|
+
this.afterSectionResolvers.push(resolve);
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return undefined;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/* tslint:disable */
|
|
2
|
+
/* eslint-disable */
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Streaming LZ4 compressor (frame format with linked blocks).
|
|
6
|
+
* Concatenate all output chunks to form a complete LZ4 frame.
|
|
7
|
+
*/
|
|
8
|
+
export class Lz4StreamCompressor {
|
|
9
|
+
free(): void;
|
|
10
|
+
[Symbol.dispose](): void;
|
|
11
|
+
compress(input: Uint8Array): Uint8Array;
|
|
12
|
+
constructor();
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* One-shot block compression with size prepended.
|
|
17
|
+
*/
|
|
18
|
+
export function compress(input: Uint8Array): Uint8Array;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* One-shot block decompression with size prepended.
|
|
22
|
+
*/
|
|
23
|
+
export function decompress(input: Uint8Array): Uint8Array;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Decompress an LZ4 stream (frame format).
|
|
27
|
+
* Auto-injects end marker if missing. On error, returns partial data and sets a warning.
|
|
28
|
+
*/
|
|
29
|
+
export function decompress_stream(input: Uint8Array): Uint8Array;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Get and clear the last warning from decompression.
|
|
33
|
+
*/
|
|
34
|
+
export function get_last_warning(): string | undefined;
|