feat(socket): 添加 Socket 运行时调试日志及轮询 400 错误调试文档

- 更新 web/index.html 中 index.js 的资源版本为 v6 以清除旧缓存
- 在 web/index.js 中新增 Socket 运行时日志上报逻辑,捕获并上报连接、断开、错误及重连事件
- 新增调试文档记录生产环境 Socket.IO polling 400 错误的问题、现象与排查计划
This commit is contained in:
2026-06-21 15:39:59 +08:00
parent b1cb84f736
commit 2ddcd18e1e
3 changed files with 91 additions and 4 deletions
+2 -2
View File
@@ -1,4 +1,4 @@
<!DOCTYPE html>
<!DOCTYPE html>
<html lang="zh-CN">
<!-- 充满未知和不稳定的票务系统! -->
@@ -933,7 +933,7 @@
</div>
<script src="/custom-dialog.js?v=12"></script>
<script src="/public-status.js?v=13"></script>
<script src="index.js?v=5"></script>
<script src="index.js?v=6"></script>
<script>
document.addEventListener('DOMContentLoaded', () => {
const isDomain = location.hostname.includes('fse-media.group');
+63 -2
View File
@@ -38,6 +38,38 @@ createApp({
// Prefer polling first so admin remains connected even when the proxy
// does not support WebSocket upgrades reliably.
const socket = io({ transports: ['polling', 'websocket'] });
// #region debug-point socket-runtime-admin
const reportSocketRuntime = (type, detail = {}) => {
try {
const payload = JSON.stringify({
category: 'admin',
source: 'socket-runtime',
level: type.includes('error') ? 'error' : 'info',
type,
detail: {
page: location.pathname,
href: location.href,
online: navigator.onLine,
socket_id: socket.id || '',
connected: !!socket.connected,
transport: socket.io?.engine?.transport?.name || '',
...detail
}
});
if (navigator.sendBeacon) {
const blob = new Blob([payload], { type: 'application/json' });
navigator.sendBeacon('/api/log', blob);
return;
}
fetch('/api/log', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: payload,
keepalive: true
}).catch(() => {});
} catch (_) {}
};
// #endregion
// Data State
const stations = ref([]);
@@ -1354,8 +1386,37 @@ createApp({
};
// Socket Listeners
socket.on('connect', () => { connected.value = true; });
socket.on('disconnect', () => { connected.value = false; });
// #region debug-point socket-runtime-admin
socket.on('connect', () => {
connected.value = true;
reportSocketRuntime('socket_connect');
});
socket.on('disconnect', (reason) => {
connected.value = false;
reportSocketRuntime('socket_disconnect', { reason: reason || '' });
});
socket.on('connect_error', (error) => {
reportSocketRuntime('socket_connect_error', {
message: error?.message || '',
description: error?.description || '',
context: error?.context || null
});
});
if (socket.io) {
socket.io.on('reconnect_attempt', (attempt) => {
reportSocketRuntime('socket_reconnect_attempt', { attempt: Number(attempt) || 0 });
});
socket.io.on('reconnect_error', (error) => {
reportSocketRuntime('socket_reconnect_error', {
message: error?.message || '',
description: error?.description || ''
});
});
socket.io.on('reconnect_failed', () => {
reportSocketRuntime('socket_reconnect_failed');
});
}
// #endregion
socket.on('stations:updated', (data) => {
stations.value = data;