'use strict'; /** * Minimal server-side logging - plain stdout lines, no logging library. * This app runs as a single Docker container watched via `docker logs`/ * journalctl (see README's Deploying section), not behind a log * aggregator, so a consistent prefix + timestamp is what actually makes * these greppable in practice, not structured JSON nobody's parsing. * * Static methods rather than a singleton instance: there's no state here * at all (unlike PartyService/MusicQueueService, which really do own * something) - a class is just a namespace for these two, kept as a class * for consistency with the rest of server/src/services' shape. */ export class Logger { /** * Party business-lifecycle events - created/joined/left/destroyed, host * handoff, queue advance, playstate transitions, pause/skip requests. * Deliberately covers only that, not connection-level noise like every * Socket.IO reconnect or the 3s playstate heartbeat re-sending the same * state (see SocketGateway, which only calls this on an actual * play/pause transition, not every heartbeat tick). */ static party(message: string): void { console.log(`[watchparty:party] ${new Date().toISOString()} ${message}`); } /** * The streaming route specifically (CatalogService's /master.m3u8 * handler) - a different concern from the party lifecycle above (it's * about one HTTP request, not party state). Deliberately logs only the * individual override values it cares about, never the full resolved * URL or params blob - Emby's own TranscodingUrl can carry an api_key, * and that has no business ending up in a log file. */ static stream(message: string): void { console.log(`[watchparty:stream] ${new Date().toISOString()} ${message}`); } /** `"name(id)"` - the same shape in every party lifecycle log line. */ static who(userId: string, userName: string): string { return `${userName}(${userId})`; } /** * Emby answering anything but success, to any proxied call - see * EmbyClient.fetch, the one place every Emby request goes through. * Added after several rounds of chasing a real error message through * browser devtools and Emby's own live log view (see docs/architecture.md's * player-track-selection section): Emby often sends back a real, * detailed text body on a failure, which neither of those reliably * surfaced - this puts it directly in `docker logs` instead, from now on. */ static emby(message: string): void { console.log(`[watchparty:emby] ${new Date().toISOString()} ${message}`); } }