/** * @since 2.0.0 * * The `LogLevel` module provides utilities for managing log levels in Effect applications. * It defines a hierarchy of log levels and provides functions for comparing and filtering logs * based on their severity. * * ## Log Level Hierarchy * * The log levels are ordered from most severe to least severe: * * 1. **All** - Special level that allows all messages * 2. **Fatal** - System is unusable, immediate attention required * 3. **Error** - Error conditions that should be investigated * 4. **Warn** - Warning conditions that may indicate problems * 5. **Info** - Informational messages about normal operation * 6. **Debug** - Debug information useful during development * 7. **Trace** - Very detailed trace information * 8. **None** - Special level that suppresses all messages * * ## Basic Usage * * ```ts * import { Effect } from "effect" * * // Basic log level usage * const program = Effect.gen(function*() { * yield* Effect.logFatal("System is shutting down") * yield* Effect.logError("Database connection failed") * yield* Effect.logWarning("Memory usage is high") * yield* Effect.logInfo("User logged in") * yield* Effect.logDebug("Processing request") * yield* Effect.logTrace("Variable value: xyz") * }) * ``` * * ## Level Comparison * * ```ts * import { LogLevel } from "effect" * * // Check if one level is more severe than another * console.log(LogLevel.isGreaterThan("Error", "Info")) // true * console.log(LogLevel.isGreaterThan("Debug", "Error")) // false * * // Check if level meets minimum threshold * console.log(LogLevel.isGreaterThanOrEqualTo("Info", "Debug")) // true * console.log(LogLevel.isLessThan("Trace", "Info")) // true * ``` * * ## Filtering by Level * * ```ts * import { Logger, LogLevel } from "effect" * * // Create a logger that only logs Error and above * const errorLogger = Logger.make((options) => { * if (LogLevel.isGreaterThanOrEqualTo(options.logLevel, "Error")) { * console.log(`[${options.logLevel}] ${options.message}`) * } * }) * * // Production logger - Info and above * const productionLogger = Logger.make((options) => { * if (LogLevel.isGreaterThanOrEqualTo(options.logLevel, "Info")) { * console.log( * `${options.date.toISOString()} [${options.logLevel}] ${options.message}` * ) * } * }) * * // Development logger - Debug and above * const devLogger = Logger.make((options) => { * if (LogLevel.isGreaterThanOrEqualTo(options.logLevel, "Debug")) { * console.log(`[${options.logLevel}] ${options.message}`) * } * }) * ``` * * ## Runtime Configuration * * ```ts * import { Config, Effect, Logger, LogLevel } from "effect" * * // Configure log level from environment * const logLevelConfig = Config.string("LOG_LEVEL").pipe( * Config.withDefault("Info") * ) * * const configurableLogger = Effect.gen(function*() { * const minLevel = yield* logLevelConfig * * return Logger.make((options) => { * if (LogLevel.isGreaterThanOrEqualTo(options.logLevel, minLevel)) { * console.log(`[${options.logLevel}] ${options.message}`) * } * }) * }) * ``` */ import type * as Effect from "./Effect.ts" import * as Equ from "./Equivalence.ts" import * as core from "./internal/core.ts" import * as effect from "./internal/effect.ts" import * as Ord from "./Order.ts" import * as References from "./References.ts" /** * Represents the severity level of a log message. * * The levels are ordered from most severe to least severe: * - `All` - Special level that allows all messages * - `Fatal` - System is unusable, immediate attention required * - `Error` - Error conditions that should be investigated * - `Warn` - Warning conditions that may indicate problems * - `Info` - Informational messages about normal operation * - `Debug` - Debug information useful during development * - `Trace` - Very detailed trace information * - `None` - Special level that suppresses all messages * * @example * ```ts * import { Effect } from "effect" * * // Using log levels with Effect logging * const program = Effect.gen(function*() { * yield* Effect.logFatal("System failure") * yield* Effect.logError("Database error") * yield* Effect.logWarning("High memory usage") * yield* Effect.logInfo("User logged in") * yield* Effect.logDebug("Processing request") * yield* Effect.logTrace("Variable state") * }) * * // Type-safe log level variables * const errorLevel = "Error" // LogLevel * const debugLevel = "Debug" // LogLevel * ``` * * @since 4.0.0 * @category models */ export type LogLevel = "All" | "Fatal" | "Error" | "Warn" | "Info" | "Debug" | "Trace" | "None" /** * @since 4.0.0 * @category models */ export type Severity = "Fatal" | "Error" | "Warn" | "Info" | "Debug" | "Trace" /** * @since 4.0.0 * @category models */ export const values: ReadonlyArray = ["All", "Fatal", "Error", "Warn", "Info", "Debug", "Trace", "None"] /** * An `Order` instance for `LogLevel` that defines the severity ordering. * * This order treats "All" as the least restrictive level and "None" as the most restrictive, * with Fatal being the most severe actual log level. * * @example * ```ts * import { LogLevel } from "effect" * * // Compare log levels using Order * console.log(LogLevel.Order("Error", "Info")) // 1 (Error > Info) * console.log(LogLevel.Order("Debug", "Error")) // -1 (Debug < Error) * console.log(LogLevel.Order("Info", "Info")) // 0 (Info == Info) * ``` * * @since 2.0.0 * @category ordering */ export const Order: Ord.Order = effect.LogLevelOrder /** * An `Equivalence` instance for log levels using strict equality (`===`). * * @example * ```ts * import { LogLevel } from "effect" * * console.log(LogLevel.Equivalence("Error", "Error")) // true * console.log(LogLevel.Equivalence("Error", "Info")) // false * ``` * * @category instances * @since 4.0.0 */ export const Equivalence: Equ.Equivalence = Equ.strictEqual() /** * Returns the ordinal value of the log level. * * @since 4.0.0 * @category ordering */ export const getOrdinal = (self: LogLevel): number => effect.logLevelToOrder(self) /** * Determines if the first log level is more severe than the second. * * Returns `true` if `self` represents a more severe level than `that`. * This is useful for filtering logs based on minimum severity requirements. * * @example * ```ts * import { LogLevel } from "effect" * * // Check if Error is more severe than Info * console.log(LogLevel.isGreaterThan("Error", "Info")) // true * console.log(LogLevel.isGreaterThan("Debug", "Error")) // false * * // Use with filtering * const isFatal = LogLevel.isGreaterThan("Fatal", "Warn") * const isError = LogLevel.isGreaterThan("Error", "Warn") * const isDebug = LogLevel.isGreaterThan("Debug", "Warn") * console.log(isFatal) // true * console.log(isError) // true * console.log(isDebug) // false * * // Curried usage * const isMoreSevereThanInfo = LogLevel.isGreaterThan("Info") * console.log(isMoreSevereThanInfo("Error")) // true * console.log(isMoreSevereThanInfo("Debug")) // false * ``` * * @since 2.0.0 * @category ordering */ export const isGreaterThan: { /** * Determines if the first log level is more severe than the second. * * Returns `true` if `self` represents a more severe level than `that`. * This is useful for filtering logs based on minimum severity requirements. * * @example * ```ts * import { LogLevel } from "effect" * * // Check if Error is more severe than Info * console.log(LogLevel.isGreaterThan("Error", "Info")) // true * console.log(LogLevel.isGreaterThan("Debug", "Error")) // false * * // Use with filtering * const isFatal = LogLevel.isGreaterThan("Fatal", "Warn") * const isError = LogLevel.isGreaterThan("Error", "Warn") * const isDebug = LogLevel.isGreaterThan("Debug", "Warn") * console.log(isFatal) // true * console.log(isError) // true * console.log(isDebug) // false * * // Curried usage * const isMoreSevereThanInfo = LogLevel.isGreaterThan("Info") * console.log(isMoreSevereThanInfo("Error")) // true * console.log(isMoreSevereThanInfo("Debug")) // false * ``` * * @since 2.0.0 * @category ordering */ (that: LogLevel): (self: LogLevel) => boolean /** * Determines if the first log level is more severe than the second. * * Returns `true` if `self` represents a more severe level than `that`. * This is useful for filtering logs based on minimum severity requirements. * * @example * ```ts * import { LogLevel } from "effect" * * // Check if Error is more severe than Info * console.log(LogLevel.isGreaterThan("Error", "Info")) // true * console.log(LogLevel.isGreaterThan("Debug", "Error")) // false * * // Use with filtering * const isFatal = LogLevel.isGreaterThan("Fatal", "Warn") * const isError = LogLevel.isGreaterThan("Error", "Warn") * const isDebug = LogLevel.isGreaterThan("Debug", "Warn") * console.log(isFatal) // true * console.log(isError) // true * console.log(isDebug) // false * * // Curried usage * const isMoreSevereThanInfo = LogLevel.isGreaterThan("Info") * console.log(isMoreSevereThanInfo("Error")) // true * console.log(isMoreSevereThanInfo("Debug")) // false * ``` * * @since 2.0.0 * @category ordering */ (self: LogLevel, that: LogLevel): boolean } = effect.isLogLevelGreaterThan /** * Determines if the first log level is more severe than or equal to the second. * * Returns `true` if `self` represents a level that is more severe than or equal to `that`. * This is the most common function for implementing minimum log level filtering. * * @example * ```ts * import { Logger, LogLevel } from "effect" * * // Check if level meets minimum threshold * console.log(LogLevel.isGreaterThanOrEqualTo("Error", "Error")) // true * console.log(LogLevel.isGreaterThanOrEqualTo("Error", "Info")) // true * console.log(LogLevel.isGreaterThanOrEqualTo("Debug", "Info")) // false * * // Create a logger that only logs Info and above * const infoLogger = Logger.make((options) => { * if (LogLevel.isGreaterThanOrEqualTo(options.logLevel, "Info")) { * console.log(`[${options.logLevel}] ${options.message}`) * } * }) * * // Production logger - only Error and Fatal * const productionLogger = Logger.make((options) => { * if (LogLevel.isGreaterThanOrEqualTo(options.logLevel, "Error")) { * console.error( * `${options.date.toISOString()} [${options.logLevel}] ${options.message}` * ) * } * }) * * // Curried usage for filtering * const isInfoOrAbove = LogLevel.isGreaterThanOrEqualTo("Info") * const shouldLog = isInfoOrAbove("Error") // true * ``` * * @since 2.0.0 * @category ordering */ export const isGreaterThanOrEqualTo: { /** * Determines if the first log level is more severe than or equal to the second. * * Returns `true` if `self` represents a level that is more severe than or equal to `that`. * This is the most common function for implementing minimum log level filtering. * * @example * ```ts * import { Logger, LogLevel } from "effect" * * // Check if level meets minimum threshold * console.log(LogLevel.isGreaterThanOrEqualTo("Error", "Error")) // true * console.log(LogLevel.isGreaterThanOrEqualTo("Error", "Info")) // true * console.log(LogLevel.isGreaterThanOrEqualTo("Debug", "Info")) // false * * // Create a logger that only logs Info and above * const infoLogger = Logger.make((options) => { * if (LogLevel.isGreaterThanOrEqualTo(options.logLevel, "Info")) { * console.log(`[${options.logLevel}] ${options.message}`) * } * }) * * // Production logger - only Error and Fatal * const productionLogger = Logger.make((options) => { * if (LogLevel.isGreaterThanOrEqualTo(options.logLevel, "Error")) { * console.error( * `${options.date.toISOString()} [${options.logLevel}] ${options.message}` * ) * } * }) * * // Curried usage for filtering * const isInfoOrAbove = LogLevel.isGreaterThanOrEqualTo("Info") * const shouldLog = isInfoOrAbove("Error") // true * ``` * * @since 2.0.0 * @category ordering */ (that: LogLevel): (self: LogLevel) => boolean /** * Determines if the first log level is more severe than or equal to the second. * * Returns `true` if `self` represents a level that is more severe than or equal to `that`. * This is the most common function for implementing minimum log level filtering. * * @example * ```ts * import { Logger, LogLevel } from "effect" * * // Check if level meets minimum threshold * console.log(LogLevel.isGreaterThanOrEqualTo("Error", "Error")) // true * console.log(LogLevel.isGreaterThanOrEqualTo("Error", "Info")) // true * console.log(LogLevel.isGreaterThanOrEqualTo("Debug", "Info")) // false * * // Create a logger that only logs Info and above * const infoLogger = Logger.make((options) => { * if (LogLevel.isGreaterThanOrEqualTo(options.logLevel, "Info")) { * console.log(`[${options.logLevel}] ${options.message}`) * } * }) * * // Production logger - only Error and Fatal * const productionLogger = Logger.make((options) => { * if (LogLevel.isGreaterThanOrEqualTo(options.logLevel, "Error")) { * console.error( * `${options.date.toISOString()} [${options.logLevel}] ${options.message}` * ) * } * }) * * // Curried usage for filtering * const isInfoOrAbove = LogLevel.isGreaterThanOrEqualTo("Info") * const shouldLog = isInfoOrAbove("Error") // true * ``` * * @since 2.0.0 * @category ordering */ (self: LogLevel, that: LogLevel): boolean } = Ord.isGreaterThanOrEqualTo(Order) /** * Determines if the first log level is less severe than the second. * * Returns `true` if `self` represents a less severe level than `that`. * This is useful for filtering out logs that are too verbose. * * @example * ```ts * import { LogLevel } from "effect" * * // Check if Debug is less severe than Info * console.log(LogLevel.isLessThan("Debug", "Info")) // true * console.log(LogLevel.isLessThan("Error", "Info")) // false * * // Filter out verbose logs * const isFatalVerbose = LogLevel.isLessThan("Fatal", "Info") * const isErrorVerbose = LogLevel.isLessThan("Error", "Info") * const isTraceVerbose = LogLevel.isLessThan("Trace", "Info") * console.log(isFatalVerbose) // false (Fatal is not verbose) * console.log(isErrorVerbose) // false (Error is not verbose) * console.log(isTraceVerbose) // true (Trace is verbose) * * // Curried usage * const isLessSevereThanError = LogLevel.isLessThan("Error") * console.log(isLessSevereThanError("Info")) // true * console.log(isLessSevereThanError("Fatal")) // false * ``` * * @since 2.0.0 * @category ordering */ export const isLessThan: { /** * Determines if the first log level is less severe than the second. * * Returns `true` if `self` represents a less severe level than `that`. * This is useful for filtering out logs that are too verbose. * * @example * ```ts * import { LogLevel } from "effect" * * // Check if Debug is less severe than Info * console.log(LogLevel.isLessThan("Debug", "Info")) // true * console.log(LogLevel.isLessThan("Error", "Info")) // false * * // Filter out verbose logs * const isFatalVerbose = LogLevel.isLessThan("Fatal", "Info") * const isErrorVerbose = LogLevel.isLessThan("Error", "Info") * const isTraceVerbose = LogLevel.isLessThan("Trace", "Info") * console.log(isFatalVerbose) // false (Fatal is not verbose) * console.log(isErrorVerbose) // false (Error is not verbose) * console.log(isTraceVerbose) // true (Trace is verbose) * * // Curried usage * const isLessSevereThanError = LogLevel.isLessThan("Error") * console.log(isLessSevereThanError("Info")) // true * console.log(isLessSevereThanError("Fatal")) // false * ``` * * @since 2.0.0 * @category ordering */ (that: LogLevel): (self: LogLevel) => boolean /** * Determines if the first log level is less severe than the second. * * Returns `true` if `self` represents a less severe level than `that`. * This is useful for filtering out logs that are too verbose. * * @example * ```ts * import { LogLevel } from "effect" * * // Check if Debug is less severe than Info * console.log(LogLevel.isLessThan("Debug", "Info")) // true * console.log(LogLevel.isLessThan("Error", "Info")) // false * * // Filter out verbose logs * const isFatalVerbose = LogLevel.isLessThan("Fatal", "Info") * const isErrorVerbose = LogLevel.isLessThan("Error", "Info") * const isTraceVerbose = LogLevel.isLessThan("Trace", "Info") * console.log(isFatalVerbose) // false (Fatal is not verbose) * console.log(isErrorVerbose) // false (Error is not verbose) * console.log(isTraceVerbose) // true (Trace is verbose) * * // Curried usage * const isLessSevereThanError = LogLevel.isLessThan("Error") * console.log(isLessSevereThanError("Info")) // true * console.log(isLessSevereThanError("Fatal")) // false * ``` * * @since 2.0.0 * @category ordering */ (self: LogLevel, that: LogLevel): boolean } = Ord.isLessThan(Order) /** * Determines if the first log level is less severe than or equal to the second. * * Returns `true` if `self` represents a level that is less severe than or equal to `that`. * This is useful for implementing maximum log level filtering. * * @example * ```ts * import { Logger, LogLevel } from "effect" * * // Check if level is at or below threshold * console.log(LogLevel.isLessThanOrEqualTo("Info", "Info")) // true * console.log(LogLevel.isLessThanOrEqualTo("Debug", "Info")) // true * console.log(LogLevel.isLessThanOrEqualTo("Error", "Info")) // false * * // Create a logger that suppresses verbose logs * const quietLogger = Logger.make((options) => { * if (LogLevel.isLessThanOrEqualTo(options.logLevel, "Info")) { * console.log(`[${options.logLevel}] ${options.message}`) * } * }) * * // Development logger - suppress trace logs * const devLogger = Logger.make((options) => { * if (LogLevel.isLessThanOrEqualTo(options.logLevel, "Debug")) { * console.log(`[${options.logLevel}] ${options.message}`) * } * }) * * // Curried usage for filtering * const isInfoOrBelow = LogLevel.isLessThanOrEqualTo("Info") * const shouldLog = isInfoOrBelow("Debug") // true * ``` * * @since 2.0.0 * @category ordering */ export const isLessThanOrEqualTo: { /** * Determines if the first log level is less severe than or equal to the second. * * Returns `true` if `self` represents a level that is less severe than or equal to `that`. * This is useful for implementing maximum log level filtering. * * @example * ```ts * import { Logger, LogLevel } from "effect" * * // Check if level is at or below threshold * console.log(LogLevel.isLessThanOrEqualTo("Info", "Info")) // true * console.log(LogLevel.isLessThanOrEqualTo("Debug", "Info")) // true * console.log(LogLevel.isLessThanOrEqualTo("Error", "Info")) // false * * // Create a logger that suppresses verbose logs * const quietLogger = Logger.make((options) => { * if (LogLevel.isLessThanOrEqualTo(options.logLevel, "Info")) { * console.log(`[${options.logLevel}] ${options.message}`) * } * }) * * // Development logger - suppress trace logs * const devLogger = Logger.make((options) => { * if (LogLevel.isLessThanOrEqualTo(options.logLevel, "Debug")) { * console.log(`[${options.logLevel}] ${options.message}`) * } * }) * * // Curried usage for filtering * const isInfoOrBelow = LogLevel.isLessThanOrEqualTo("Info") * const shouldLog = isInfoOrBelow("Debug") // true * ``` * * @since 2.0.0 * @category ordering */ (that: LogLevel): (self: LogLevel) => boolean /** * Determines if the first log level is less severe than or equal to the second. * * Returns `true` if `self` represents a level that is less severe than or equal to `that`. * This is useful for implementing maximum log level filtering. * * @example * ```ts * import { Logger, LogLevel } from "effect" * * // Check if level is at or below threshold * console.log(LogLevel.isLessThanOrEqualTo("Info", "Info")) // true * console.log(LogLevel.isLessThanOrEqualTo("Debug", "Info")) // true * console.log(LogLevel.isLessThanOrEqualTo("Error", "Info")) // false * * // Create a logger that suppresses verbose logs * const quietLogger = Logger.make((options) => { * if (LogLevel.isLessThanOrEqualTo(options.logLevel, "Info")) { * console.log(`[${options.logLevel}] ${options.message}`) * } * }) * * // Development logger - suppress trace logs * const devLogger = Logger.make((options) => { * if (LogLevel.isLessThanOrEqualTo(options.logLevel, "Debug")) { * console.log(`[${options.logLevel}] ${options.message}`) * } * }) * * // Curried usage for filtering * const isInfoOrBelow = LogLevel.isLessThanOrEqualTo("Info") * const shouldLog = isInfoOrBelow("Debug") // true * ``` * * @since 2.0.0 * @category ordering */ (self: LogLevel, that: LogLevel): boolean } = Ord.isLessThanOrEqualTo(Order) /** * Checks whether a given log level is enabled for the current fiber. * * A log level is enabled when it is greater than or equal to * `References.MinimumLogLevel`. * * @example * ```ts * import { Effect, LogLevel, References } from "effect" * * const program = Effect.gen(function*() { * const debugEnabled = yield* LogLevel.isEnabled("Debug") * const errorEnabled = yield* LogLevel.isEnabled("Error") * * console.log({ debugEnabled, errorEnabled }) * }) * * const warnOnly = program.pipe( * Effect.provideService(References.MinimumLogLevel, "Warn") * ) * ``` * * @since 4.0.0 * @category filtering */ export const isEnabled = (self: LogLevel): Effect.Effect => core.withFiber((fiber) => effect.succeed(!isGreaterThan(fiber.getRef(References.MinimumLogLevel), self)))