Strip ANSI sequences from container logs for clean display.
Release rolling / release (push) Successful in 8m28s
Release rolling / release (push) Successful in 8m28s
PM2 and similar tools emit VT100 color codes that browsers hide only partially, leaving artifacts like [32m between table columns. Strip CSI/OSC escapes when formatting log lines, and harden Docker multiplex demux on the server so frames are not mis-parsed as text.
This commit is contained in:
@@ -5560,6 +5560,33 @@ let logsState = {
|
||||
containerId: null,
|
||||
};
|
||||
|
||||
/**
|
||||
* Strip ANSI / VT100 escape sequences from container log text.
|
||||
* Apps like PM2 emit colors as ESC[…m; browsers hide ESC so you see "[32m" junk.
|
||||
*/
|
||||
function stripAnsi(input) {
|
||||
let s = String(input ?? '');
|
||||
// CSI: ESC [ ... final byte (@-~)
|
||||
s = s.replace(/\u001b\[[\x30-\x3f]*[\x20-\x2f]*[\x40-\x7e]/g, '');
|
||||
// OSC: ESC ] ... BEL or ST (ESC \)
|
||||
s = s.replace(/\u001b\][^\u0007\u001b]*(?:\u0007|\u001b\\)/g, '');
|
||||
// 2-byte escapes: ESC + final
|
||||
s = s.replace(/\u001b[@-Z\\-_]/g, '');
|
||||
// 7-bit CSI without ESC (rare) and C1 CSI (0x9b)
|
||||
s = s.replace(/\u009b[\x30-\x3f]*[\x20-\x2f]*[\x40-\x7e]/g, '');
|
||||
// Orphaned SGR fragments if ESC was already lost: [1;32m or [39m
|
||||
s = s.replace(/\x1b/g, '');
|
||||
s = s.replace(/(?:^|[^\d])\[(?:\d{1,3};)*\d{0,3}[mK]/g, (m) =>
|
||||
m.startsWith('[') ? '' : m[0]
|
||||
);
|
||||
// Clean leftover pure SGR tokens at line start / after space
|
||||
s = s.replace(/(?:^|\s)\[(?:\d{1,3};)*\d{0,3}m/g, (m) => (m[0] === '[' ? '' : m[0]));
|
||||
s = s.replace(/\[(?:\d{1,3};)*\d{0,3}m/g, '');
|
||||
// Other C0 controls except tab/newline
|
||||
s = s.replace(/[\u0000-\u0008\u000B\u000C\u000E-\u001F\u007F]/g, '');
|
||||
return s;
|
||||
}
|
||||
|
||||
// Detect log level from log line
|
||||
function detectLogLevel(line) {
|
||||
const lowerLine = line.toLowerCase();
|
||||
@@ -5577,8 +5604,10 @@ function detectLogLevel(line) {
|
||||
|
||||
// Format log line with timestamp and level detection
|
||||
function formatLogLine(rawLine) {
|
||||
// Preserve leading spaces; only drop pure empty lines
|
||||
const line = String(rawLine ?? '').replace(/\r$/, '');
|
||||
// Strip ANSI first so colors/tables from PM2 etc. don't leak as "[32m"
|
||||
let line = stripAnsi(String(rawLine ?? ''));
|
||||
// Normalize CR-only progress lines / CRLF
|
||||
line = line.replace(/\r/g, '');
|
||||
if (!line.trim()) return null;
|
||||
|
||||
const level = detectLogLevel(line);
|
||||
|
||||
Reference in New Issue
Block a user