import * as path from "@std/path"; function generateTimeStringForFileName( instant?: Temporal.Instant | Date, ): string { if (instant == null) { instant = Temporal.Now.instant(); } else if (instant instanceof Date) { instant = instant.toTemporalInstant(); } return instant.toString().replaceAll(/:|\./g, "-"); } export class Logger { constructor(public readonly path: string) {} warn(message: string) { console.log(message); } generateLogFilePath( prefix: string = "", suffix: string = "", instant?: Temporal.Instant | Date, ): string { return path.join( this.path, `${prefix}-${generateTimeStringForFileName(instant)}-${suffix}`, ); } openLogFile( prefix: string = "", suffix: string = "", instant?: Temporal.Instant | Date, ): Promise { const logPath = this.generateLogFilePath(prefix, suffix, instant); return Deno.open(logPath, { read: false, write: true, append: true, create: true, }); } async logProgramOutput( process: Deno.ChildProcess, program: string, instant?: Temporal.Instant | Date, ): Promise { const stdoutFile = await this.openLogFile(program, "stdout", instant); const stderrFile = await this.openLogFile(program, "stderr", instant); process.stdout.pipeTo(stdoutFile.writable); process.stderr.pipeTo(stderrFile.writable); } } let _logger: Logger | null = null; export function getLogger(): Logger { if (_logger == null) { throw new Error("No logger is set now."); } return _logger; } export function setLogger(logger: Logger | null) { _logger = logger; }