querysub 0.374.0 → 0.376.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 -4
- package/src/deployManager/components/MachineDetailPage.tsx +2 -5
- package/src/deployManager/components/ServiceDetailPage.tsx +2 -5
- package/src/deployManager/machineApplyMainCode.ts +7 -0
- package/src/diagnostics/NodeViewer.tsx +4 -5
- package/src/diagnostics/logs/IndexedLogs/BufferIndex.ts +10 -5
- package/src/diagnostics/logs/IndexedLogs/BufferIndexCPP.cpp +20 -0
- package/src/diagnostics/logs/IndexedLogs/BufferIndexHelpers.ts +29 -2
- package/src/diagnostics/logs/IndexedLogs/BufferUnitIndex.ts +61 -20
- package/src/diagnostics/logs/IndexedLogs/BufferUnitSet.ts +2 -2
- package/src/diagnostics/logs/IndexedLogs/IndexedLogs.ts +7 -7
- package/src/diagnostics/logs/IndexedLogs/LogViewer3.tsx +250 -243
- package/src/diagnostics/logs/IndexedLogs/LogViewerParams.ts +21 -0
- package/src/diagnostics/logs/IndexedLogs/{bufferMatcher.ts → bufferSearchFindMatcher.ts} +9 -4
- package/src/diagnostics/logs/IndexedLogs/moveIndexLogsToPublic.ts +3 -3
- package/src/diagnostics/logs/diskLogger.ts +0 -38
- package/src/diagnostics/logs/errorNotifications2/errorNotifications2.ts +9 -0
- package/src/diagnostics/logs/injectFileLocationToConsole.ts +3 -0
- package/src/diagnostics/logs/lifeCycleAnalysis/lifeCycles.tsx +24 -22
- package/src/diagnostics/managementPages.tsx +0 -18
- package/test.ts +0 -5
- package/bin/error-email.js +0 -8
- package/bin/error-im.js +0 -8
- package/src/diagnostics/logs/FastArchiveAppendable.ts +0 -843
- package/src/diagnostics/logs/FastArchiveController.ts +0 -573
- package/src/diagnostics/logs/FastArchiveViewer.tsx +0 -1090
- package/src/diagnostics/logs/LogViewer2.tsx +0 -552
- package/src/diagnostics/logs/errorNotifications/ErrorDigestPage.tsx +0 -409
- package/src/diagnostics/logs/errorNotifications/ErrorNotificationController.ts +0 -756
- package/src/diagnostics/logs/errorNotifications/ErrorSuppressionUI.tsx +0 -280
- package/src/diagnostics/logs/errorNotifications/ErrorWarning.tsx +0 -254
- package/src/diagnostics/logs/errorNotifications/errorDigestEmail.tsx +0 -233
- package/src/diagnostics/logs/errorNotifications/errorDigestEntry.tsx +0 -14
- package/src/diagnostics/logs/errorNotifications/errorDigests.tsx +0 -292
- package/src/diagnostics/logs/errorNotifications/errorWatchEntry.tsx +0 -209
- package/src/diagnostics/logs/importLogsEntry.ts +0 -38
- package/src/diagnostics/logs/lifeCycleAnalysis/LifeCyclePages.tsx +0 -150
- package/src/diagnostics/logs/logViewerExtractField.ts +0 -36
|
@@ -1,409 +0,0 @@
|
|
|
1
|
-
module.noserverhotreload = false;
|
|
2
|
-
module.hotreload = true;
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
import { SocketFunction } from "socket-function/SocketFunction";
|
|
6
|
-
import { qreact } from "../../../4-dom/qreact";
|
|
7
|
-
import { getSyncedController } from "../../../library-components/SyncedController";
|
|
8
|
-
import { ErrorDigestController, errorDigestHistory, ErrorDigestInfo } from "./errorDigests";
|
|
9
|
-
import { isManagementUser } from "../../../-0-hooks/hooks";
|
|
10
|
-
import { assertIsManagementUser } from "../../managementPages";
|
|
11
|
-
import { URLParam } from "../../../library-components/URLParam";
|
|
12
|
-
import { tabURL } from "../../../library-components/urlResetGroups";
|
|
13
|
-
import { Anchor, ATag } from "../../../library-components/ATag";
|
|
14
|
-
import { css } from "../../../4-dom/css";
|
|
15
|
-
import { list, sort } from "socket-function/src/misc";
|
|
16
|
-
import { formatDateTime, formatVeryNiceDateTime, formatNumber } from "socket-function/src/formatting/format";
|
|
17
|
-
import { Table } from "../../../5-diagnostics/Table";
|
|
18
|
-
import { Histogram } from "../../../library-components/Histogram";
|
|
19
|
-
import { TabbedUI } from "../../../library-components/TabbedUI";
|
|
20
|
-
import { LogDatum } from "../diskLogger";
|
|
21
|
-
import { t } from "../../../2-proxy/schema2";
|
|
22
|
-
import { getErrorLogsLink } from "./ErrorWarning";
|
|
23
|
-
|
|
24
|
-
export const digestKeyURL = new URLParam("digestKey", "");
|
|
25
|
-
export const fileDetailTabURL = new URLParam("fileDetailTab", "errors");
|
|
26
|
-
|
|
27
|
-
export class ErrorDigestPage extends qreact.Component {
|
|
28
|
-
state = t.state({
|
|
29
|
-
selectedFile: t.string("")
|
|
30
|
-
});
|
|
31
|
-
render() {
|
|
32
|
-
// Get the current tab mode
|
|
33
|
-
let currentTab = tabURL.value;
|
|
34
|
-
let selectedDigestKey = digestKeyURL.value;
|
|
35
|
-
|
|
36
|
-
if (currentTab === "detail" && selectedDigestKey) {
|
|
37
|
-
return this.renderDigestDetail(selectedDigestKey);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
return this.renderDigestList();
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
renderDigestList() {
|
|
44
|
-
let controller = ErrorDigestController(SocketFunction.browserNodeId());
|
|
45
|
-
|
|
46
|
-
let keys = controller.getDigestKeys();
|
|
47
|
-
|
|
48
|
-
if (!keys || keys.length === 0) {
|
|
49
|
-
return (
|
|
50
|
-
<div className={css.vbox(16).pad2(24)}>
|
|
51
|
-
<div className={css.fontSize(24).fontWeight(600)}>
|
|
52
|
-
Error Digest History
|
|
53
|
-
</div>
|
|
54
|
-
<div>No digest data available</div>
|
|
55
|
-
</div>
|
|
56
|
-
);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
// Sort lexicographically (highest = newest) and take latest 100
|
|
60
|
-
let sortedKeys = sort(keys as string[], key => key).reverse().slice(0, 100);
|
|
61
|
-
|
|
62
|
-
return (
|
|
63
|
-
<div className={css.vbox(16).paddingTop(24).paddingLeft(24).fillHeight.fillWidth}>
|
|
64
|
-
<div className={css.fontSize(24).fontWeight(600)}>
|
|
65
|
-
Error Digest History
|
|
66
|
-
</div>
|
|
67
|
-
<div className={css.fontSize(14).color("gray")}>
|
|
68
|
-
Showing latest {Math.min(sortedKeys.length, 100)} digests (sorted by creation time, newest first)
|
|
69
|
-
</div>
|
|
70
|
-
|
|
71
|
-
<div className={css.vbox(8).overflowAuto.fillWidth}>
|
|
72
|
-
{sortedKeys.map(key => (
|
|
73
|
-
<ATag
|
|
74
|
-
key={key}
|
|
75
|
-
values={[
|
|
76
|
-
tabURL.getOverride("detail"),
|
|
77
|
-
digestKeyURL.getOverride(key)
|
|
78
|
-
]}
|
|
79
|
-
className={css.pad2(12).hsla(0, 0, 0, 0.1).pointer.hslahover(0, 0, 0, 0.15)}
|
|
80
|
-
>
|
|
81
|
-
{formatVeryNiceDateTime(+key.split(".")[0])}
|
|
82
|
-
</ATag>
|
|
83
|
-
))}
|
|
84
|
-
</div>
|
|
85
|
-
</div>
|
|
86
|
-
);
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
renderDigestDetail(digestKey: string) {
|
|
90
|
-
let controller = ErrorDigestController(SocketFunction.browserNodeId());
|
|
91
|
-
|
|
92
|
-
let digestData = controller.getDigest(digestKey);
|
|
93
|
-
|
|
94
|
-
if (!digestData) {
|
|
95
|
-
return (
|
|
96
|
-
<div className={css.vbox(16).pad2(24)}>
|
|
97
|
-
<div className={css.hbox(16)}>
|
|
98
|
-
<ATag
|
|
99
|
-
values={[
|
|
100
|
-
tabURL.getOverride(""),
|
|
101
|
-
digestKeyURL.getOverride("")
|
|
102
|
-
]}
|
|
103
|
-
>
|
|
104
|
-
← Back to Digest List
|
|
105
|
-
</ATag>
|
|
106
|
-
</div>
|
|
107
|
-
<div>Loading digest data...</div>
|
|
108
|
-
</div>
|
|
109
|
-
);
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
// If a file is selected, show file details
|
|
113
|
-
if (this.state.selectedFile) {
|
|
114
|
-
return this.renderFileDetail(digestData, digestKey);
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
return (
|
|
118
|
-
<div className={css.vbox(24).pad2(24).fillHeight.overflowAuto}>
|
|
119
|
-
{/* Header */}
|
|
120
|
-
<div className={css.hbox(16).alignItems("center")}>
|
|
121
|
-
<ATag
|
|
122
|
-
values={[
|
|
123
|
-
tabURL.getOverride(""),
|
|
124
|
-
digestKeyURL.getOverride("")
|
|
125
|
-
]}
|
|
126
|
-
>
|
|
127
|
-
← Back to Digest List
|
|
128
|
-
</ATag>
|
|
129
|
-
<div className={css.fontSize(24).fontWeight(600)}>
|
|
130
|
-
Digest: {formatVeryNiceDateTime(+digestKey.split(".")[0])}
|
|
131
|
-
</div>
|
|
132
|
-
</div>
|
|
133
|
-
|
|
134
|
-
<Anchor
|
|
135
|
-
className={css.fontSize(24)}
|
|
136
|
-
values={getErrorLogsLink({
|
|
137
|
-
startTime: digestData.startTime,
|
|
138
|
-
endTime: digestData.endTime,
|
|
139
|
-
})}
|
|
140
|
-
>
|
|
141
|
-
View live logs
|
|
142
|
-
</Anchor>
|
|
143
|
-
|
|
144
|
-
{/* Metadata Section */}
|
|
145
|
-
{this.renderMetadata(digestData)}
|
|
146
|
-
|
|
147
|
-
{/* Charts Section */}
|
|
148
|
-
{this.renderCharts(digestData)}
|
|
149
|
-
|
|
150
|
-
{/* Files Table */}
|
|
151
|
-
{this.renderFilesTable(digestData)}
|
|
152
|
-
</div>
|
|
153
|
-
);
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
renderMetadata(digestData: ErrorDigestInfo) {
|
|
157
|
-
return (
|
|
158
|
-
<div className={css.vbox(16)}>
|
|
159
|
-
<div className={css.fontSize(20).fontWeight(600)}>Metadata</div>
|
|
160
|
-
<div className={css.hbox(32).wrap}>
|
|
161
|
-
<div className={css.vbox(4)}>
|
|
162
|
-
<div className={css.fontSize(14).colorhsl(0, 0, 60)}>Compressed Bytes</div>
|
|
163
|
-
<div className={css.fontSize(16).fontWeight(500)}>
|
|
164
|
-
{formatNumber(digestData.totalCompressedBytes)}
|
|
165
|
-
</div>
|
|
166
|
-
</div>
|
|
167
|
-
<div className={css.vbox(4)}>
|
|
168
|
-
<div className={css.fontSize(14).colorhsl(0, 0, 60)}>Uncompressed Bytes</div>
|
|
169
|
-
<div className={css.fontSize(16).fontWeight(500)}>
|
|
170
|
-
{formatNumber(digestData.totalUncompressedBytes)}
|
|
171
|
-
</div>
|
|
172
|
-
</div>
|
|
173
|
-
<div className={css.vbox(4)}>
|
|
174
|
-
<div className={css.fontSize(14).colorhsl(0, 0, 60)}>Total Files</div>
|
|
175
|
-
<div className={css.fontSize(16).fontWeight(500)}>
|
|
176
|
-
{formatNumber(digestData.totalFiles)}
|
|
177
|
-
</div>
|
|
178
|
-
</div>
|
|
179
|
-
<div className={css.vbox(4)}>
|
|
180
|
-
<div className={css.fontSize(14).colorhsl(0, 0, 60)}>Scan Duration</div>
|
|
181
|
-
<div className={css.fontSize(16).fontWeight(500)}>
|
|
182
|
-
{formatNumber(digestData.scanDuration)}ms
|
|
183
|
-
</div>
|
|
184
|
-
</div>
|
|
185
|
-
<div className={css.vbox(4)}>
|
|
186
|
-
<div className={css.fontSize(14).colorhsl(0, 0, 60)}>Start Time</div>
|
|
187
|
-
<div className={css.fontSize(16).fontWeight(500)}>
|
|
188
|
-
{formatVeryNiceDateTime(digestData.startTime)}
|
|
189
|
-
</div>
|
|
190
|
-
</div>
|
|
191
|
-
<div className={css.vbox(4)}>
|
|
192
|
-
<div className={css.fontSize(14).colorhsl(0, 0, 60)}>End Time</div>
|
|
193
|
-
<div className={css.fontSize(16).fontWeight(500)}>
|
|
194
|
-
{formatVeryNiceDateTime(digestData.endTime)}
|
|
195
|
-
</div>
|
|
196
|
-
</div>
|
|
197
|
-
</div>
|
|
198
|
-
</div>
|
|
199
|
-
);
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
renderCharts(digestData: ErrorDigestInfo) {
|
|
203
|
-
// Convert histogram data to chart data
|
|
204
|
-
let unsuppressedErrorsData: { x: number; y: number }[] = [];
|
|
205
|
-
let unsuppressedWarningsData: { x: number; y: number }[] = [];
|
|
206
|
-
let corruptData: { x: number; y: number }[] = [];
|
|
207
|
-
let suppressedData: { x: number; y: number }[] = [];
|
|
208
|
-
|
|
209
|
-
for (let [time, data] of digestData.histogram.entries()) {
|
|
210
|
-
unsuppressedErrorsData.push({ x: time, y: data.unsuppressedErrors });
|
|
211
|
-
unsuppressedWarningsData.push({ x: time, y: data.unsuppressedWarnings });
|
|
212
|
-
corruptData.push({ x: time, y: data.corruptErrors + data.corruptWarnings });
|
|
213
|
-
suppressedData.push({ x: time, y: data.suppressedErrors + data.suppressedWarnings });
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
return (
|
|
217
|
-
<div className={css.vbox(16)}>
|
|
218
|
-
<div className={css.fontSize(20).fontWeight(600)}>Error Distribution Over Time</div>
|
|
219
|
-
<div className={css.vbox(16)}>
|
|
220
|
-
<div className={css.hbox(16).wrap}>
|
|
221
|
-
<div className={css.fillWidth.minWidth(400).height(300)}>
|
|
222
|
-
<Histogram
|
|
223
|
-
title="Unsuppressed Errors"
|
|
224
|
-
values={unsuppressedErrorsData}
|
|
225
|
-
xColumn={{
|
|
226
|
-
title: "Time",
|
|
227
|
-
format: (value) => formatDateTime(value)
|
|
228
|
-
}}
|
|
229
|
-
yColumn={{ title: "Count" }}
|
|
230
|
-
/>
|
|
231
|
-
</div>
|
|
232
|
-
<div className={css.fillWidth.minWidth(400).height(300)}>
|
|
233
|
-
<Histogram
|
|
234
|
-
title="Unsuppressed Warnings"
|
|
235
|
-
values={unsuppressedWarningsData}
|
|
236
|
-
xColumn={{
|
|
237
|
-
title: "Time",
|
|
238
|
-
format: (value) => formatDateTime(value)
|
|
239
|
-
}}
|
|
240
|
-
yColumn={{ title: "Count" }}
|
|
241
|
-
/>
|
|
242
|
-
</div>
|
|
243
|
-
</div>
|
|
244
|
-
<div className={css.hbox(16).wrap}>
|
|
245
|
-
<div className={css.fillWidth.minWidth(400).height(300)}>
|
|
246
|
-
<Histogram
|
|
247
|
-
title="Corrupt Errors + Warnings"
|
|
248
|
-
values={corruptData}
|
|
249
|
-
xColumn={{
|
|
250
|
-
title: "Time",
|
|
251
|
-
format: (value) => formatDateTime(value)
|
|
252
|
-
}}
|
|
253
|
-
yColumn={{ title: "Count" }}
|
|
254
|
-
/>
|
|
255
|
-
</div>
|
|
256
|
-
<div className={css.fillWidth.minWidth(400).height(300)}>
|
|
257
|
-
<Histogram
|
|
258
|
-
title="Suppressed Errors + Warnings"
|
|
259
|
-
values={suppressedData}
|
|
260
|
-
xColumn={{
|
|
261
|
-
title: "Time",
|
|
262
|
-
format: (value) => formatDateTime(value)
|
|
263
|
-
}}
|
|
264
|
-
yColumn={{ title: "Count" }}
|
|
265
|
-
/>
|
|
266
|
-
</div>
|
|
267
|
-
</div>
|
|
268
|
-
</div>
|
|
269
|
-
</div>
|
|
270
|
-
);
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
renderFilesTable(digestData: ErrorDigestInfo) {
|
|
274
|
-
// Convert byFile map to table rows
|
|
275
|
-
let fileRows = Array.from(digestData.byFile.entries()).map(([fileName, fileData]) => {
|
|
276
|
-
let latestError = fileData.latestErrors[fileData.latestErrors.length - 1];
|
|
277
|
-
let latestWarning = fileData.latestWarnings[fileData.latestWarnings.length - 1];
|
|
278
|
-
let latestLog = latestError ?? latestWarning;
|
|
279
|
-
|
|
280
|
-
return {
|
|
281
|
-
fileName,
|
|
282
|
-
errorCount: fileData.errors,
|
|
283
|
-
warningCount: fileData.warnings,
|
|
284
|
-
latestMessage: latestLog?.param0 ?? "No messages",
|
|
285
|
-
latestTime: latestLog?.time ?? 0
|
|
286
|
-
};
|
|
287
|
-
});
|
|
288
|
-
|
|
289
|
-
// Sort by error count descending
|
|
290
|
-
fileRows = sort(fileRows, row => row.errorCount).reverse();
|
|
291
|
-
|
|
292
|
-
return (
|
|
293
|
-
<div className={css.vbox(16)}>
|
|
294
|
-
<div className={css.fontSize(20).fontWeight(600)}>Files ({fileRows.length} files)</div>
|
|
295
|
-
<Table
|
|
296
|
-
columns={{
|
|
297
|
-
fileName: { title: "File Name" },
|
|
298
|
-
errorCount: { title: "Errors" },
|
|
299
|
-
warningCount: { title: "Warnings" },
|
|
300
|
-
latestMessage: {
|
|
301
|
-
title: "Latest Message",
|
|
302
|
-
formatter: (value: any) => String(value).slice(0, 100) + (String(value).length > 100 ? "..." : "")
|
|
303
|
-
}
|
|
304
|
-
}}
|
|
305
|
-
rows={fileRows}
|
|
306
|
-
getRowAttributes={(row: any) => ({
|
|
307
|
-
className: css.cursor("pointer").hslhover(210, 20, 95),
|
|
308
|
-
onClick: () => {
|
|
309
|
-
this.state.selectedFile = row.fileName;
|
|
310
|
-
}
|
|
311
|
-
})}
|
|
312
|
-
/>
|
|
313
|
-
</div>
|
|
314
|
-
);
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
renderFileDetail(digestData: ErrorDigestInfo, digestKey: string) {
|
|
318
|
-
let selectedFileName = this.state.selectedFile;
|
|
319
|
-
let fileData = digestData.byFile.get(selectedFileName);
|
|
320
|
-
|
|
321
|
-
if (!fileData) {
|
|
322
|
-
return (
|
|
323
|
-
<div className={css.vbox(16).pad2(24)}>
|
|
324
|
-
<div>File not found</div>
|
|
325
|
-
</div>
|
|
326
|
-
);
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
return (
|
|
330
|
-
<div className={css.vbox(24).pad2(24).fillHeight}>
|
|
331
|
-
{/* Header with back button */}
|
|
332
|
-
<div className={css.hbox(16).alignItems("center")}>
|
|
333
|
-
<ATag
|
|
334
|
-
clickOverride={() => {
|
|
335
|
-
this.state.selectedFile = "";
|
|
336
|
-
}}
|
|
337
|
-
className={css.cursor("pointer")}
|
|
338
|
-
>
|
|
339
|
-
← Back to Files Table
|
|
340
|
-
</ATag>
|
|
341
|
-
<div className={css.fontSize(20).fontWeight(600)}>
|
|
342
|
-
{selectedFileName}
|
|
343
|
-
</div>
|
|
344
|
-
</div>
|
|
345
|
-
|
|
346
|
-
{/* File stats */}
|
|
347
|
-
<div className={css.hbox(32)}>
|
|
348
|
-
<div className={css.vbox(4)}>
|
|
349
|
-
<div className={css.fontSize(14).colorhsl(0, 0, 60)}>Errors</div>
|
|
350
|
-
<div className={css.fontSize(16).fontWeight(500)}>{fileData.errors}</div>
|
|
351
|
-
</div>
|
|
352
|
-
<div className={css.vbox(4)}>
|
|
353
|
-
<div className={css.fontSize(14).colorhsl(0, 0, 60)}>Warnings</div>
|
|
354
|
-
<div className={css.fontSize(16).fontWeight(500)}>{fileData.warnings}</div>
|
|
355
|
-
</div>
|
|
356
|
-
</div>
|
|
357
|
-
|
|
358
|
-
{/* Tabbed interface for errors/warnings */}
|
|
359
|
-
<div className={css.fillHeight.overflowHidden}>
|
|
360
|
-
<TabbedUI
|
|
361
|
-
tab={fileDetailTabURL}
|
|
362
|
-
tabs={[
|
|
363
|
-
{
|
|
364
|
-
value: "errors",
|
|
365
|
-
title: `Errors (${fileData.errors})`,
|
|
366
|
-
contents: this.renderLogEntries(fileData.latestErrors, "errors")
|
|
367
|
-
},
|
|
368
|
-
{
|
|
369
|
-
value: "warnings",
|
|
370
|
-
title: `Warnings (${fileData.warnings})`,
|
|
371
|
-
contents: this.renderLogEntries(fileData.latestWarnings, "warnings")
|
|
372
|
-
}
|
|
373
|
-
]}
|
|
374
|
-
/>
|
|
375
|
-
</div>
|
|
376
|
-
</div>
|
|
377
|
-
);
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
renderLogEntries(logs: LogDatum[], type: "errors" | "warnings") {
|
|
381
|
-
if (logs.length === 0) {
|
|
382
|
-
return <div className={css.colorhsl(0, 0, 60)}>No {type} found</div>;
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
let tableRows = logs.map((log, index) => ({
|
|
386
|
-
index: logs.length - index,
|
|
387
|
-
time: formatVeryNiceDateTime(log.time),
|
|
388
|
-
message: log.param0 ?? "No message",
|
|
389
|
-
threadId: log.__threadId ?? "Unknown",
|
|
390
|
-
name: log.__NAME__ ?? "Unknown"
|
|
391
|
-
}));
|
|
392
|
-
|
|
393
|
-
return (
|
|
394
|
-
<div className={css.fillHeight.overflowAuto}>
|
|
395
|
-
<Table
|
|
396
|
-
columns={{
|
|
397
|
-
index: { title: "#" },
|
|
398
|
-
time: { title: "Time" },
|
|
399
|
-
name: { title: "Source" },
|
|
400
|
-
threadId: { title: "Thread" },
|
|
401
|
-
message: { title: "Message" }
|
|
402
|
-
}}
|
|
403
|
-
rows={tableRows}
|
|
404
|
-
initialLimit={50}
|
|
405
|
-
/>
|
|
406
|
-
</div>
|
|
407
|
-
);
|
|
408
|
-
}
|
|
409
|
-
}
|