feat(opsserver): add real-time log push to ops dashboard and recent DNS query tracking

This commit is contained in:
2026-02-21 14:02:48 +00:00
parent 1337a4905a
commit ffc93eb9d3
16 changed files with 203 additions and 22 deletions

View File

@@ -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();
}
})();