Loggers.kt
- package com.hexagontk.core
- import com.hexagontk.core.text.stripAnsi
- import java.lang.System.Logger
- import java.lang.System.Logger.Level
- import java.lang.System.Logger.Level.*
- import kotlin.reflect.KClass
- const val HEXAGONTK_LOGGING_COLOR = "hexagontk_logging_color"
- const val HEXAGONTK_LOGGING_LOGGER_NAME = "hexagontk_logging_logger_name"
- internal val useColor: Boolean by lazy { Platform.systemFlag(HEXAGONTK_LOGGING_COLOR) }
- internal val defaultLoggerName: String by lazy {
- Platform.systemSetting(HEXAGONTK_LOGGING_LOGGER_NAME, "com.hexagontk.core.logging")
- }
- /** Default logger for when you feel too lazy to declare one. */
- val logger: Logger by lazy { loggerOf(defaultLoggerName) }
- /**
- * Use this [T] to log a message with a prefix using [TRACE] level.
- *
- * [com.hexagontk.core.logger] must have the [TRACE] level enabled.
- *
- * @receiver Object which string representation will be logged.
- * @param T Type of the logged object.
- * @param prefix Prefix for the logging message.
- * @return The receiver reference for chaining methods.
- */
- fun <T> T.trace(prefix: String = ""): T =
- apply { logger.trace { "$prefix$this" } }
- /**
- * Use this [T] to log a message with a prefix using [DEBUG] level.
- *
- * [com.hexagontk.core.logger] must have the [DEBUG] level enabled.
- *
- * @receiver Object which string representation will be logged.
- * @param T Type of the logged object.
- * @param prefix Prefix for the logging message.
- * @return The receiver reference for chaining methods.
- */
- fun <T> T.debug(prefix: String = ""): T =
- apply { logger.debug { "$prefix$this" } }
- /**
- * Use this [T] to log a message with a prefix using [INFO] level.
- *
- * [com.hexagontk.core.logger] must have the [INFO] level enabled.
- *
- * @receiver Object which string representation will be logged.
- * @param T Type of the logged object.
- * @param prefix Prefix for the logging message.
- * @return The receiver reference for chaining methods.
- */
- fun <T> T.info(prefix: String = ""): T =
- apply { logger.info { "$prefix$this" } }
- /**
- * Logger constructor function.
- *
- * @param type Logger type. It is shown in the logs messages and used for log filtering.
- */
- fun loggerOf(type: KClass<*>): Logger =
- loggerOf(type.qualifiedName ?: error("Cannot get qualified name of type"))
- /**
- * Logger constructor function.
- *
- * @param name Logger name. It is shown in the logs messages and used for log filtering.
- */
- fun loggerOf(name: String): Logger =
- System.getLogger(name)
- /**
- * 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> Logger.log(level: Level, exception: E, message: (E) -> Any?) {
- val messageSupplier = { stripAnsi(message(exception), useColor) }
- log(level, messageSupplier, exception)
- }
- /**
- * Log a message using [TRACE] level.
- *
- * @param message The required message to log.
- */
- fun Logger.trace(message: () -> Any?) {
- logMessage(TRACE, message)
- }
- /**
- * Log a message using [DEBUG] level.
- *
- * @param message The required message to log.
- */
- fun Logger.debug(message: () -> Any?) {
- logMessage(DEBUG, message)
- }
- /**
- * Log a message using [INFO] level.
- *
- * @param message The required message to log.
- */
- fun Logger.info(message: () -> Any?) {
- logMessage(INFO, message)
- }
- /**
- * Log a message using [WARNING] level.
- *
- * @param message The required message to log.
- */
- fun Logger.warn(message: () -> Any?) {
- logMessage(WARNING, message)
- }
- /**
- * Log a message using [ERROR] level.
- *
- * @param message The required message to log.
- */
- fun Logger.error(message: () -> Any?) {
- logMessage(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> Logger.warn(exception: E?, message: (E?) -> Any? = { "" }) {
- if (exception == null) log(WARNING) { message(null)?.toString() }
- 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> Logger.error(exception: E?, message: (E?) -> Any? = { "" }) {
- if (exception == null) log(ERROR) { message(null)?.toString() }
- else log(ERROR, exception, message)
- }
- internal fun <T> stripAnsi(receiver: T?, apply: Boolean): String? =
- receiver?.toString()?.let { if (apply) it.stripAnsi() else it }
- private fun Logger.logMessage(level: Level, message: () -> Any?) {
- val messageSupplier = { stripAnsi(message(), !useColor) }
- log(level, messageSupplier)
- }