std/log/base_handler.ts
Asher Gomez e9716720b6
docs(log): document BaseHandler (#6067)
* docs(log): document `BaseHandler`

* fix

* fix
2024-09-27 12:31:58 +09:00

378 lines
9.5 KiB
TypeScript

// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
// This module is browser compatible.
import {
getLevelByName,
getLevelName,
type LevelName,
type LogLevel,
} from "./levels.ts";
import type { LogRecord } from "./logger.ts";
export type { LevelName, LogLevel, LogRecord };
/**
* A function type that defines the structure of a formatter function.
*
* @param logRecord The log record that needs to be formatted.
* @returns A string representation of the log record.
*/
export type FormatterFunction = (logRecord: LogRecord) => string;
const DEFAULT_FORMATTER: FormatterFunction = ({ levelName, msg }) =>
`${levelName} ${msg}`;
/** Options for {@linkcode BaseHandler}. */
export interface BaseHandlerOptions {
/** A function that formats log records. */
formatter?: FormatterFunction;
}
/**
* A base class for all log handlers.
*
* This class is abstract and should not be instantiated directly. Instead, it
* should be extended by other classes that implement the `log` method.
*
* @example Usage
* ```ts
* import { BaseHandler } from "@std/log/base-handler";
* import { assertInstanceOf } from "@std/assert/instance-of";
*
* class MyHandler extends BaseHandler {
* log(msg: string) {
* console.log(msg);
* }
* }
*
* const handler = new MyHandler("INFO");
* assertInstanceOf(handler, BaseHandler);
* ```
*/
export abstract class BaseHandler {
#levelName: LevelName;
#level: LogLevel;
/**
* The function that formats log records.
*
* @example Usage
* ```ts
* import { BaseHandler } from "@std/log/base-handler";
* import { LogRecord } from "@std/log/logger";
* import { LogLevels } from "@std/log/levels";
* import { assertEquals } from "@std/assert/equals";
*
* class MyHandler extends BaseHandler {
* log(msg: string) {
* console.log(msg);
* }
* }
*
* const handler = new MyHandler("INFO");
* const record = new LogRecord({
* msg: "Hello, world!",
* args: ["foo", "bar"],
* level: LogLevels.INFO,
* loggerName: "example",
* });
* const formatted = handler.formatter(record);
* assertEquals(formatted, "INFO Hello, world!");
* ```
*/
formatter: FormatterFunction;
/**
* Constructs a new instance.
*
* @param levelName The name of the log level to handle.
* @param options Options for the handler.
*/
constructor(
levelName: LevelName,
options?: BaseHandlerOptions,
) {
const { formatter = DEFAULT_FORMATTER } = options ?? {};
this.#levelName = levelName;
this.#level = getLevelByName(levelName);
this.formatter = formatter;
}
/**
* Getter for the log level that this handler will handle.
*
* @example Usage
* ```ts
* import { BaseHandler } from "@std/log/base-handler";
* import { LogLevels } from "@std/log/levels";
* import { assertEquals } from "@std/assert/equals";
*
* class MyHandler extends BaseHandler {
* log(msg: string) {
* console.log(msg);
* }
* }
*
* const handler = new MyHandler("INFO");
* assertEquals(handler.level, LogLevels.INFO);
* ```
*
* @returns The log level to handle.
*/
get level(): LogLevel {
return this.#level;
}
/**
* Setter for the log level that this handler will handle.
*
* @example Usage
* ```ts
* import { BaseHandler } from "@std/log/base-handler";
* import { LogLevels } from "@std/log/levels";
* import { assertEquals } from "@std/assert/equals";
*
* class MyHandler extends BaseHandler {
* log(msg: string) {
* console.log(msg);
* }
* }
*
* const handler = new MyHandler("INFO");
* handler.level = LogLevels.DEBUG;
* assertEquals(handler.level, LogLevels.DEBUG);
* ```
*
* @param level The log level to handle.
*/
set level(level: LogLevel) {
this.#level = level;
this.#levelName = getLevelName(level);
}
/**
* Getter for the name of the log level that this handler will handle.
*
* @example Usage
* ```ts
* import { BaseHandler } from "@std/log/base-handler";
* import { assertEquals } from "@std/assert/equals";
*
* class MyHandler extends BaseHandler {
* log(msg: string) {
* console.log(msg);
* }
* }
*
* const handler = new MyHandler("INFO");
* assertEquals(handler.levelName, "INFO");
* ```
*
* @returns The name of the log level to handle.
*/
get levelName(): LevelName {
return this.#levelName;
}
/**
* Setter for the name of the log level that this handler will handle.
*
* @param levelName The name of the log level to handle.
*
* @example Usage
* ```ts
* import { BaseHandler } from "@std/log/base-handler";
* import { assertEquals } from "@std/assert/equals";
*
* class MyHandler extends BaseHandler {
* log(msg: string) {
* console.log(msg);
* }
* }
*
* const handler = new MyHandler("INFO");
* handler.levelName = "DEBUG";
* assertEquals(handler.levelName, "DEBUG");
* ```
*/
set levelName(levelName: LevelName) {
this.#levelName = levelName;
this.#level = getLevelByName(levelName);
}
/**
* Handles a log record.
*
* @param logRecord The log record to handle.
*
* @example Usage
* ```ts
* import { BaseHandler } from "@std/log/base-handler";
* import { LogRecord } from "@std/log/logger";
* import { LogLevels } from "@std/log/levels";
* import { assertInstanceOf } from "@std/assert/instance-of";
*
* class MyHandler extends BaseHandler {
* log(msg: string) {
* console.log(msg);
* }
* }
*
* const handler = new MyHandler("INFO");
* const record = new LogRecord({
* msg: "Hello, world!",
* args: ["foo", "bar"],
* level: LogLevels.INFO,
* loggerName: "example",
* });
* handler.handle(record);
*
* assertInstanceOf(handler, BaseHandler);
* ```
*/
handle(logRecord: LogRecord) {
if (this.level > logRecord.level) return;
const msg = this.format(logRecord);
this.log(msg);
}
/**
* Formats a log record.
*
* @param logRecord The log record to format.
* @returns A string representation of the log record.
*
* @example Usage
* ```ts
* import { BaseHandler } from "@std/log/base-handler";
* import { LogRecord } from "@std/log/logger";
* import { LogLevels } from "@std/log/levels";
* import { assertEquals } from "@std/assert/equals";
*
* class MyHandler extends BaseHandler {
* log(msg: string) {
* console.log(msg);
* }
* }
*
* const handler = new MyHandler("INFO");
* const record = new LogRecord({
* msg: "Hello, world!",
* args: ["foo", "bar"],
* level: LogLevels.INFO,
* loggerName: "example",
* });
* const formatted = handler.format(record);
* assertEquals(formatted, "INFO Hello, world!");
* ```
*/
format(logRecord: LogRecord): string {
return this.formatter(logRecord);
}
/**
* Logs a message.
*
* This method should be implemented by subclasses to handle the log record.
*
* @param msg The message to log.
*
* @example Usage
* ```ts
* import { BaseHandler } from "@std/log/base-handler";
* import { assertInstanceOf } from "@std/assert/instance-of";
*
* class MyHandler extends BaseHandler {
* log(msg: string) {
* console.log(msg);
* }
* }
*
* const handler = new MyHandler("INFO");
* handler.log("Hello, world!"); // Prints "Hello, world!"
*
* assertInstanceOf(handler, BaseHandler);
* ```
*/
abstract log(msg: string): void;
/**
* Initializes the handler.
*
* This method is called when the handler is added to a logger. It can be
* used to perform any setup that is required by the handler.
*
* @example Usage
* ```ts
* import { BaseHandler } from "@std/log/base-handler";
* import { assertInstanceOf } from "@std/assert/instance-of";
*
* class MyHandler extends BaseHandler {
* log(msg: string) {
* console.log(msg);
* }
*
* override setup() {
* console.log("Handler setup!");
* }
* }
*
* const handler = new MyHandler("INFO");
* handler.setup(); // Prints "Handler setup!"
*
* assertInstanceOf(handler, BaseHandler);
* ```
*/
setup() {}
/**
* Destroys the handler, performing any cleanup that is required.
*
* This method is called when the handler is removed from a logger. It can be
* used to perform any cleanup that is required by the handler.
*
* @example Usage
* ```ts
* import { BaseHandler } from "@std/log/base-handler";
* import { assertInstanceOf } from "@std/assert/instance-of";
*
* class MyHandler extends BaseHandler {
* log(msg: string) {
* console.log(msg);
* }
*
* override destroy() {
* console.log("Handler destroyed!");
* }
* }
*
* const handler = new MyHandler("INFO");
* handler.destroy(); // Prints "Handler destroyed!"
* assertInstanceOf(handler, BaseHandler);
* ```
*/
destroy() {}
/**
* Automatically disposes of the handler when instantiated with the `using`
* keyword by calling the {@linkcode BaseHandler.destroy} method.
*
* @example Usage
* ```ts
* import { BaseHandler } from "@std/log/base-handler";
* import { LogRecord } from "@std/log/logger";
* import { assertInstanceOf } from "@std/assert/instance-of";
*
* class MyHandler extends BaseHandler {
* log(msg: string) {
* console.log(msg);
* }
* }
*
* using handler = new MyHandler("INFO");
* assertInstanceOf(handler, BaseHandler);
* ```
*/
[Symbol.dispose]() {
this.destroy();
}
}