Skip to content

Commit f070172

Browse files
committed
frontend/LogsButton: Add prettify/format to LogsButton's viewer
So it's consistent with the Pod's logs.
1 parent 813dcca commit f070172

File tree

1 file changed

+94
-9
lines changed

1 file changed

+94
-9
lines changed

frontend/src/components/common/Resource/LogsButton.tsx

Lines changed: 94 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import { KubeObject } from '../../../lib/k8s/KubeObject';
3535
import Pod from '../../../lib/k8s/pod';
3636
import ReplicaSet from '../../../lib/k8s/replicaSet';
3737
import { Activity } from '../../activity/Activity';
38+
import { colorizePrettifiedLog } from '../../pod/jsonHandling';
3839
import ActionButton from '../ActionButton';
3940
import { LogViewer } from '../LogViewer';
4041
import { LightTooltip } from '../Tooltip';
@@ -67,6 +68,9 @@ function LogsButtonContent({ item }: LogsButtonProps) {
6768
const [lines, setLines] = useState<number>(100);
6869
const [showPrevious, setShowPrevious] = React.useState<boolean>(false);
6970
const [showReconnectButton, setShowReconnectButton] = useState(false);
71+
const [prettifyLogs, setPrettifyLogs] = useState<boolean>(false);
72+
const [formatJsonValues, setFormatJsonValues] = useState<boolean>(false);
73+
const [hasJsonLogs, setHasJsonLogs] = useState<boolean>(false);
7074

7175
const xtermRef = React.useRef<XTerminal | null>(null);
7276
const { t } = useTranslation(['glossary', 'translation']);
@@ -141,6 +145,14 @@ function LogsButtonContent({ item }: LogsButtonProps) {
141145
setShowPrevious(previous => !previous);
142146
}
143147

148+
function handlePrettifyChange() {
149+
setPrettifyLogs(prev => !prev);
150+
}
151+
152+
function handleFormatJsonValuesChange() {
153+
setFormatJsonValues(prev => !prev);
154+
}
155+
144156
// Handler for initial logs button click
145157
async function onMount() {
146158
if (item instanceof Deployment || item instanceof ReplicaSet || item instanceof DaemonSet) {
@@ -222,16 +234,19 @@ function LogsButtonContent({ item }: LogsButtonProps) {
222234
return timestampA.localeCompare(timestampB);
223235
});
224236

237+
const displayLogs =
238+
prettifyLogs && hasJsonLogs ? allLogs.map(log => colorizePrettifiedLog(log)) : allLogs;
239+
225240
if (xtermRef.current) {
226241
xtermRef.current.clear();
227-
xtermRef.current.write(allLogs.join('').replaceAll('\n', '\r\n'));
242+
xtermRef.current.write(displayLogs.join('').replaceAll('\n', '\r\n'));
228243
}
229244

230245
setLogs({
231246
logs: allLogs,
232247
lastLineShown: allLogs.length - 1,
233248
});
234-
}, [allPodLogs]);
249+
}, [allPodLogs, prettifyLogs, hasJsonLogs]);
235250

