@64mb/freelens-power 1.6.1 → 2.1.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/README.md +1 -1
- package/out/main/common/power-logs.js.map +1 -1
- package/out/main/common/resource-search-kind-priority.js +23 -0
- package/out/main/common/resource-search-kind-priority.js.map +1 -0
- package/out/main/common/store/logs-preferences-store.js +5 -0
- package/out/main/common/store/logs-preferences-store.js.map +1 -1
- package/out/main/dashboard-views.js +26 -0
- package/out/main/dashboard-views.js.map +1 -1
- package/out/main/power-logs-database.js +5 -0
- package/out/main/power-logs-database.js.map +1 -1
- package/out/main/power-logs-ipc.js +8 -0
- package/out/main/power-logs-ipc.js.map +1 -1
- package/out/main/power-logs-query.js +1 -0
- package/out/main/power-logs-query.js.map +1 -1
- package/out/main/resource-search-database.js +7 -2
- package/out/main/resource-search-database.js.map +1 -1
- package/out/main/resource-search-worker.js +6 -2
- package/out/main/resource-search-worker.js.map +1 -1
- package/out/renderer/_virtual/_global-external_react.js +2 -1
- package/out/renderer/ai-diagnostic-handoff.js +1 -0
- package/out/renderer/ai-diagnostic-handoff.js.map +1 -1
- package/out/renderer/ai-extras.js +7 -2
- package/out/renderer/ai-extras.js.map +1 -1
- package/out/renderer/ai.js +1 -1
- package/out/renderer/ai.js.map +1 -1
- package/out/renderer/appearance.js +2 -0
- package/out/renderer/appearance.js.map +1 -1
- package/out/renderer/dashboard.js +35 -8
- package/out/renderer/dashboard.js.map +1 -1
- package/out/renderer/index.js +2 -1
- package/out/renderer/index.js.map +1 -1
- package/out/renderer/power-log-json-cell.js +82 -0
- package/out/renderer/power-log-json-cell.js.map +1 -0
- package/out/renderer/power-log-json-fields.js +144 -0
- package/out/renderer/power-log-json-fields.js.map +1 -0
- package/out/renderer/power-log-json.js +223 -20
- package/out/renderer/power-log-json.js.map +1 -1
- package/out/renderer/power-log-message-tokens.js +60 -0
- package/out/renderer/power-log-message-tokens.js.map +1 -0
- package/out/renderer/power-log-message.js +26 -0
- package/out/renderer/power-log-message.js.map +1 -0
- package/out/renderer/power-log-sql-editor.js +91 -0
- package/out/renderer/power-log-sql-editor.js.map +1 -0
- package/out/renderer/power-logs-client.js +4 -0
- package/out/renderer/power-logs-client.js.map +1 -1
- package/out/renderer/power-logs-sql-drafts.js +76 -0
- package/out/renderer/power-logs-sql-drafts.js.map +1 -0
- package/out/renderer/power-logs-sql-row.js +5 -13
- package/out/renderer/power-logs-sql-row.js.map +1 -1
- package/out/renderer/power-logs.css.js +39 -6
- package/out/renderer/power-logs.css.js.map +1 -1
- package/out/renderer/power-logs.js +372 -135
- package/out/renderer/power-logs.js.map +1 -1
- package/out/renderer/preferences/logs-preferences.js +159 -38
- package/out/renderer/preferences/logs-preferences.js.map +1 -1
- package/out/renderer/preferences/preferences.js +2 -9
- package/out/renderer/preferences/preferences.js.map +1 -1
- package/out/renderer/preferences/section-navigation.js +44 -0
- package/out/renderer/preferences/section-navigation.js.map +1 -0
- package/out/renderer/resource-search-model.js +2 -1
- package/out/renderer/resource-search-model.js.map +1 -1
- package/out/renderer/resource-search-sync.js +1 -1
- package/out/renderer/resource-search-sync.js.map +1 -1
- package/out/renderer/resource-search.js +84 -81
- package/out/renderer/resource-search.js.map +1 -1
- package/out/renderer/src/common/power-log-field-filters.js +92 -0
- package/out/renderer/src/common/power-log-field-filters.js.map +1 -0
- package/out/renderer/src/common/power-log-json-filter-sql.js +106 -0
- package/out/renderer/src/common/power-log-json-filter-sql.js.map +1 -0
- package/out/renderer/src/common/power-log-json-preset.js +34 -0
- package/out/renderer/src/common/power-log-json-preset.js.map +1 -0
- package/out/renderer/src/common/power-log-level.js +171 -0
- package/out/renderer/src/common/power-log-level.js.map +1 -0
- package/out/renderer/src/common/power-log-parser.js +7 -29
- package/out/renderer/src/common/power-log-parser.js.map +1 -1
- package/out/renderer/src/common/power-log-sql-level.js +25 -0
- package/out/renderer/src/common/power-log-sql-level.js.map +1 -0
- package/out/renderer/src/common/power-logs-ai.js +4 -0
- package/out/renderer/src/common/power-logs-ai.js.map +1 -1
- package/out/renderer/src/common/power-logs.js.map +1 -1
- package/out/renderer/src/common/resource-search-kind-priority.js +28 -0
- package/out/renderer/src/common/resource-search-kind-priority.js.map +1 -0
- package/out/renderer/src/common/store/logs-preferences-store.js +5 -0
- package/out/renderer/src/common/store/logs-preferences-store.js.map +1 -1
- package/package.json +1 -1
|
@@ -8,12 +8,21 @@ const require_jsx_runtime = require("./_virtual/_global-external_react/jsx-runti
|
|
|
8
8
|
const require_ai_diagnostic_handoff = require("./ai-diagnostic-handoff.js");
|
|
9
9
|
const require_date_time = require("./src/common/date-time.js");
|
|
10
10
|
const require_diagnostic_explain_button = require("./diagnostic-explain-button.js");
|
|
11
|
+
const require_power_log_field_filters = require("./src/common/power-log-field-filters.js");
|
|
12
|
+
const require_power_log_json_filter_sql = require("./src/common/power-log-json-filter-sql.js");
|
|
13
|
+
const require_power_log_json_preset = require("./src/common/power-log-json-preset.js");
|
|
14
|
+
const require_power_log_sql_level = require("./src/common/power-log-sql-level.js");
|
|
11
15
|
const require_power_logs_ai = require("./src/common/power-logs-ai.js");
|
|
16
|
+
const require_power_log_json_fields = require("./power-log-json-fields.js");
|
|
12
17
|
const require_power_log_json = require("./power-log-json.js");
|
|
18
|
+
const require_power_log_message = require("./power-log-message.js");
|
|
19
|
+
const require_power_log_json_cell = require("./power-log-json-cell.js");
|
|
20
|
+
const require_power_log_sql_editor = require("./power-log-sql-editor.js");
|
|
13
21
|
const require_power_logs_css = require("./power-logs.css.js");
|
|
14
22
|
const require_power_logs_client = require("./power-logs-client.js");
|
|
15
23
|
const require_power_logs_collector = require("./power-logs-collector.js");
|
|
16
24
|
const require_power_logs_entrypoints = require("./power-logs-entrypoints.js");
|
|
25
|
+
const require_power_logs_sql_drafts = require("./power-logs-sql-drafts.js");
|
|
17
26
|
const require_power_logs_sql_row = require("./power-logs-sql-row.js");
|
|
18
27
|
const require_resource_search_client = require("./resource-search-client.js");
|
|
19
28
|
const require_power_logs_transport = require("./power-logs-transport.js");
|
|
@@ -38,8 +47,8 @@ var levels = [
|
|
|
38
47
|
var examples = [
|
|
39
48
|
["Recent", "SELECT message, level, container, pod, timestamp FROM logs ORDER BY timestamp DESC NULLS LAST LIMIT 200"],
|
|
40
49
|
["Errors", "SELECT pod, container, count(*) AS errors FROM logs WHERE level IN ('error','fatal') GROUP BY pod, container ORDER BY errors DESC"],
|
|
41
|
-
["Timeline", "SELECT strftime('%Y-%m-%d %H:%M', timestamp / 1000, 'unixepoch') AS minute, level, count(*) AS lines FROM logs GROUP BY minute, level ORDER BY minute"],
|
|
42
|
-
["JSON", "SELECT
|
|
50
|
+
["Timeline", "SELECT strftime('%Y-%m-%d %H:%M', timestamp / 1000, 'unixepoch') AS minute, UPPER(level) AS level, count(*) AS lines FROM logs GROUP BY minute, level ORDER BY minute"],
|
|
51
|
+
["JSON", "SELECT fieldsJson FROM logs WHERE fieldsJson IS NOT NULL LIMIT 100"]
|
|
43
52
|
];
|
|
44
53
|
var sqlColumnWidth = (column) => column === "message" || column === "fieldsJson" ? 360 : column === "level" ? 90 : 200;
|
|
45
54
|
function initialTarget() {
|
|
@@ -127,7 +136,10 @@ var SourcePicker = require__global_external_mobx_react.observer(() => {
|
|
|
127
136
|
return /* @__PURE__ */ require_jsx_runtime.jsxs("div", {
|
|
128
137
|
className: "power-logs-source",
|
|
129
138
|
children: [
|
|
130
|
-
/* @__PURE__ */ require_jsx_runtime.jsx("span", {
|
|
139
|
+
/* @__PURE__ */ require_jsx_runtime.jsx("span", {
|
|
140
|
+
className: "power-logs-control-label",
|
|
141
|
+
children: "Resource"
|
|
142
|
+
}),
|
|
131
143
|
/* @__PURE__ */ require_jsx_runtime.jsx(LogSelect, {
|
|
132
144
|
label: "Resource",
|
|
133
145
|
value,
|
|
@@ -176,6 +188,7 @@ function LogRows({ records, loading, selected, onSelect, follow, setFollow, comp
|
|
|
176
188
|
follow,
|
|
177
189
|
compact
|
|
178
190
|
]);
|
|
191
|
+
const levelCharacters = require__global_external_react.useMemo(() => records.reduce((width, record) => Math.max(width, record.level.length), 4), [records]);
|
|
179
192
|
const rowHeight = compact ? 20 : 34;
|
|
180
193
|
const start = Math.max(0, Math.floor(top / rowHeight) - 5);
|
|
181
194
|
const visible = records.slice(start, start + Math.ceil(height / rowHeight) + 10);
|
|
@@ -184,6 +197,7 @@ function LogRows({ records, loading, selected, onSelect, follow, setFollow, comp
|
|
|
184
197
|
children: /* @__PURE__ */ require_jsx_runtime.jsx("div", {
|
|
185
198
|
className: "power-logs-stream",
|
|
186
199
|
ref: viewport,
|
|
200
|
+
style: { "--power-log-level-ch": levelCharacters },
|
|
187
201
|
"aria-label": "Log lines",
|
|
188
202
|
"aria-busy": loading,
|
|
189
203
|
onScroll: (event) => {
|
|
@@ -220,30 +234,29 @@ function LogRows({ records, loading, selected, onSelect, follow, setFollow, comp
|
|
|
220
234
|
}),
|
|
221
235
|
/* @__PURE__ */ require_jsx_runtime.jsxs("span", {
|
|
222
236
|
className: "power-log-origin",
|
|
223
|
-
|
|
237
|
+
id: `power-log-source-${record.key}`,
|
|
224
238
|
children: [
|
|
225
|
-
record.
|
|
239
|
+
record.pod,
|
|
226
240
|
record.previous ? " (previous)" : "",
|
|
227
|
-
|
|
228
|
-
|
|
241
|
+
/* @__PURE__ */ require_jsx_runtime.jsx(require_extensions.Renderer.Component.Tooltip, {
|
|
242
|
+
targetId: `power-log-source-${record.key}`,
|
|
243
|
+
children: sourceKey(record)
|
|
244
|
+
})
|
|
229
245
|
]
|
|
230
246
|
}),
|
|
231
|
-
/* @__PURE__ */ require_jsx_runtime.jsx(
|
|
247
|
+
/* @__PURE__ */ require_jsx_runtime.jsx(require_power_log_message.LogMessage, { text: record.message })
|
|
232
248
|
]
|
|
233
249
|
}, record.key))
|
|
234
250
|
})
|
|
235
251
|
})
|
|
236
252
|
});
|
|
237
253
|
}
|
|
238
|
-
function LogDetails({ record, jsonColumn, onClose }) {
|
|
254
|
+
function LogDetails({ record, jsonColumn, onClose, onFilter }) {
|
|
239
255
|
const structuredFields = require__global_external_react.useMemo(() => {
|
|
240
256
|
if (!record?.fieldsJson) return "";
|
|
241
|
-
|
|
242
|
-
return JSON.stringify(JSON.parse(record.fieldsJson), null, 2);
|
|
243
|
-
} catch {
|
|
244
|
-
return record.fieldsJson;
|
|
245
|
-
}
|
|
257
|
+
return require_power_log_json_fields.formatJsonLiteral(record.fieldsJson);
|
|
246
258
|
}, [record?.fieldsJson]);
|
|
259
|
+
const fieldsEnabled = require__global_external_react.useMemo(() => !require_power_log_json_fields.jsonHasDuplicateKeys(record.fieldsJson ?? ""), [record.fieldsJson]);
|
|
247
260
|
const [copyFeedback, setCopyFeedback] = require__global_external_react.useState("");
|
|
248
261
|
require__global_external_react.useEffect(() => setCopyFeedback(""), [structuredFields]);
|
|
249
262
|
return /* @__PURE__ */ require_jsx_runtime.jsxs("aside", {
|
|
@@ -262,9 +275,9 @@ function LogDetails({ record, jsonColumn, onClose }) {
|
|
|
262
275
|
})] }),
|
|
263
276
|
/* @__PURE__ */ require_jsx_runtime.jsx("p", {
|
|
264
277
|
className: "power-logs-muted",
|
|
265
|
-
children: [record.pod && sourceKey(record), record.level].filter(Boolean).join(" · ")
|
|
278
|
+
children: [record.pod && sourceKey(record), record.level.toUpperCase()].filter(Boolean).join(" · ")
|
|
266
279
|
}),
|
|
267
|
-
record.message && /* @__PURE__ */ require_jsx_runtime.jsx("pre", { children: record.message }),
|
|
280
|
+
record.message && /* @__PURE__ */ require_jsx_runtime.jsx("pre", { children: /* @__PURE__ */ require_jsx_runtime.jsx(require_power_log_message.LogMessage, { text: record.message }) }),
|
|
268
281
|
record.fieldsJson && /* @__PURE__ */ require_jsx_runtime.jsxs(require_jsx_runtime.Fragment, { children: [/* @__PURE__ */ require_jsx_runtime.jsxs("div", {
|
|
269
282
|
className: "power-logs-structured-heading",
|
|
270
283
|
children: [
|
|
@@ -293,31 +306,72 @@ function LogDetails({ record, jsonColumn, onClose }) {
|
|
|
293
306
|
children: copyFeedback
|
|
294
307
|
})
|
|
295
308
|
]
|
|
296
|
-
}), /* @__PURE__ */ require_jsx_runtime.jsx(require_power_log_json.LogJson, {
|
|
309
|
+
}), /* @__PURE__ */ require_jsx_runtime.jsx(require_power_log_json.LogJson, {
|
|
310
|
+
text: structuredFields,
|
|
311
|
+
fieldsEnabled,
|
|
312
|
+
Icon,
|
|
313
|
+
onFilter
|
|
314
|
+
})] })
|
|
297
315
|
]
|
|
298
316
|
});
|
|
299
317
|
}
|
|
318
|
+
var sameFieldFilter = (a, b) => a.operator === b.operator && a.path.length === b.path.length && a.path.every((part, index) => part === b.path[index]) && require_power_log_field_filters.jsonValuesEqual(a.value, b.value);
|
|
319
|
+
var fieldFilterLabel = (filter) => `${filter.path.reduce((path, part) => `${path}[${typeof part === "number" ? part : JSON.stringify(part)}]`, "$")} ${filter.operator === "eq" ? "=" : "!="} ${JSON.stringify(filter.value)}`;
|
|
320
|
+
function FieldFilters({ filters, sql = false, disabled = false, onRemove }) {
|
|
321
|
+
if (!filters.length) return null;
|
|
322
|
+
return /* @__PURE__ */ require_jsx_runtime.jsxs("div", {
|
|
323
|
+
className: "power-logs-field-filters",
|
|
324
|
+
"aria-label": sql ? "SQL JSON filters" : "Live JSON filters",
|
|
325
|
+
children: [/* @__PURE__ */ require_jsx_runtime.jsxs("span", {
|
|
326
|
+
className: "power-logs-muted",
|
|
327
|
+
children: [sql ? "Result filters" : "JSON filters", " · AND"]
|
|
328
|
+
}), filters.map((filter, index) => {
|
|
329
|
+
const label = `${filter.column ? `${filter.column} ` : ""}${fieldFilterLabel(filter)}`;
|
|
330
|
+
return /* @__PURE__ */ require_jsx_runtime.jsxs("button", {
|
|
331
|
+
type: "button",
|
|
332
|
+
disabled,
|
|
333
|
+
title: label,
|
|
334
|
+
"aria-label": `Remove JSON filter ${label}`,
|
|
335
|
+
onClick: () => onRemove(index),
|
|
336
|
+
children: [/* @__PURE__ */ require_jsx_runtime.jsx("span", { children: label }), /* @__PURE__ */ require_jsx_runtime.jsx(Icon, {
|
|
337
|
+
material: "close",
|
|
338
|
+
size: 14
|
|
339
|
+
})]
|
|
340
|
+
}, index);
|
|
341
|
+
})]
|
|
342
|
+
});
|
|
343
|
+
}
|
|
300
344
|
function Workspace({ clusterId, contextId }) {
|
|
301
345
|
const client = require__global_external_react.useMemo(() => require_power_logs_client.createPowerLogsClient({
|
|
302
346
|
clusterId,
|
|
303
347
|
contextId
|
|
304
348
|
}), [clusterId, contextId]);
|
|
349
|
+
const drafts = require__global_external_react.useMemo(() => new require_power_logs_sql_drafts.CaptureSqlDrafts((id, query) => client.saveSql(id, query), () => setError("Could not save the SQL draft. Your edits remain available in this workspace.")), [client]);
|
|
350
|
+
require__global_external_react.useEffect(() => () => {
|
|
351
|
+
drafts.dispose();
|
|
352
|
+
}, [drafts]);
|
|
305
353
|
const [target, setTarget] = require__global_external_react.useState(initialTarget);
|
|
306
354
|
const [records, setRecords] = require__global_external_react.useState([]);
|
|
307
355
|
const [sources, setSources] = require__global_external_react.useState([]);
|
|
308
356
|
const [notes, setNotes] = require__global_external_react.useState([]);
|
|
309
357
|
const [status, setStatus] = require__global_external_react.useState("Choose a resource to read its logs");
|
|
310
358
|
const [error, setError] = require__global_external_react.useState("");
|
|
359
|
+
const [sqlError, setSqlError] = require__global_external_react.useState("");
|
|
311
360
|
const [tab, setTab] = require__global_external_react.useState("live");
|
|
312
361
|
const [text, setText] = require__global_external_react.useState("");
|
|
313
362
|
const [level, setLevel] = require__global_external_react.useState("");
|
|
314
363
|
const [source, setSource] = require__global_external_react.useState(initialSource);
|
|
364
|
+
const [fieldFilters, setFieldFilters] = require__global_external_react.useState([]);
|
|
365
|
+
const matchFields = require__global_external_react.useMemo(() => require_power_log_field_filters.compileJsonFilters(fieldFilters), [fieldFilters]);
|
|
366
|
+
const parsedFields = require__global_external_react.useRef(/* @__PURE__ */ new WeakMap());
|
|
367
|
+
const [sqlFieldFilters, setSqlFieldFilters] = require__global_external_react.useState();
|
|
315
368
|
const preferences = require_logs_preferences_store.LogsPreferencesStore.getInstanceOrCreate();
|
|
316
369
|
const limits = require_power_logs_limits.normalizePowerLogsLimits(preferences.limits);
|
|
317
370
|
require__global_external_react.useEffect(() => {
|
|
318
371
|
require_power_logs_limits.applyPowerLogsLimits(preferences.limits);
|
|
319
372
|
}, [preferences.limits]);
|
|
320
373
|
const [compact, setCompact] = require__global_external_react.useState(preferences.compactRows === true);
|
|
374
|
+
const [hideResourceName, setHideResourceName] = require__global_external_react.useState(preferences.hideResourceNameColumn === true);
|
|
321
375
|
const [selected, setSelected] = require__global_external_react.useState();
|
|
322
376
|
const [selectedSqlRow, setSelectedSqlRow] = require__global_external_react.useState();
|
|
323
377
|
const [liveCoverage, setLiveCoverage] = require__global_external_react.useState();
|
|
@@ -325,16 +379,35 @@ function Workspace({ clusterId, contextId }) {
|
|
|
325
379
|
const [follow, setFollow] = require__global_external_react.useState(true);
|
|
326
380
|
const [busy, setBusy] = require__global_external_react.useState(() => Boolean(initialTarget()));
|
|
327
381
|
const [captures, setCaptures] = require__global_external_react.useState([]);
|
|
328
|
-
const [captureId,
|
|
382
|
+
const [captureId, updateCaptureId] = require__global_external_react.useState("");
|
|
329
383
|
const captureSelection = require__global_external_react.useRef(captureId);
|
|
330
384
|
captureSelection.current = captureId;
|
|
385
|
+
const setCaptureId = (id, snapshot = captures.find((item) => item.id === id)) => {
|
|
386
|
+
if (id !== captureSelection.current) drafts.flush();
|
|
387
|
+
captureSelection.current = id;
|
|
388
|
+
const query = snapshot ? drafts.read(snapshot, examples[0][1]) : examples[0][1];
|
|
389
|
+
sqlDraft.current = query;
|
|
390
|
+
updateSql(query);
|
|
391
|
+
updateCaptureId(id);
|
|
392
|
+
};
|
|
331
393
|
const deleting = require__global_external_react.useRef(/* @__PURE__ */ new Set());
|
|
332
394
|
const [deletingCount, setDeletingCount] = require__global_external_react.useState(0);
|
|
333
395
|
const [capturing, setCapturing] = require__global_external_react.useState();
|
|
334
396
|
const [capturePending, setCapturePending] = require__global_external_react.useState(false);
|
|
335
397
|
const [captureMinutes, setCaptureMinutes] = require__global_external_react.useState(15);
|
|
336
398
|
const [previous, setPrevious] = require__global_external_react.useState(false);
|
|
337
|
-
const [sql,
|
|
399
|
+
const [sql, updateSql] = require__global_external_react.useState(examples[0][1]);
|
|
400
|
+
const sqlDraft = require__global_external_react.useRef(sql);
|
|
401
|
+
sqlDraft.current = sql;
|
|
402
|
+
const setSql = (query) => {
|
|
403
|
+
sqlDraft.current = query;
|
|
404
|
+
updateSql(query);
|
|
405
|
+
if (captureSelection.current) drafts.set(captureSelection.current, query);
|
|
406
|
+
};
|
|
407
|
+
const captureKeys = require__global_external_react.useRef(/* @__PURE__ */ new Map());
|
|
408
|
+
require__global_external_react.useEffect(() => {
|
|
409
|
+
setSqlFieldFilters((current) => current && (current.rendered !== sql || current.captureId !== captureId) ? void 0 : current);
|
|
410
|
+
}, [sql, captureId]);
|
|
338
411
|
const [result, setResult] = require__global_external_react.useState();
|
|
339
412
|
const [resultEvidence, setResultEvidence] = require__global_external_react.useState();
|
|
340
413
|
const [resultPage, setResultPage] = require__global_external_react.useState(0);
|
|
@@ -479,6 +552,7 @@ function Workspace({ clusterId, contextId }) {
|
|
|
479
552
|
};
|
|
480
553
|
require__global_external_react.useEffect(() => {
|
|
481
554
|
setText("");
|
|
555
|
+
setFieldFilters([]);
|
|
482
556
|
setSources([]);
|
|
483
557
|
setTab("live");
|
|
484
558
|
readHistory();
|
|
@@ -609,11 +683,11 @@ function Workspace({ clusterId, contextId }) {
|
|
|
609
683
|
if (current) try {
|
|
610
684
|
const saved = await client.finish(current.id, partial || controller.signal.aborted, [...new Set(captureNotes)].slice(0, 20));
|
|
611
685
|
if (alive.current) {
|
|
612
|
-
setCaptureId(saved.id);
|
|
686
|
+
setCaptureId(saved.id, saved);
|
|
613
687
|
setCaptures((items) => [saved, ...items.filter((item) => item.id !== saved.id)]);
|
|
614
688
|
setTab("captures");
|
|
615
689
|
setSql(examples[0][1]);
|
|
616
|
-
|
|
690
|
+
applyPreset("Recent", saved, true);
|
|
617
691
|
}
|
|
618
692
|
} catch {
|
|
619
693
|
if (alive.current) setError("The temporary capture could not be finalized");
|
|
@@ -637,6 +711,7 @@ function Workspace({ clusterId, contextId }) {
|
|
|
637
711
|
setError("");
|
|
638
712
|
setResult(void 0);
|
|
639
713
|
setSelectedSqlRow(void 0);
|
|
714
|
+
setSqlError("");
|
|
640
715
|
setResultEvidence({
|
|
641
716
|
capture: captured,
|
|
642
717
|
sql: query
|
|
@@ -644,10 +719,24 @@ function Workspace({ clusterId, contextId }) {
|
|
|
644
719
|
setResultPage(0);
|
|
645
720
|
try {
|
|
646
721
|
const value = await client.query(captured.id, id, query);
|
|
647
|
-
if (alive.current && queryRef.current === id) if (value.error)
|
|
648
|
-
|
|
722
|
+
if (alive.current && queryRef.current === id) if (value.error) {
|
|
723
|
+
setSqlError(value.error);
|
|
724
|
+
setResultEvidence({
|
|
725
|
+
capture: captured,
|
|
726
|
+
sql: query,
|
|
727
|
+
error: value.error
|
|
728
|
+
});
|
|
729
|
+
} else setResult(value);
|
|
649
730
|
} catch {
|
|
650
|
-
if (alive.current && queryRef.current === id)
|
|
731
|
+
if (alive.current && queryRef.current === id) {
|
|
732
|
+
const message = "Query stopped or failed. Use one read-only SELECT or EXPLAIN; external files, networking and extensions are disabled.";
|
|
733
|
+
setSqlError(message);
|
|
734
|
+
setResultEvidence({
|
|
735
|
+
capture: captured,
|
|
736
|
+
sql: query,
|
|
737
|
+
error: message
|
|
738
|
+
});
|
|
739
|
+
}
|
|
651
740
|
} finally {
|
|
652
741
|
if (queryRef.current === id) {
|
|
653
742
|
if (alive.current) setQueryId("");
|
|
@@ -655,11 +744,123 @@ function Workspace({ clusterId, contextId }) {
|
|
|
655
744
|
}
|
|
656
745
|
}
|
|
657
746
|
};
|
|
658
|
-
const
|
|
747
|
+
const applyPreset = async (title, selectedCapture, execute = false) => {
|
|
748
|
+
const captured = selectedCapture ?? captures.find((item) => item.id === captureId);
|
|
749
|
+
if (queryRef.current || !selectedCapture && captureController.current) return;
|
|
750
|
+
if (title === "Recent") {
|
|
751
|
+
const query = examples[0][1];
|
|
752
|
+
setSql(query);
|
|
753
|
+
setSelectedSqlRow(void 0);
|
|
754
|
+
if (execute && captured) runQuery(captured, query);
|
|
755
|
+
return;
|
|
756
|
+
}
|
|
757
|
+
if (queryRef.current || !selectedCapture && captureController.current || !captured || captured.state === "collecting" || deleting.current.has(captured.id)) return;
|
|
758
|
+
const draft = execute ? examples[0][1] : sqlDraft.current;
|
|
759
|
+
const id = (0, node_crypto.randomUUID)();
|
|
760
|
+
queryRef.current = id;
|
|
761
|
+
setQueryId(id);
|
|
762
|
+
setSqlError("");
|
|
763
|
+
let prepared;
|
|
764
|
+
try {
|
|
765
|
+
let keys = captureKeys.current.get(captured.id);
|
|
766
|
+
if (!keys) {
|
|
767
|
+
const schema = await client.query(captured.id, id, require_power_log_json_preset.JSON_KEY_DISCOVERY_SQL);
|
|
768
|
+
if (schema.error) throw new Error(schema.error);
|
|
769
|
+
const keyColumn = schema.columns.indexOf("key");
|
|
770
|
+
keys = schema.truncated ? ["\0"] : keyColumn < 0 ? [] : schema.rows.map((row) => row[keyColumn]).filter((key) => typeof key === "string");
|
|
771
|
+
captureKeys.current.set(captured.id, keys);
|
|
772
|
+
if (captureKeys.current.size > 10) captureKeys.current.delete(captureKeys.current.keys().next().value);
|
|
773
|
+
}
|
|
774
|
+
if (!alive.current || queryRef.current !== id || captureSelection.current !== captured.id) return;
|
|
775
|
+
if (sqlDraft.current !== draft) {
|
|
776
|
+
setSqlError("SQL draft changed while detecting JSON fields. Select the preset again to replace it.");
|
|
777
|
+
return;
|
|
778
|
+
}
|
|
779
|
+
prepared = require_power_log_json_preset.buildJsonProjectionSql(keys);
|
|
780
|
+
setSql(prepared);
|
|
781
|
+
setSelectedSqlRow(void 0);
|
|
782
|
+
} catch {
|
|
783
|
+
if (alive.current) setSqlError("Could not detect JSON fields for this snapshot. Try the preset again.");
|
|
784
|
+
} finally {
|
|
785
|
+
if (queryRef.current === id) {
|
|
786
|
+
queryRef.current = "";
|
|
787
|
+
if (alive.current) setQueryId("");
|
|
788
|
+
}
|
|
789
|
+
}
|
|
790
|
+
if (prepared && execute && alive.current) runQuery(captured, prepared);
|
|
791
|
+
};
|
|
792
|
+
const addLiveFilter = (filter) => {
|
|
793
|
+
if (!require_power_log_field_filters.jsonValuesEqual(filter.value, filter.value)) {
|
|
794
|
+
setError("This JSON value is too large or unsupported for filtering");
|
|
795
|
+
return;
|
|
796
|
+
}
|
|
797
|
+
if (fieldFilters.some((current) => sameFieldFilter(current, filter))) return;
|
|
798
|
+
if (fieldFilters.length >= 32) {
|
|
799
|
+
setError("Up to 32 JSON filters can be combined");
|
|
800
|
+
return;
|
|
801
|
+
}
|
|
802
|
+
setFieldFilters([...fieldFilters, filter]);
|
|
803
|
+
};
|
|
804
|
+
const activeSqlFilters = sqlFieldFilters?.rendered === sql && sqlFieldFilters.captureId === captureId ? sqlFieldFilters : void 0;
|
|
805
|
+
const sqlFilteringDisabled = Boolean(queryId || capturePending || deleting.current.has(captureId) || !captures.some((capture) => capture.id === captureId && capture.state !== "collecting"));
|
|
806
|
+
const applySqlFilters = (filters) => {
|
|
807
|
+
if (queryRef.current || captureController.current || sqlFilteringDisabled) return;
|
|
808
|
+
if (!resultEvidence || resultEvidence.sql !== sql) {
|
|
809
|
+
setSqlError("Run the edited SQL query before filtering its results");
|
|
810
|
+
return;
|
|
811
|
+
}
|
|
812
|
+
try {
|
|
813
|
+
const base = activeSqlFilters?.base ?? sql;
|
|
814
|
+
const query = require_power_log_json_filter_sql.buildJsonFilterSql(base, filters);
|
|
815
|
+
setSqlFieldFilters({
|
|
816
|
+
base,
|
|
817
|
+
rendered: query,
|
|
818
|
+
captureId,
|
|
819
|
+
filters
|
|
820
|
+
});
|
|
821
|
+
setSql(query);
|
|
822
|
+
runQuery(void 0, query);
|
|
823
|
+
} catch {
|
|
824
|
+
setSqlError("This JSON filter cannot be added to the query. Check the field path and value size.");
|
|
825
|
+
}
|
|
826
|
+
};
|
|
827
|
+
const addSqlFilter = (column, filter) => {
|
|
828
|
+
const columnNames = result?.columns.map((name) => name.replace(/[A-Z]/g, (letter) => letter.toLowerCase())) ?? [];
|
|
829
|
+
if (!result?.columns.includes(column) || new Set(columnNames).size !== columnNames.length) {
|
|
830
|
+
setSqlError("JSON filters require unique result column names, ignoring case");
|
|
831
|
+
return;
|
|
832
|
+
}
|
|
833
|
+
const filters = activeSqlFilters?.filters ?? [];
|
|
834
|
+
if (filters.some((current) => current.column === column && sameFieldFilter(current, filter))) return;
|
|
835
|
+
if (filters.length >= 32) {
|
|
836
|
+
setSqlError("Up to 32 JSON filters can be combined");
|
|
837
|
+
return;
|
|
838
|
+
}
|
|
839
|
+
applySqlFilters([...filters, {
|
|
840
|
+
...filter,
|
|
841
|
+
column
|
|
842
|
+
}]);
|
|
843
|
+
};
|
|
844
|
+
const matchesRecordFields = (record) => {
|
|
845
|
+
if (!fieldFilters.length) return true;
|
|
846
|
+
if (!parsedFields.current.has(record)) {
|
|
847
|
+
let fields;
|
|
848
|
+
try {
|
|
849
|
+
fields = JSON.parse(record.fieldsJson ?? "null");
|
|
850
|
+
} catch {
|
|
851
|
+
fields = void 0;
|
|
852
|
+
}
|
|
853
|
+
parsedFields.current.set(record, fields);
|
|
854
|
+
}
|
|
855
|
+
return matchFields(parsedFields.current.get(record));
|
|
856
|
+
};
|
|
857
|
+
const filtered = require__global_external_react.useMemo(() => records.filter((record) => (!text || record.message.toLocaleLowerCase().includes(text.toLocaleLowerCase())) && (!level || record.level === level) && (!source || (source.startsWith("container:") ? record.container === source.slice(10) : sourceKey(record) === source)) && matchesRecordFields(record)), [
|
|
659
858
|
records,
|
|
660
859
|
text,
|
|
661
860
|
level,
|
|
662
|
-
source
|
|
861
|
+
source,
|
|
862
|
+
fieldFilters,
|
|
863
|
+
matchFields
|
|
663
864
|
]);
|
|
664
865
|
const chosenCapture = captures.find((item) => item.id === captureId);
|
|
665
866
|
const collectionNotes = tab === "live" ? [.../* @__PURE__ */ new Set([...notes, ...live ? liveCoverage?.notes ?? [] : []])] : [];
|
|
@@ -674,12 +875,12 @@ function Workspace({ clusterId, contextId }) {
|
|
|
674
875
|
const sql = event.detail?.sql;
|
|
675
876
|
if (typeof sql !== "string" || !sql.trim() || sql.length > 65536) return;
|
|
676
877
|
setTab("captures");
|
|
677
|
-
setSql(sql);
|
|
678
878
|
setSelectedSqlRow(void 0);
|
|
679
879
|
if (!captureId) {
|
|
680
880
|
const latest = captures.find((item) => item.state !== "collecting" && item.target.uid === target?.uid);
|
|
681
881
|
if (latest) setCaptureId(latest.id);
|
|
682
882
|
}
|
|
883
|
+
setSql(sql);
|
|
683
884
|
requestAnimationFrame(() => document.getElementById("power-logs-sql")?.focus());
|
|
684
885
|
};
|
|
685
886
|
window.addEventListener("power-logs-sql-draft", insert);
|
|
@@ -690,12 +891,19 @@ function Workspace({ clusterId, contextId }) {
|
|
|
690
891
|
target?.uid
|
|
691
892
|
]);
|
|
692
893
|
const attachAi = () => {
|
|
693
|
-
const
|
|
694
|
-
|
|
695
|
-
|
|
894
|
+
const queryEvidence = result ?? (resultEvidence?.error ? {
|
|
895
|
+
columns: [],
|
|
896
|
+
rows: [],
|
|
897
|
+
truncated: false,
|
|
898
|
+
elapsedMs: 0,
|
|
899
|
+
error: resultEvidence.error
|
|
900
|
+
} : void 0);
|
|
901
|
+
const resource = tab === "captures" ? queryEvidence && resultEvidence ? resultEvidence.capture.target : chosenCapture?.target ?? target : target;
|
|
902
|
+
const summary = tab === "captures" && queryEvidence && resultEvidence ? require_power_logs_ai.powerLogQueryEvidence(resultEvidence.capture, resultEvidence.sql, selectedSqlRow ? {
|
|
903
|
+
...queryEvidence,
|
|
696
904
|
rows: [selectedSqlRow.row],
|
|
697
905
|
truncated: false
|
|
698
|
-
} :
|
|
906
|
+
} : queryEvidence) : tab === "live" && selected ? require_power_logs_ai.powerLogLineEvidence(resource, selected) : JSON.stringify({
|
|
699
907
|
target: resource,
|
|
700
908
|
...tab === "captures" ? {
|
|
701
909
|
sql,
|
|
@@ -708,6 +916,7 @@ function Workspace({ clusterId, contextId }) {
|
|
|
708
916
|
});
|
|
709
917
|
if (!require_ai_diagnostic_handoff.explainDiagnosticFinding({
|
|
710
918
|
clusterId,
|
|
919
|
+
source: "logs",
|
|
711
920
|
title: tab === "captures" ? selectedSqlRow ? "SQL row" : "SQL query" : selected ? "Log line" : "Power Logs",
|
|
712
921
|
summary: summary.slice(0, 6e3),
|
|
713
922
|
...resource ? { resource: {
|
|
@@ -722,7 +931,9 @@ function Workspace({ clusterId, contextId }) {
|
|
|
722
931
|
deleting.current.add(id);
|
|
723
932
|
setDeletingCount(deleting.current.size);
|
|
724
933
|
try {
|
|
934
|
+
await drafts.flush();
|
|
725
935
|
await client.delete(id);
|
|
936
|
+
drafts.forget(id);
|
|
726
937
|
if (id === captureSelection.current) {
|
|
727
938
|
setCaptureId("");
|
|
728
939
|
setResult(void 0);
|
|
@@ -753,6 +964,7 @@ function Workspace({ clusterId, contextId }) {
|
|
|
753
964
|
className: "power-logs",
|
|
754
965
|
"data-testid": "power-logs-page",
|
|
755
966
|
"data-compact": compact || void 0,
|
|
967
|
+
"data-hide-resource-name": hideResourceName || void 0,
|
|
756
968
|
children: [
|
|
757
969
|
/* @__PURE__ */ require_jsx_runtime.jsx("style", { children: require_power_logs_css.powerLogsStyles }),
|
|
758
970
|
/* @__PURE__ */ require_jsx_runtime.jsxs("header", { children: [
|
|
@@ -793,11 +1005,7 @@ function Workspace({ clusterId, contextId }) {
|
|
|
793
1005
|
onClick: () => {
|
|
794
1006
|
setTab("captures");
|
|
795
1007
|
const latest = captures.find((item) => item.state !== "collecting" && (!target || item.target.uid === target.uid));
|
|
796
|
-
if (!captureId && latest && !capturePending)
|
|
797
|
-
setCaptureId(latest.id);
|
|
798
|
-
setSql(examples[0][1]);
|
|
799
|
-
runQuery(latest, examples[0][1]);
|
|
800
|
-
}
|
|
1008
|
+
if (!captureId && latest && !capturePending) setCaptureId(latest.id);
|
|
801
1009
|
refreshCaptures();
|
|
802
1010
|
},
|
|
803
1011
|
children: [/* @__PURE__ */ require_jsx_runtime.jsx(Icon, {
|
|
@@ -854,6 +1062,14 @@ function Workspace({ clusterId, contextId }) {
|
|
|
854
1062
|
preferences.compactRows = value;
|
|
855
1063
|
},
|
|
856
1064
|
children: "Compact density"
|
|
1065
|
+
}),
|
|
1066
|
+
/* @__PURE__ */ require_jsx_runtime.jsx(require_extensions.Renderer.Component.Switch, {
|
|
1067
|
+
checked: hideResourceName,
|
|
1068
|
+
onChange: (value) => {
|
|
1069
|
+
setHideResourceName(value);
|
|
1070
|
+
preferences.hideResourceNameColumn = value;
|
|
1071
|
+
},
|
|
1072
|
+
children: "Hide resource name column"
|
|
857
1073
|
})
|
|
858
1074
|
] })]
|
|
859
1075
|
}),
|
|
@@ -1036,6 +1252,10 @@ function Workspace({ clusterId, contextId }) {
|
|
|
1036
1252
|
})
|
|
1037
1253
|
]
|
|
1038
1254
|
}),
|
|
1255
|
+
/* @__PURE__ */ require_jsx_runtime.jsx(FieldFilters, {
|
|
1256
|
+
filters: fieldFilters,
|
|
1257
|
+
onRemove: (index) => setFieldFilters(fieldFilters.filter((_, item) => item !== index))
|
|
1258
|
+
}),
|
|
1039
1259
|
/* @__PURE__ */ require_jsx_runtime.jsxs("div", {
|
|
1040
1260
|
className: "power-logs-muted power-logs-status",
|
|
1041
1261
|
role: "status",
|
|
@@ -1064,97 +1284,101 @@ function Workspace({ clusterId, contextId }) {
|
|
|
1064
1284
|
compact
|
|
1065
1285
|
}), selected && /* @__PURE__ */ require_jsx_runtime.jsx(LogDetails, {
|
|
1066
1286
|
record: selected,
|
|
1067
|
-
onClose: () => setSelected(void 0)
|
|
1287
|
+
onClose: () => setSelected(void 0),
|
|
1288
|
+
onFilter: addLiveFilter
|
|
1068
1289
|
})]
|
|
1069
1290
|
})
|
|
1070
1291
|
] }) : /* @__PURE__ */ require_jsx_runtime.jsxs(require_jsx_runtime.Fragment, { children: [
|
|
1071
1292
|
/* @__PURE__ */ require_jsx_runtime.jsxs("div", {
|
|
1072
1293
|
className: "power-logs-toolbar power-logs-snapshot-bar",
|
|
1073
|
-
children: [
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
" ",
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
event
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1294
|
+
children: [
|
|
1295
|
+
/* @__PURE__ */ require_jsx_runtime.jsx("span", {
|
|
1296
|
+
className: "power-logs-control-label",
|
|
1297
|
+
children: "Snapshot"
|
|
1298
|
+
}),
|
|
1299
|
+
/* @__PURE__ */ require_jsx_runtime.jsx(LogSelect, {
|
|
1300
|
+
label: "Capture snapshot",
|
|
1301
|
+
onKeyDown: (event) => {
|
|
1302
|
+
if (event.key !== "Delete" || !event.altKey || (event.target.value ?? "").length > 0) return;
|
|
1303
|
+
const button = document.querySelector(".Select__menu .Select__option--is-focused [data-capture-delete]");
|
|
1304
|
+
if (button && !button.disabled) {
|
|
1305
|
+
event.preventDefault();
|
|
1306
|
+
event.stopPropagation();
|
|
1307
|
+
deleteCapture(button.dataset.captureDelete);
|
|
1308
|
+
}
|
|
1309
|
+
},
|
|
1310
|
+
renderOption: (option, context) => {
|
|
1311
|
+
const item = captures.find((item) => item.id === option.value);
|
|
1312
|
+
if (context !== "menu" || !item) return option.label;
|
|
1313
|
+
return /* @__PURE__ */ require_jsx_runtime.jsxs("span", {
|
|
1314
|
+
className: "power-logs-snapshot-option",
|
|
1315
|
+
title: option.label,
|
|
1316
|
+
children: [/* @__PURE__ */ require_jsx_runtime.jsxs("span", {
|
|
1317
|
+
className: "power-logs-option-text",
|
|
1318
|
+
children: [/* @__PURE__ */ require_jsx_runtime.jsx("strong", { children: item.target.name }), /* @__PURE__ */ require_jsx_runtime.jsxs("small", { children: [
|
|
1319
|
+
require_date_time.formatDateTime(item.createdAt),
|
|
1320
|
+
" · ",
|
|
1321
|
+
item.rows.toLocaleString(),
|
|
1322
|
+
" lines ·",
|
|
1323
|
+
" ",
|
|
1324
|
+
item.state[0].toUpperCase(),
|
|
1325
|
+
item.state.slice(1)
|
|
1326
|
+
] })]
|
|
1327
|
+
}), /* @__PURE__ */ require_jsx_runtime.jsx("button", {
|
|
1328
|
+
type: "button",
|
|
1329
|
+
"aria-label": `Delete snapshot ${item.target.name}`,
|
|
1330
|
+
title: "Delete snapshot (Alt+Delete)",
|
|
1331
|
+
"data-capture-delete": item.id,
|
|
1332
|
+
onKeyDown: (event) => event.stopPropagation(),
|
|
1333
|
+
disabled: !!queryId || capturePending || deletingCount > 0 || item.state === "collecting",
|
|
1334
|
+
onMouseDown: (event) => {
|
|
1335
|
+
event.preventDefault();
|
|
1336
|
+
event.stopPropagation();
|
|
1337
|
+
},
|
|
1338
|
+
onClick: (event) => {
|
|
1339
|
+
event.preventDefault();
|
|
1340
|
+
event.stopPropagation();
|
|
1341
|
+
deleteCapture(item.id);
|
|
1342
|
+
},
|
|
1343
|
+
children: /* @__PURE__ */ require_jsx_runtime.jsx(require_extensions.Renderer.Component.Icon, {
|
|
1344
|
+
material: "delete_outline",
|
|
1345
|
+
size: 16,
|
|
1346
|
+
tooltip: "Delete snapshot",
|
|
1347
|
+
tooltipOverrideDisabled: true
|
|
1348
|
+
})
|
|
1349
|
+
})]
|
|
1350
|
+
});
|
|
1351
|
+
},
|
|
1352
|
+
value: captureId,
|
|
1353
|
+
disabled: !!queryId || capturePending || deletingCount > 0,
|
|
1354
|
+
onChange: (value) => {
|
|
1355
|
+
setCaptureId(value);
|
|
1356
|
+
setResult(void 0);
|
|
1357
|
+
setResultEvidence(void 0);
|
|
1358
|
+
setSelectedSqlRow(void 0);
|
|
1359
|
+
setSqlError("");
|
|
1360
|
+
},
|
|
1361
|
+
options: [{
|
|
1362
|
+
value: "",
|
|
1363
|
+
label: "Choose a snapshot"
|
|
1364
|
+
}, ...captures.map((item) => ({
|
|
1365
|
+
value: item.id,
|
|
1366
|
+
label: `${item.target.name} · ${require_date_time.formatDateTime(item.createdAt)} · ${item.rows.toLocaleString()} lines · ${item.state[0].toUpperCase()}${item.state.slice(1)}`
|
|
1367
|
+
}))]
|
|
1368
|
+
}),
|
|
1369
|
+
/* @__PURE__ */ require_jsx_runtime.jsxs("button", {
|
|
1370
|
+
type: "button",
|
|
1371
|
+
disabled: !captureId || !!queryId || deleting.current.has(captureId),
|
|
1372
|
+
title: "Export JSON Lines (NDJSON)",
|
|
1373
|
+
onClick: () => {
|
|
1374
|
+
client.export(captureId).catch(() => setError("Could not export capture"));
|
|
1375
|
+
},
|
|
1376
|
+
children: [/* @__PURE__ */ require_jsx_runtime.jsx(Icon, {
|
|
1377
|
+
material: "download",
|
|
1378
|
+
size: 16
|
|
1379
|
+
}), " Export JSON"]
|
|
1380
|
+
})
|
|
1381
|
+
]
|
|
1158
1382
|
}),
|
|
1159
1383
|
!!chosenCapture?.notes.length && /* @__PURE__ */ require_jsx_runtime.jsxs("details", {
|
|
1160
1384
|
className: "power-logs-snapshot-notes power-logs-muted",
|
|
@@ -1169,6 +1393,7 @@ function Workspace({ clusterId, contextId }) {
|
|
|
1169
1393
|
children: [
|
|
1170
1394
|
/* @__PURE__ */ require_jsx_runtime.jsx("label", {
|
|
1171
1395
|
htmlFor: "power-logs-sql",
|
|
1396
|
+
className: "power-logs-control-label",
|
|
1172
1397
|
title: `Read-only SELECT · ${limits.queryMs / 1e3} s · ${limits.resultRows.toLocaleString()} rows · Schema: logs(timestamp INTEGER in milliseconds, pod, podUid, container, level, message, fieldsJson, previous INTEGER 0 or 1)`,
|
|
1173
1398
|
children: "SQL query"
|
|
1174
1399
|
}),
|
|
@@ -1193,26 +1418,35 @@ function Workspace({ clusterId, contextId }) {
|
|
|
1193
1418
|
}),
|
|
1194
1419
|
examples.map(([title, query]) => /* @__PURE__ */ require_jsx_runtime.jsxs("button", {
|
|
1195
1420
|
type: "button",
|
|
1196
|
-
|
|
1421
|
+
disabled: !!queryId || capturePending,
|
|
1422
|
+
onClick: () => title === "JSON" || title === "Recent" ? void applyPreset(title) : setSql(query),
|
|
1197
1423
|
children: [
|
|
1198
1424
|
/* @__PURE__ */ require_jsx_runtime.jsx(Icon, {
|
|
1199
1425
|
material: title === "Recent" ? "history" : title === "Errors" ? "error_outline" : title === "Timeline" ? "timeline" : "data_object",
|
|
1200
1426
|
size: 16
|
|
1201
1427
|
}),
|
|
1202
1428
|
" ",
|
|
1203
|
-
"SQL
|
|
1429
|
+
"SQL · ",
|
|
1204
1430
|
title
|
|
1205
1431
|
]
|
|
1206
1432
|
}, title))
|
|
1207
1433
|
]
|
|
1208
1434
|
}),
|
|
1209
|
-
/* @__PURE__ */ require_jsx_runtime.jsx(
|
|
1210
|
-
|
|
1435
|
+
/* @__PURE__ */ require_jsx_runtime.jsx(FieldFilters, {
|
|
1436
|
+
sql: true,
|
|
1437
|
+
filters: activeSqlFilters?.filters ?? [],
|
|
1438
|
+
disabled: sqlFilteringDisabled,
|
|
1439
|
+
onRemove: (index) => applySqlFilters((activeSqlFilters?.filters ?? []).filter((_, item) => item !== index))
|
|
1440
|
+
}),
|
|
1441
|
+
/* @__PURE__ */ require_jsx_runtime.jsx(require_power_log_sql_editor.SqlEditor, {
|
|
1211
1442
|
id: "power-logs-sql",
|
|
1212
1443
|
value: sql,
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1444
|
+
onChange: setSql
|
|
1445
|
+
}),
|
|
1446
|
+
sqlError && /* @__PURE__ */ require_jsx_runtime.jsx("div", {
|
|
1447
|
+
role: "alert",
|
|
1448
|
+
className: "power-logs-notice power-logs-error power-logs-query-error",
|
|
1449
|
+
children: sqlError
|
|
1216
1450
|
}),
|
|
1217
1451
|
result ? /* @__PURE__ */ require_jsx_runtime.jsxs(require_jsx_runtime.Fragment, { children: [
|
|
1218
1452
|
/* @__PURE__ */ require_jsx_runtime.jsx("div", {
|
|
@@ -1259,22 +1493,25 @@ function Workspace({ clusterId, contextId }) {
|
|
|
1259
1493
|
},
|
|
1260
1494
|
children: row.map((cell, j) => /* @__PURE__ */ require_jsx_runtime.jsx("td", {
|
|
1261
1495
|
"data-column": result.columns[j],
|
|
1262
|
-
"data-level": result.columns[j]
|
|
1263
|
-
children: /* @__PURE__ */ require_jsx_runtime.jsx(
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1496
|
+
"data-level": require_power_log_sql_level.sqlCellLevel(result.columns[j], cell),
|
|
1497
|
+
children: /* @__PURE__ */ require_jsx_runtime.jsx(require_power_log_json_cell.LogJsonCell, {
|
|
1498
|
+
value: cell === null ? null : String(cell),
|
|
1499
|
+
column: result.columns[j],
|
|
1500
|
+
rawValue: cell,
|
|
1501
|
+
Icon,
|
|
1502
|
+
onFilter: sqlFilteringDisabled ? void 0 : (filter) => addSqlFilter(result.columns[j], filter)
|
|
1267
1503
|
})
|
|
1268
1504
|
}, j))
|
|
1269
1505
|
}, i)) })
|
|
1270
1506
|
]
|
|
1271
1507
|
}), result.rows.length === 0 && /* @__PURE__ */ require_jsx_runtime.jsx("div", {
|
|
1272
1508
|
className: "power-logs-empty",
|
|
1273
|
-
children: chosenCapture?.rows === 0 ? "This snapshot contains no log lines. Try a longer capture window." : "This query returned no rows. Adjust the query or choose SQL
|
|
1509
|
+
children: chosenCapture?.rows === 0 ? "This snapshot contains no log lines. Try a longer capture window." : "This query returned no rows. Adjust the query or choose SQL · Recent."
|
|
1274
1510
|
})]
|
|
1275
1511
|
}), selectedSqlRow && /* @__PURE__ */ require_jsx_runtime.jsx(LogDetails, {
|
|
1276
1512
|
record: selectedSqlRow.record,
|
|
1277
1513
|
jsonColumn: selectedSqlRow.jsonColumn,
|
|
1514
|
+
onFilter: !sqlFilteringDisabled && selectedSqlRow.jsonColumn ? (filter) => addSqlFilter(selectedSqlRow.jsonColumn, filter) : void 0,
|
|
1278
1515
|
onClose: () => setSelectedSqlRow(void 0)
|
|
1279
1516
|
})]
|
|
1280
1517
|
}),
|