You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
70 lines
2.4 KiB
70 lines
2.4 KiB
import type { LogEntry, LogLevel, Logger } from '../logger.js';
|
|
|
|
/** A `LogEntry` tagged with where it came from, for display in `DebugPanel.svelte`. */
|
|
export interface DisplayLogEntry extends LogEntry {
|
|
source: 'client' | 'server';
|
|
}
|
|
|
|
const MAX_ENTRIES = 500;
|
|
|
|
let entries: DisplayLogEntry[] = [];
|
|
const subscribers = new Set<(entries: DisplayLogEntry[]) => void>();
|
|
|
|
function notify(): void {
|
|
for (const run of subscribers) run(entries);
|
|
}
|
|
|
|
function push(entry: DisplayLogEntry): void {
|
|
entries = entries.length >= MAX_ENTRIES ? [...entries.slice(1), entry] : [...entries, entry];
|
|
notify();
|
|
}
|
|
|
|
/**
|
|
* Feeds a server-forwarded `debug.log` entry into the same shared buffer the
|
|
* panel renders. Not for direct use by app code — call `clientLogger` for
|
|
* anything happening in the browser itself; this is exported specifically
|
|
* for `server-log-forwarder.ts`.
|
|
*/
|
|
export function pushLogEntry(entry: LogEntry, source: DisplayLogEntry['source'] = 'server'): void {
|
|
push({ ...entry, source });
|
|
}
|
|
|
|
function log(level: LogLevel, category: string, message: string, data?: unknown): void {
|
|
if (data === undefined) {
|
|
console[level](`[${category}] ${message}`);
|
|
} else {
|
|
console[level](`[${category}] ${message}`, data);
|
|
}
|
|
push({ level, category, message, data, timestamp: Date.now(), source: 'client' });
|
|
}
|
|
|
|
/**
|
|
* Ambient client-side logger — any browser code (with or without a realtime
|
|
* connection) can call this directly, e.g. `clientLogger.warn('ws', ...)`.
|
|
* Feeds the same shared buffer `DebugPanel.svelte` renders.
|
|
*/
|
|
export const clientLogger: Logger = {
|
|
debug: (category, message, data) => log('debug', category, message, data),
|
|
info: (category, message, data) => log('info', category, message, data),
|
|
warn: (category, message, data) => log('warn', category, message, data),
|
|
error: (category, message, data) => log('error', category, message, data)
|
|
};
|
|
|
|
/**
|
|
* Read-only, Svelte-store-compatible view of the shared log buffer (client
|
|
* entries plus anything forwarded from the server) — hand-rolled the same
|
|
* way as `$lib/client/humanoid/avatar-state.ts`'s `deriveAvatarState`; no
|
|
* `svelte/store` import anywhere in this repo, and this doesn't start one.
|
|
*/
|
|
export const debugLogStore = {
|
|
subscribe(run: (entries: DisplayLogEntry[]) => void): () => void {
|
|
subscribers.add(run);
|
|
run(entries);
|
|
return () => subscribers.delete(run);
|
|
}
|
|
};
|
|
|
|
export function clearLogs(): void {
|
|
entries = [];
|
|
notify();
|
|
}
|
|
|