mirror of
https://github.com/legop3/MultiRoombaRover.git
synced 2026-09-15 17:12:59 -04:00
make logs opt-in and remove them from /
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -12,7 +12,7 @@
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
|
||||
<meta name="apple-mobile-web-app-title" content="Roomba Rover" />
|
||||
<title>Roomba Rover</title>
|
||||
<script type="module" crossorigin src="/assets/index-D0FgC_A-.js"></script>
|
||||
<script type="module" crossorigin src="/assets/index-CiUVS_ut.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-BVKa8Zph.css">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
@@ -7,6 +7,7 @@ const loggerRoot = require('../../globals/logger');
|
||||
const logger = loggerRoot.child('logStream');
|
||||
|
||||
const MAX_HISTORY = 200;
|
||||
const LOG_ROOM = 'log:subscribers';
|
||||
const history = [];
|
||||
|
||||
function pushEntry(entry) {
|
||||
@@ -17,11 +18,22 @@ function pushEntry(entry) {
|
||||
}
|
||||
|
||||
function broadcast(entry) {
|
||||
io.emit('log:entry', entry);
|
||||
/*
|
||||
The raw server log stream can produce dozens of socket messages per second.
|
||||
Sending those messages only to sockets that joined the diagnostic log room
|
||||
keeps ordinary driver pages from spending network, parsing, and session-store
|
||||
work on logs they never render.
|
||||
*/
|
||||
io.to(LOG_ROOM).emit('log:entry', entry);
|
||||
}
|
||||
|
||||
function hydrateSocket(socket) {
|
||||
if (!socket) return;
|
||||
/*
|
||||
Hydration is tied to an explicit subscription instead of connection startup.
|
||||
This preserves the existing "latest 200 logs" operator view while avoiding
|
||||
a large initial payload for pages that do not mount the log panel.
|
||||
*/
|
||||
socket.emit('log:init', history);
|
||||
}
|
||||
|
||||
@@ -38,6 +50,23 @@ loggerRoot.registerSink(({ level, label, message, timestamp }) => {
|
||||
});
|
||||
|
||||
io.on('connection', (socket) => {
|
||||
logger.info('Hydrating log history for', socket.id);
|
||||
hydrateSocket(socket);
|
||||
socket.on('log:subscribe', () => {
|
||||
/*
|
||||
Joining before hydration means a log emitted during the same event loop
|
||||
turn cannot be missed between "send history" and "start live stream".
|
||||
A duplicate edge entry is less harmful than a hidden gap in diagnostics,
|
||||
and entries have stable ids for React keys if that ever occurs.
|
||||
*/
|
||||
socket.join(LOG_ROOM);
|
||||
hydrateSocket(socket);
|
||||
});
|
||||
|
||||
socket.on('log:unsubscribe', () => {
|
||||
/*
|
||||
Leaving the room is enough to stop future log entries. The retained server
|
||||
history remains global so the next subscriber can still hydrate from the
|
||||
same rolling diagnostic buffer.
|
||||
*/
|
||||
socket.leave(LOG_ROOM);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -15,7 +15,6 @@ import {
|
||||
} from './controls/index.js';
|
||||
import RoomCameraPanel from './components/RoomCameraPanel/index.jsx';
|
||||
import KinectPanel from './components/KinectPanel/index.jsx';
|
||||
import LogPanel from './components/LogPanel/index.jsx';
|
||||
import DriverVideo from './components/DriverVideo/index.jsx';
|
||||
import RightPaneTabs from './components/RightPaneTabs/index.jsx';
|
||||
import ModeGateOverlay from './components/ModeGateOverlay/index.jsx';
|
||||
@@ -82,7 +81,6 @@ function DesktopLayout({ layout, onOpenHelpOverlay }) {
|
||||
<DriverVideo />
|
||||
<PiHostStatsCard />
|
||||
<TelemetryPanel />
|
||||
{/* <LogPanel /> */}
|
||||
</div>
|
||||
<div className={`flex min-w-0 flex-1 flex-col ${themeGapClass} overflow-y-auto`}>
|
||||
<GlobalObjectiveBanner layout={layout} />
|
||||
@@ -174,7 +172,6 @@ function MobileFeatureTabs({
|
||||
<TabPanel id="settings">
|
||||
<div className={themeStackClass}>
|
||||
<SettingsPanel />
|
||||
<LogPanel />
|
||||
</div>
|
||||
</TabPanel>
|
||||
</TabPanels>
|
||||
|
||||
@@ -2,12 +2,45 @@
|
||||
// Purpose: Defines the Log Panel module and the local helpers/components used in this file.
|
||||
// Scope: Keeps behavior unchanged while isolating this concern into a clear, single-responsibility unit.
|
||||
import { useSessionSelector } from '../../context/SessionContext.jsx';
|
||||
import { useMemo } from 'react';
|
||||
import { useEffect, useMemo } from 'react';
|
||||
import { useSocket } from '../../context/SocketContext.jsx';
|
||||
import CardFrame from '../CardFrame/index.jsx';
|
||||
|
||||
export default function LogPanel() {
|
||||
const socket = useSocket();
|
||||
const logs = useSessionSelector((state) => state.logs);
|
||||
const rendered = useMemo(() => logs.slice().reverse(), [logs]);
|
||||
|
||||
useEffect(() => {
|
||||
const subscribe = () => {
|
||||
socket.emit('log:subscribe');
|
||||
};
|
||||
|
||||
/*
|
||||
Server logs are noisy enough that receiving them globally can make normal
|
||||
driving views pay for a diagnostic tool they are not using. The panel owns
|
||||
the subscription because it is the visible consumer: when a route or tab
|
||||
unmounts this component, the server can stop sending log traffic to this
|
||||
browser entirely instead of merely hiding the rendered rows.
|
||||
|
||||
The connect listener matters because Socket.IO rooms are attached to the
|
||||
current server-side socket instance. A reconnect gives the browser a fresh
|
||||
room membership, so the mounted panel must ask for the log room again.
|
||||
*/
|
||||
subscribe();
|
||||
socket.on('connect', subscribe);
|
||||
|
||||
return () => {
|
||||
/*
|
||||
Unsubscribing on unmount keeps inactive tab panels and non-log routes
|
||||
from continuing to receive high-volume log entries after the operator
|
||||
has navigated away from the diagnostic view.
|
||||
*/
|
||||
socket.off('connect', subscribe);
|
||||
socket.emit('log:unsubscribe');
|
||||
};
|
||||
}, [socket]);
|
||||
|
||||
return (
|
||||
<CardFrame title="Server logs" bodyClassName="space-y-0.5 text-base">
|
||||
<div className="surface h-64 overflow-y-auto font-mono text-xs">
|
||||
|
||||
Reference in New Issue
Block a user