feat(opsserver): add real-time log push to ops dashboard and recent DNS query tracking
This commit is contained in:
@@ -1075,6 +1075,55 @@ export const toggleRemoteIngressAction = remoteIngressStatePart.createAction<{
|
||||
}
|
||||
});
|
||||
|
||||
// ============================================================================
|
||||
// TypedSocket Client for Real-time Log Streaming
|
||||
// ============================================================================
|
||||
|
||||
let socketClient: plugins.typedsocket.TypedSocket | null = null;
|
||||
const socketRouter = new plugins.domtools.plugins.typedrequest.TypedRouter();
|
||||
|
||||
// Register handler for pushed log entries from the server
|
||||
socketRouter.addTypedHandler(
|
||||
new plugins.domtools.plugins.typedrequest.TypedHandler<interfaces.requests.IReq_PushLogEntry>(
|
||||
'pushLogEntry',
|
||||
async (dataArg) => {
|
||||
const current = logStatePart.getState();
|
||||
const updated = [...current.recentLogs, dataArg.entry];
|
||||
// Cap at 2000 entries
|
||||
if (updated.length > 2000) {
|
||||
updated.splice(0, updated.length - 2000);
|
||||
}
|
||||
logStatePart.setState({ ...current, recentLogs: updated });
|
||||
return {};
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
async function connectSocket() {
|
||||
if (socketClient) return;
|
||||
try {
|
||||
socketClient = await plugins.typedsocket.TypedSocket.createClient(
|
||||
socketRouter,
|
||||
plugins.typedsocket.TypedSocket.useWindowLocationOriginUrl(),
|
||||
);
|
||||
await socketClient.setTag('role', 'ops_dashboard');
|
||||
} catch (err) {
|
||||
console.error('TypedSocket connection failed:', err);
|
||||
socketClient = null;
|
||||
}
|
||||
}
|
||||
|
||||
async function disconnectSocket() {
|
||||
if (socketClient) {
|
||||
try {
|
||||
await socketClient.stop();
|
||||
} catch {
|
||||
// ignore disconnect errors
|
||||
}
|
||||
socketClient = null;
|
||||
}
|
||||
}
|
||||
|
||||
// Combined refresh action for efficient polling
|
||||
async function dispatchCombinedRefreshAction() {
|
||||
const context = getActionContext();
|
||||
@@ -1237,9 +1286,21 @@ let currentRefreshRate = 1000; // Track current refresh rate to avoid unnecessar
|
||||
if (state.isLoggedIn !== previousIsLoggedIn) {
|
||||
previousIsLoggedIn = state.isLoggedIn;
|
||||
startAutoRefresh();
|
||||
|
||||
// Connect/disconnect TypedSocket based on login state
|
||||
if (state.isLoggedIn) {
|
||||
connectSocket();
|
||||
} else {
|
||||
disconnectSocket();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Initial start
|
||||
startAutoRefresh();
|
||||
|
||||
// Connect TypedSocket if already logged in (e.g., persistent session)
|
||||
if (loginStatePart.getState().isLoggedIn) {
|
||||
connectSocket();
|
||||
}
|
||||
})();
|
||||
Reference in New Issue
Block a user