Logger.kt
package com.hexagonkt.core.logging
import com.hexagonkt.core.text.stripAnsi
import java.lang.System.Logger.Level
import java.lang.System.Logger.Level.*
import kotlin.reflect.KClass
/**
* Logger class with Kotlin usability improvements. It is backed by a [System.Logger] instance.
*
* @param name Logger name. It is shown in the logs messages and used for log filtering.
* @sample com.hexagonkt.core.logging.LoggerTest.loggerUsage
*/
class Logger(
val name: String,
internal val logger: System.Logger = System.getLogger(name)
) {
/**
* Logger class with Kotlin improvements like lazy evaluation.
*
* @param type Logger type. It is shown in the logs messages and used for log filtering.
*/
constructor(type: KClass<*>):
this(type.qualifiedName ?: error("Cannot get qualified name of type"))
/**
* Check if this logger is enabled for a given log level.
*
* @param level Level to check.
* @return True if this logger is enabled for the supplied level.
*/
fun isLoggable(level: Level): Boolean =
logger.isLoggable(level)
/**
* Log a message, with associated exception information.
*
* @param level Level used in the log statement.
* @param exception The exception associated with log message.
* @param message The message supplier to use in the log statement.
*/
fun <E : Throwable> log(level: Level, exception: E, message: (E) -> Any?) {
val messageSupplier = { stripAnsi(message(exception), useColor) }
logger.log(level, messageSupplier, exception)
}
/**
* Log a message.
*
* @param level Level used in the log statement.
* @param message The message supplier to use in the log statement.
*/
fun log(level: Level, message: () -> Any?) {
val messageSupplier = { stripAnsi(message(), useColor) }
logger.log(level, messageSupplier)
}
/**
* Log a message using [TRACE] level.
*
* @param message The required message to log.
*/
fun trace(message: () -> Any?) {
log(TRACE, message)
}
/**
* Log a message using [DEBUG] level.
*
* @param message The required message to log.
*/
fun debug(message: () -> Any?) {
log(DEBUG, message)
}
/**
* Log a message using [INFO] level.
*
* @param message The required message to log.
*/
fun info(message: () -> Any?) {
log(INFO, message)
}
/**
* Log a message using [WARNING] level.
*
* @param message The required message to log.
*/
fun warn(message: () -> Any?) {
log(WARNING, message)
}
/**
* Log a message using [ERROR] level.
*
* @param message The required message to log.
*/
fun error(message: () -> Any?) {
log(ERROR, message)
}
/**
* Log a message using [WARNING] level with associated exception information.
*
* @param exception The exception associated with log message.
* @param message The message to log (optional). If not supplied it will be empty.
*/
fun <E : Throwable> warn(exception: E?, message: (E?) -> Any? = { "" }) {
if (exception == null) log(WARNING) { message(null) }
else log(WARNING, exception, message)
}
/**
* Log a message using [ERROR] level with associated exception information.
*
* @param exception The exception associated with log message.
* @param message The message to log (function to optional). If not supplied it will be empty.
*/
fun <E : Throwable> error(exception: E?, message: (E?) -> Any? = { "" }) {
if (exception == null) log(ERROR) { message(null) }
else log(ERROR, exception, message)
}
internal fun <T> stripAnsi(receiver: T?, apply: Boolean): String? =
receiver?.toString()?.let { if (apply) it.stripAnsi() else it }
}