mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-07-08 21:56:08 +00:00
f8e89cc848
* fix(logs): render journalctl output in the SysLog viewer The log viewer's parseLogLine only understood the app-log format (2006/01/02 15:04:05 LEVEL - body). With SysLog ticked the backend returns journalctl lines (Mon DD HH:MM:SS host ident[pid]: LEVEL - body), so the parser mistook the journal time for the level and dropped the body, leaving only timestamps. Detect and strip the journald prefix, keep the journal timestamp as the stamp, then parse the real level and body from the remainder. * feat(mtproto): surface mtg output and add status reporting mtg's stdout/stderr was captured by a writer that kept only the last line and showed it nowhere, so the reason a proxy could not reach Telegram was invisible. Stream mtg output line-by-line into the x-ui log, tagged per inbound, so it appears in the panel log viewer and journald. Also fix mangled log lines: logger.Info uses fmt.Sprint, which drops the space between adjacent string operands, producing output like 'inbound3on0.0.0.0:8443'. Switch the affected mtproto calls to the formatted (*f) variants. Add show_mtproto_status to x-ui.sh so 'x-ui status' reports each mtproto inbound's mtg process state and bind address. * fix(logs): parse all journalctl message shapes in SysLog viewer Real journalctl output mixes four message shapes after the 'Mon DD HH:MM:SS host ident[pid]:' prefix: go-logging 'LEVEL - msg' (x-ui/xray), Go std-log with an embedded date (net/http, runtime), telego's '[timestamp] LEVEL msg', and systemd lines. The viewer only understood the first, so std-log and telego lines — which never contain ' - ' — collapsed to a bare timestamp (e.g. the 8s telego 409 spam). Extract the parser into a pure, testable module and teach it the other shapes: strip the redundant Go std-log date, lift the level out of telego brackets, and always keep the message body. Add a unit test covering each shape with real captured lines. * fix(mtproto): reap orphaned mtg sidecars so a stale one can't break new clients On Linux x-ui does not kill its mtg children when it dies (no kill-on-exit, unlike the Windows job object). After a crash, OOM, kill -9, or update, a stale mtg keeps holding the inbound port with an OLD secret, so new clients fail the FakeTLS handshake and get silently domain-fronted to the fakeTLS domain instead of proxied to Telegram (a few MB of traffic, never connects). Sweep orphans at startup: on the first reconcile, before x-ui starts any of its own mtg, scan /proc and SIGKILL any process whose executable is our mtg-<goos>-<goarch> binary. x-ui is the sole owner of mtg, so anything alive then is an orphan. Runs once per process (swept guard), survives the binary-deleted-during-update case via /proc/<pid>/cmdline, and is a no-op on Windows (job object) and other platforms. Also clear stray mtg in update.sh/install.sh after stopping x-ui, anchored to the 'mtg-linux-<arch> run ' invocation so the pattern can't match unrelated command lines (e.g. x-ui.sh's own 'grep mtg-linux'). * fix(logs): drop dead body initializer flagged by eslint no-useless-assignment * fix(mtproto): drop remark fragment from tg://proxy export link The mtproto export link appended the inbound remark as a URL fragment (tg://proxy?server=...&port=...&secret=...#remark). Telegram Desktop rejects a proxy deep link with a trailing fragment as 'This proxy link is invalid', breaking one-click import, and a remark is meaningless for proxy links across clients. Stop adding it in both the panel link (genMtprotoLink) and the subscription service. Fixes #5105. * fix(x-ui.sh): remove unused check_mtproto_status helper show_mtproto_status does its own process check, so check_mtproto_status was dead code. Drop it (per Copilot review on #5107).
81 lines
3.4 KiB
TypeScript
81 lines
3.4 KiB
TypeScript
import { describe, it, expect } from 'vitest';
|
|
|
|
import { parseLogLine } from '@/pages/index/logParse';
|
|
|
|
// Fixtures are real lines captured from `journalctl -u x-ui` on a production
|
|
// host (the SysLog view) plus the in-memory app-log format. Each journald entry
|
|
// carries a "Mon DD HH:MM:SS host ident[pid]: " prefix that the viewer used to
|
|
// mistake for the level, leaving only a bare timestamp on screen.
|
|
describe('parseLogLine — SysLog (journalctl) formats', () => {
|
|
it('x-ui go-logging line: keeps level, strips prefix, tags X-UI', () => {
|
|
const r = parseLogLine(
|
|
'Jun 08 23:57:28 ubuntu-4gb-fsn1-1 /usr/local/x-ui/x-ui[72297]: INFO - mtproto: started mtg for inbound 3 on 0.0.0.0:8443',
|
|
);
|
|
expect(r.stamp).toBe('Jun 08 23:57:28');
|
|
expect(r.levelText).toBe('INFO');
|
|
expect(r.service).toBe('X-UI:');
|
|
expect(r.body).toBe('mtproto: started mtg for inbound 3 on 0.0.0.0:8443');
|
|
});
|
|
|
|
it('xray go-logging line: lifts the XRAY service tag', () => {
|
|
const r = parseLogLine(
|
|
'Jun 08 23:56:52 ubuntu-4gb-fsn1-1 /usr/local/x-ui/x-ui[72297]: WARNING - XRAY: core: Xray 26.6.1 started',
|
|
);
|
|
expect(r.stamp).toBe('Jun 08 23:56:52');
|
|
expect(r.levelText).toBe('WARNING');
|
|
expect(r.service).toBe('XRAY:');
|
|
expect(r.body).toBe('core: Xray 26.6.1 started');
|
|
});
|
|
|
|
it('Go std-log line: strips the redundant embedded date, keeps the message', () => {
|
|
const r = parseLogLine(
|
|
'Jun 08 19:22:22 ubuntu-4gb-fsn1-1 x-ui[1439]: 2026/06/08 19:22:22 http: TLS handshake error from 18.97.5.1:36022: EOF',
|
|
);
|
|
expect(r.stamp).toBe('Jun 08 19:22:22');
|
|
expect(r.levelText).toBe('');
|
|
expect(r.body).toBe('http: TLS handshake error from 18.97.5.1:36022: EOF');
|
|
});
|
|
|
|
it('telego bracketed line: lifts the ERROR level out of "[ts] ERROR ..."', () => {
|
|
const r = parseLogLine(
|
|
'Jun 09 00:14:52 ubuntu-4gb-fsn1-1 x-ui[72297]: [Tue Jun 9 00:14:52 UTC 2026] ERROR Retrying getting updates in 8s...',
|
|
);
|
|
expect(r.stamp).toBe('Jun 09 00:14:52');
|
|
expect(r.levelText).toBe('ERROR');
|
|
expect(r.body).toBe('Retrying getting updates in 8s...');
|
|
});
|
|
|
|
it('systemd line: shows the body rather than a bare timestamp', () => {
|
|
const r = parseLogLine(
|
|
'Jun 08 23:56:47 ubuntu-4gb-fsn1-1 systemd[1]: Stopping x-ui.service - x-ui Service...',
|
|
);
|
|
expect(r.stamp).toBe('Jun 08 23:56:47');
|
|
expect(r.body).toBe('Stopping x-ui.service - x-ui Service...');
|
|
});
|
|
|
|
it('never collapses a journald entry to just its timestamp', () => {
|
|
const r = parseLogLine(
|
|
'Jun 09 00:15:00 ubuntu-4gb-fsn1-1 x-ui[72297]: [Tue Jun 9 00:15:00 UTC 2026] ERROR Getting updates: telego: getUpdates: api: 409 "Conflict"',
|
|
);
|
|
expect(r.body.length).toBeGreaterThan(0);
|
|
expect(r.body).toContain('Conflict');
|
|
});
|
|
});
|
|
|
|
describe('parseLogLine — app-log format (SysLog off)', () => {
|
|
it('parses "YYYY/MM/DD HH:MM:SS LEVEL - body"', () => {
|
|
const r = parseLogLine('2026/06/09 00:35:09 INFO - mtproto: started mtg for inbound 3 on 0.0.0.0:8443');
|
|
expect(r.date).toBe('2026/06/09');
|
|
expect(r.time).toBe('00:35:09');
|
|
expect(r.levelText).toBe('INFO');
|
|
expect(r.service).toBe('X-UI:');
|
|
expect(r.body).toBe('mtproto: started mtg for inbound 3 on 0.0.0.0:8443');
|
|
});
|
|
|
|
it('handles an empty line without throwing', () => {
|
|
const r = parseLogLine('');
|
|
expect(r.stamp).toBe('');
|
|
expect(r.body).toBe('');
|
|
});
|
|
});
|