TypeScript: いい感じのシンプルな Logger クラス

TypeScript: いい感じのシンプルな Logger クラス

ロギング用の外部ライブラリを使うまでもないんだよなぁ、というときにちょうどいい感じのシンプルな Logger クラスをどうぞ。

export class Logger {
  static get start(): InlineLogger {
    return new InlineLogger();
  }

  static info(...data: any[]): void {
    Logger.start.info(...data);
  }

  static error(...data: any[]): void {
    Logger.start.error(...data);
  }
}

class InlineLogger {
  private static config = {
    info: {
      log: (...data: any[]) => console.info(...data),
      prefix: "[INFO]",
    },
    error: {
      log: (...data: any[]) => console.error(...data),
      prefix: "[ERROR]",
    },
  } as const;

  private messageBuffer: string[] = [];

  private dataToString(data: any[]): string {
    return data
      .flat()
      .map((d) => String(d))
      .join(" ");
  }

  private flush(
    severity: keyof typeof InlineLogger.config,
    ...data: any[]
  ): void {
    const message = [...this.messageBuffer];
    if (data.length > 0) {
      message.push(this.dataToString(data));
    }
    if (message.length === 0) {
      return;
    }
    const { log, prefix } = InlineLogger.config[severity];
    const messageBody = message.join(" | ");
    log(`${prefix} ${messageBody}`);
  }

  add(...data: any[]): this {
    const message = this.dataToString(data);
    this.messageBuffer.push(message);
    return this;
  }

  info(...data: any[]): void {
    this.flush("info", ...data);
  }

  error(...data: any[]): void {
    this.flush("error", ...data);
  }
}

こんな感じで使えます。

import { Logger } from "./logger";

const logger = Logger.start;

logger.info("HELLO"); // [INFO] HELLO
logger.error("HELLO"); // [ERROR] HELLO

logger.add("WORLD");

logger.info(); // [INFO] HELLO | WORLD
logger.error(); // [ERROR] HELLO | WORLD

logger.info("SUCCESS"); // [INFO] HELLO | WORLD | SUCCESS
logger.error("FAILURE"); // [ERROR] HELLO | WORLD | FAILURE