|
|
|
|
@ -5,9 +5,9 @@ import type { WebSocket } from 'ws'
|
|
|
|
|
* _terminal Routes
|
|
|
|
|
*
|
|
|
|
|
* The websocket behind the admin area's terminal view, which streams this instance's log lines to a
|
|
|
|
|
* browser as they are written. Read-only: nothing a client sends is looked at, and the socket carries
|
|
|
|
|
* exactly what `core/logger.ts` hands to `console.log`, formatted string and all — including the ANSI
|
|
|
|
|
* colours, which xterm renders.
|
|
|
|
|
* browser as they are written. Read-only: nothing a client sends is looked at, and every frame after
|
|
|
|
|
* the first is exactly what `core/logger.ts` hands to `console.log`, formatted string and all —
|
|
|
|
|
* including the ANSI colours, which xterm renders. The first frame is the handshake below.
|
|
|
|
|
*
|
|
|
|
|
* Only this instance's own main thread is on that stream. Worker threads build their own logger
|
|
|
|
|
* (`worker.ts`), and other instances write to their own consoles, so a clustered deployment shows the
|
|
|
|
|
@ -43,6 +43,15 @@ async function routes(app: FastifyInstance) {
|
|
|
|
|
return socket.close(4403, 'You are not allowed to read the server logs')
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const user = req.session.user?.email ?? req.session.user?.id ?? 'unknown'
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Logged before the listener is attached, so the line is already in the backlog by the time it
|
|
|
|
|
is replayed below and the terminal opens on its own arrival. Every other connected terminal
|
|
|
|
|
sees it live, which is the point: who is reading the logs is itself worth logging.
|
|
|
|
|
*/
|
|
|
|
|
WIKI.logger.info(`Streaming server logs to user ${user}... [ CONNECTED ]`)
|
|
|
|
|
|
|
|
|
|
const send = (line: string) => {
|
|
|
|
|
if (socket.readyState !== socket.OPEN || socket.bufferedAmount > MAX_BUFFERED) {
|
|
|
|
|
return
|
|
|
|
|
@ -50,6 +59,14 @@ async function routes(app: FastifyInstance) {
|
|
|
|
|
socket.send(line)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
The handshake, and the only frame that is not a log line: which instance the client ended up
|
|
|
|
|
talking to, since in a cluster that is the one thing the logs themselves cannot tell it — a
|
|
|
|
|
line names the instance that WROTE it, and the backlog replayed below was written by this one.
|
|
|
|
|
Sent before anything else, so "the first frame" is all the client has to know to find it.
|
|
|
|
|
*/
|
|
|
|
|
socket.send(JSON.stringify({ instance: WIKI.INSTANCE_ID }))
|
|
|
|
|
|
|
|
|
|
// -> A terminal that opens onto an idle server would otherwise sit empty and look broken
|
|
|
|
|
for (const line of WIKI.logger.backlog()) {
|
|
|
|
|
send(line)
|
|
|
|
|
@ -57,7 +74,12 @@ async function routes(app: FastifyInstance) {
|
|
|
|
|
|
|
|
|
|
WIKI.logger.ws.on('log', send)
|
|
|
|
|
socket.on('close', () => {
|
|
|
|
|
// -> Off the stream first, so this instance's own goodbye is not sent down a socket that is
|
|
|
|
|
// already closing
|
|
|
|
|
WIKI.logger.ws.off('log', send)
|
|
|
|
|
WIKI.logger.info(
|
|
|
|
|
`User ${user} has disconnected from server logs streaming. [ DISCONNECTED ]`
|
|
|
|
|
)
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
|