236251
// Function to fetch and aggregate logs from all pods
237252
function fetchAllPodsLogs(pods: Pod[], container: string): () => void {
@@ -243,7 +258,16 @@ function LogsButtonContent({ item }: LogsButtonProps) {
243258
pods.forEach(pod => {
244259
const cleanup = pod.getLogs(
245260
container,
246-
({ logs: newLogs }: { logs: string[]; hasJsonLogs?: boolean }) => {
261+
({
262+
logs: newLogs,
263+
hasJsonLogs: newHasJsonLogs,
264+
}: {
265+
logs: string[];
266+
hasJsonLogs?: boolean;
267+
}) => {
268+
if (newHasJsonLogs) {
269+
setHasJsonLogs(true);
270+
}
247271
const podName = pod.getName();
248272
setAllPodLogs(current => {
249273
const updated = {
@@ -258,6 +282,8 @@ function LogsButtonContent({ item }: LogsButtonProps) {
258282
showPrevious,
259283
showTimestamps,
260284
follow,
285+
prettifyLogs,
286+
formatJsonValues,
261287
onReconnectStop: () => {
262288
setShowReconnectButton(true);
263289
},
@@ -277,6 +303,7 @@ function LogsButtonContent({ item }: LogsButtonProps) {
277303
if (selectedContainer) {
278304
clearLogs();
279305
setAllPodLogs({}); // Clear aggregated logs when switching pods
306+
setHasJsonLogs(false);
280307

281308
// Handle paused logs state
282309
if (!follow && logs.logs.length > 0) {
@@ -296,8 +323,17 @@ function LogsButtonContent({ item }: LogsButtonProps) {
296323
let lastLogLength = 0;
297324
cleanup = pod.getLogs(
298325
selectedContainer,
299-
({ logs: newLogs }: { logs: string[]; hasJsonLogs?: boolean }) => {
326+
({
327+
logs: newLogs,
328+
hasJsonLogs: newHasJsonLogs,
329+
}: {
330+
logs: string[];
331+
hasJsonLogs?: boolean;
332+
}) => {
300333
if (!isSubscribed) return;
334+
if (newHasJsonLogs) {
335+
setHasJsonLogs(true);
336+
}
301337

302338
setLogs(current => {
303339
const terminalRef = xtermRef.current;
@@ -310,10 +346,12 @@ function LogsButtonContent({ item }: LogsButtonProps) {
310346
const endIdx = Math.min(startIdx + CHUNK_SIZE, newLogs.length);
311347

312348
// Process only the new chunk of logs
313-
const newLogContent = newLogs
314-
.slice(startIdx, endIdx)
315-
.join('')
316-
.replaceAll('\n', '\r\n');
349+
const logSlice = newLogs.slice(startIdx, endIdx);
350+
const displaySlice =
351+
prettifyLogs && newHasJsonLogs
352+
? logSlice.map(log => colorizePrettifiedLog(log))
353+
: logSlice;
354+
const newLogContent = displaySlice.join('').replaceAll('\n', '\r\n');
317355

318356
terminalRef.write(newLogContent);
319357
lastLogLength = endIdx;
@@ -342,6 +380,8 @@ function LogsButtonContent({ item }: LogsButtonProps) {
342380
showPrevious,
343381
showTimestamps,
344382
follow,
383+
prettifyLogs,
384+
formatJsonValues,
345385
onReconnectStop: () => {
346386
if (isSubscribed) {
347387
setShowReconnectButton(true);
@@ -359,7 +399,18 @@ function LogsButtonContent({ item }: LogsButtonProps) {
359399
cleanup();
360400
}
361401
};
362-
}, [selectedPodIndex, selectedContainer, lines, showTimestamps, follow, clearLogs, t, pods]);
402+
}, [
403+
selectedPodIndex,
404+
selectedContainer,
405+
lines,
406+
showTimestamps,
407+
follow,
408+
clearLogs,
409+
t,
410+
pods,
411+
prettifyLogs,
412+
formatJsonValues,
413+
]);
363414

364415
// Effect to process logs when allPodLogs changes - only for "All Pods" mode
365416
React.useEffect(() => {
@@ -496,6 +547,40 @@ function LogsButtonContent({ item }: LogsButtonProps) {
496547
disabled={false}
497548
/>
498549
</LightTooltip>
550+
551+
{/* Prettify JSON logs switch */}
552+
{hasJsonLogs && (
553+
<PaddedFormControlLabel
554+
label={t('translation|Prettify')}
555+
control={
556+
<Switch
557+
checked={prettifyLogs}
558+
onChange={handlePrettifyChange}
559+
size="small"
560+
sx={{ transform: 'scale(0.8)' }}
561+
/>
562+
}
563+
/>
564+
)}
565+
566+
{/* Format JSON values switch */}
567+
{hasJsonLogs && (
568+
<LightTooltip
569+
title={t('translation|Show JSON values in plain text by removing escape characters.')}
570+
>
571+
<PaddedFormControlLabel
572+
label={t('translation|Format')}
573+
control={
574+
<Switch
575+
checked={formatJsonValues}
576+
onChange={handleFormatJsonValuesChange}
577+
size="small"
578+
sx={{ transform: 'scale(0.8)' }}
579+
/>
580+
}
581+
/>
582+
</LightTooltip>
583+
)}
499584
</Box>,
500585
];
501586

0 commit comments

Comments
 (0)