Pipe winston logs to dashboard + add Matrix sniff debug route
The dashboard's /api/logs buffer only ever saw lines explicitly pushed via broadcaster.push, so winston output (including the Matrix token-extractor's timeout diagnostics) was invisible from the deployed container. Attach a winston transport that forwards every entry into the LogBroadcaster before the rest of bootstrap runs, so the matrix sniff's `finalUrl=... hosts=[...]` line shows up in /api/logs. Also serve data/matrix-debug.png (the screenshot the extractor drops on timeout) at /api/debug/matrix-debug.png so we can see what chat.reddit.com looked like in the headed browser without shell access to the Dokploy host. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
1 parent
705d88dca1
commit
2bf8989ec7
4 files changed
+74
-2
No files matched your search
@@ -1,7 +1,41 @@
|
||||
import winston from 'winston';
|
||||
import Transport from 'winston-transport';
|
||||
|
||||
export type Logger = winston.Logger;
|
||||
|
||||
export interface LogSink {
|
||||
push(level: 'info' | 'warn' | 'error' | 'debug', message: string, data?: unknown): void;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attaches a sink (typically the dashboard's LogBroadcaster) as a winston
|
||||
* transport so every `logger.info/warn/error/debug` call also lands in the
|
||||
* dashboard's `/api/logs` buffer. Call once, as early in bootstrap as
|
||||
* possible — anything logged before this point won't be visible in the UI.
|
||||
*/
|
||||
export function attachLogSink(logger: Logger, sink: LogSink): void {
|
||||
class SinkTransport extends Transport {
|
||||
log(info: Record<string, unknown>, callback: () => void): void {
|
||||
setImmediate(() => this.emit('logged', info));
|
||||
const level = (info.level as string) || 'info';
|
||||
const allowed = ['info', 'warn', 'error', 'debug'] as const;
|
||||
const lvl = (allowed as readonly string[]).includes(level)
|
||||
? (level as 'info' | 'warn' | 'error' | 'debug')
|
||||
: 'info';
|
||||
const message = String(info.message ?? '');
|
||||
const { level: _l, message: _m, timestamp: _t, ...meta } = info;
|
||||
const hasMeta = Object.keys(meta).length > 0;
|
||||
try {
|
||||
sink.push(lvl, message, hasMeta ? meta : undefined);
|
||||
} catch {
|
||||
// never let the sink break logging
|
||||
}
|
||||
callback();
|
||||
}
|
||||
}
|
||||
logger.add(new SinkTransport({ level: 'debug' }));
|
||||
}
|
||||
|
||||
function safeStringify(value: unknown): string {
|
||||
const seen = new WeakSet<object>();
|
||||
try {
|
||||
|
||||
Reference in new issue
Block a user