Add log diagnostic context
[dcaegen2/collectors/hv-ves.git] / sources / hv-collector-utils / src / main / kotlin / org / onap / dcae / collectors / veshv / utils / logging / Logger.kt
index 033dd5e..2fb4880 100644 (file)
@@ -21,117 +21,171 @@ package org.onap.dcae.collectors.veshv.utils.logging
 
 import kotlin.reflect.KClass
 import org.slf4j.LoggerFactory
+import org.slf4j.MDC
+
+typealias MappedDiagnosticContext = () -> Map<String, String>
 
 @Suppress("TooManyFunctions", "SuboptimalLoggerUsage")
-class Logger(val logger: org.slf4j.Logger) {
+class Logger(logger: org.slf4j.Logger) {
     constructor(clazz: KClass<out Any>) : this(LoggerFactory.getLogger(clazz.java))
     constructor(name: String) : this(LoggerFactory.getLogger(name))
 
-    //
-    // TRACE
-    //
+    private val errorLogger = if (logger.isErrorEnabled) ErrorLevelLogger(logger) else OffLevelLogger
+    private val warnLogger = if (logger.isWarnEnabled) WarnLevelLogger(logger) else OffLevelLogger
+    private val infoLogger = if (logger.isInfoEnabled) InfoLevelLogger(logger) else OffLevelLogger
+    private val debugLogger = if (logger.isDebugEnabled) DebugLevelLogger(logger) else OffLevelLogger
+    private val traceLogger = if (logger.isTraceEnabled) TraceLevelLogger(logger) else OffLevelLogger
 
-    val traceEnabled: Boolean
-        get() = logger.isTraceEnabled
+    // ERROR
 
-    fun trace(messageProvider: () -> String) {
-        if (logger.isTraceEnabled) {
-            logger.trace(messageProvider())
-        }
-    }
+    fun withError(block: AtLevelLogger.() -> Unit) = errorLogger.block()
 
-    //
-    // DEBUG
-    //
+    fun withError(mdc: MappedDiagnosticContext, block: AtLevelLogger.() -> Unit) =
+            errorLogger.withMdc(mdc, block)
 
-    fun debug(message: String) {
-        logger.debug(message)
+    fun error(message: () -> String) = errorLogger.run {
+        log(message())
     }
 
-    fun debug(message: String, t: Throwable) {
-        logger.debug(message, t)
+    fun error(mdc: MappedDiagnosticContext, message: () -> String) =
+            errorLogger.withMdc(mdc) { log(message()) }
+
+    // WARN
+
+    fun withWarn(block: AtLevelLogger.() -> Unit) = warnLogger.block()
+
+    fun withWarn(mdc: MappedDiagnosticContext, block: AtLevelLogger.() -> Unit) =
+            warnLogger.withMdc(mdc, block)
+
+    fun warn(message: () -> String) = warnLogger.run {
+        log(message())
     }
 
-    fun debug(messageProvider: () -> String) {
-        if (logger.isDebugEnabled) {
-            logger.debug(messageProvider())
-        }
+    fun warn(mdc: MappedDiagnosticContext, message: () -> String) =
+            warnLogger.withMdc(mdc) { log(message()) }
+
+
+    // INFO
+
+    fun withInfo(block: AtLevelLogger.() -> Unit) = infoLogger.block()
+
+    fun withInfo(mdc: MappedDiagnosticContext, block: AtLevelLogger.() -> Unit) =
+            infoLogger.withMdc(mdc, block)
+
+    fun info(message: () -> String) = infoLogger.run {
+        log(message())
     }
 
-    fun debug(t: Throwable, messageProvider: () -> String) {
-        if (logger.isDebugEnabled) {
-            logger.debug(messageProvider(), t)
-        }
+    fun info(mdc: MappedDiagnosticContext, message: () -> String) =
+            infoLogger.withMdc(mdc) { log(message()) }
+
+    // DEBUG
+
+    fun withDebug(block: AtLevelLogger.() -> Unit) = debugLogger.block()
+
+    fun withDebug(mdc: MappedDiagnosticContext, block: AtLevelLogger.() -> Unit) =
+            debugLogger.withMdc(mdc, block)
+
+    fun debug(message: () -> String) = debugLogger.run {
+        log(message())
     }
 
-    //
-    // INFO
-    //
-    fun info(message: String) {
-        logger.info(message)
+    fun debug(mdc: MappedDiagnosticContext, message: () -> String) =
+            debugLogger.withMdc(mdc) { log(message()) }
+
+
+    // TRACE
+
+    fun withTrace(block: AtLevelLogger.() -> Unit) = traceLogger.block()
+
+    fun withTrace(mdc: MappedDiagnosticContext, block: AtLevelLogger.() -> Unit) =
+            traceLogger.withMdc(mdc, block)
+
+    fun trace(message: () -> String) = traceLogger.run {
+        log(message())
     }
 
-    fun info(messageProvider: () -> String) {
-        if (logger.isInfoEnabled) {
-            logger.info(messageProvider())
+    fun trace(mdc: MappedDiagnosticContext, message: () -> String) =
+            traceLogger.withMdc(mdc) { log(message()) }
+
+}
+
+abstract class AtLevelLogger {
+    abstract fun log(message: String)
+    abstract fun log(message: String, t: Throwable)
+    open val enabled: Boolean
+        get() = true
+
+    inline fun withMdc(mdc: MappedDiagnosticContext, block: AtLevelLogger.() -> Unit) {
+        if (enabled) {
+            try {
+                MDC.setContextMap(mdc())
+                block()
+            } finally {
+                MDC.clear()
+            }
         }
     }
+}
 
-    fun info(message: String, t: Throwable) {
-        logger.info(message, t)
+object OffLevelLogger : AtLevelLogger() {
+    override val enabled = false
+
+    override fun log(message: String) {
+        // do not log anything
     }
 
-    fun info(t: Throwable, messageProvider: () -> String) {
-        if (logger.isInfoEnabled) {
-            logger.info(messageProvider(), t)
-        }
+    override fun log(message: String, t: Throwable) {
+        // do not log anything
     }
+}
 
-    //
-    // WARN
-    //
+class ErrorLevelLogger(private val logger: org.slf4j.Logger) : AtLevelLogger() {
+    override fun log(message: String) {
+        logger.error(message)
+    }
+
+    override fun log(message: String, t: Throwable) {
+        logger.error(message, t)
+    }
+}
 
-    fun warn(message: String) {
+class WarnLevelLogger(private val logger: org.slf4j.Logger) : AtLevelLogger() {
+    override fun log(message: String) {
         logger.warn(message)
     }
 
-    fun warn(message: String, t: Throwable) {
+    override fun log(message: String, t: Throwable) {
         logger.warn(message, t)
     }
+}
 
-    fun warn(messageProvider: () -> String) {
-        if (logger.isWarnEnabled) {
-            logger.warn(messageProvider())
-        }
+class InfoLevelLogger(private val logger: org.slf4j.Logger) : AtLevelLogger() {
+    override fun log(message: String) {
+        logger.info(message)
     }
 
-    fun warn(t: Throwable, messageProvider: () -> String) {
-        if (logger.isWarnEnabled) {
-            logger.warn(messageProvider(), t)
-        }
+    override fun log(message: String, t: Throwable) {
+        logger.info(message, t)
     }
+}
 
-    //
-    // ERROR
-    //
-
-    fun error(message: String) {
-        logger.error(message)
+class DebugLevelLogger(private val logger: org.slf4j.Logger) : AtLevelLogger() {
+    override fun log(message: String) {
+        logger.debug(message)
     }
 
-    fun error(message: String, t: Throwable) {
-        logger.error(message, t)
+    override fun log(message: String, t: Throwable) {
+        logger.debug(message, t)
     }
+}
 
-    fun error(messageProvider: () -> String) {
-        if (logger.isErrorEnabled) {
-            logger.error(messageProvider())
-        }
+class TraceLevelLogger(private val logger: org.slf4j.Logger) : AtLevelLogger() {
+    override fun log(message: String) {
+        logger.trace(message)
     }
 
-    fun error(t: Throwable, messageProvider: () -> String) {
-        if (logger.isErrorEnabled) {
-            logger.error(messageProvider(), t)
-        }
+    override fun log(message: String, t: Throwable) {
+        logger.trace(message, t)
     }
 }