aboutsummaryrefslogblamecommitdiff
path: root/src/main/scala/xyz/driver/core/logging.scala
blob: c8fb6aeadee6318e27529a4aacb183035fb89925 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
                       
 





                                               

                       

                






























                                                                      






                                                                                              

                                                                                            


































                                                                                                       

   
                                  
 



                                                                           
                                                                           
                                                                           
 



                                                                           
                                                                           
                                                                           
 



                                                                           
                                                                           
                                                                           
 



                                                                           
                                                                           
                                                                           
   



                                                        



                                                                                                                       


                                                                  


                                                                                                    
                                                                                             










                                                                                                                      
                                                               
















                                                                                                   
                                                                                                                



         
 
package xyz.driver.core

import java.text.SimpleDateFormat
import java.util.Date

import ch.qos.logback.classic.spi.ILoggingEvent
import ch.qos.logback.core.LayoutBase
import org.apache.commons.lang3.StringUtils
import org.slf4j.Marker

object logging {

  trait Logger {

    def fatal(message: String): Unit
    def fatal(message: String, cause: Throwable): Unit
    def fatal(message: String, args: AnyRef*): Unit
    def fatal(marker: Marker, message: String): Unit
    def fatal(marker: Marker, message: String, cause: Throwable): Unit
    def fatal(marker: Marker, message: String, args: AnyRef*): Unit

    def error(message: String): Unit
    def error(message: String, cause: Throwable): Unit
    def error(message: String, args: AnyRef*): Unit
    def error(marker: Marker, message: String): Unit
    def error(marker: Marker, message: String, cause: Throwable): Unit
    def error(marker: Marker, message: String, args: AnyRef*): Unit

    def audit(message: String): Unit
    def audit(message: String, cause: Throwable): Unit
    def audit(message: String, args: AnyRef*): Unit
    def audit(marker: Marker, message: String): Unit
    def audit(marker: Marker, message: String, cause: Throwable): Unit
    def audit(marker: Marker, message: String, args: AnyRef*): Unit

    def debug(message: String): Unit
    def debug(message: String, cause: Throwable): Unit
    def debug(message: String, args: AnyRef*): Unit
    def debug(marker: Marker, message: String): Unit
    def debug(marker: Marker, message: String, cause: Throwable): Unit
    def debug(marker: Marker, message: String, args: AnyRef*): Unit
  }

  /**
    * Logger implementation which uses `com.typesafe.scalalogging.Logger` on the back.
    * It redefines the meaning of logging levels to fit to the Driver infrastructure design,
    * and as using error and warn, debug and trace was always confusing and mostly done wrong.
    *
    * @param scalaLogging com.typesafe.scalalogging.Logger which logging will be delegated to
    */
  class TypesafeScalaLogger(scalaLogging: com.typesafe.scalalogging.Logger) extends Logger {

    def fatal(message: String): Unit                   = scalaLogging.error("FATAL " + message)
    def fatal(message: String, cause: Throwable): Unit = scalaLogging.error("FATAL " + message, cause)
    def fatal(message: String, args: AnyRef*): Unit    = scalaLogging.error("FATAL " + message, args)
    def fatal(marker: Marker, message: String): Unit   = scalaLogging.error(marker, "FATAL " + message)
    def fatal(marker: Marker, message: String, cause: Throwable): Unit =
      scalaLogging.error(marker, "FATAL " + message, cause)
    def fatal(marker: Marker, message: String, args: AnyRef*): Unit =
      scalaLogging.error(marker, "FATAL " + message, args)

    def error(message: String): Unit                   = scalaLogging.warn("ERROR " + message)
    def error(message: String, cause: Throwable): Unit = scalaLogging.warn("ERROR " + message, cause)
    def error(message: String, args: AnyRef*): Unit    = scalaLogging.warn("ERROR " + message, args)
    def error(marker: Marker, message: String): Unit   = scalaLogging.warn(marker, "ERROR " + message)
    def error(marker: Marker, message: String, cause: Throwable): Unit =
      scalaLogging.warn(marker, "ERROR " + message, cause)
    def error(marker: Marker, message: String, args: AnyRef*): Unit =
      scalaLogging.warn(marker, "ERROR " + message, args)

    def audit(message: String): Unit                   = scalaLogging.info("AUDIT " + message)
    def audit(message: String, cause: Throwable): Unit = scalaLogging.info("AUDIT " + message, cause)
    def audit(message: String, args: AnyRef*): Unit    = scalaLogging.info("AUDIT " + message, args)
    def audit(marker: Marker, message: String): Unit   = scalaLogging.info(marker, "AUDIT " + message)
    def audit(marker: Marker, message: String, cause: Throwable): Unit =
      scalaLogging.info(marker, "AUDIT " + message, cause)
    def audit(marker: Marker, message: String, args: AnyRef*): Unit =
      scalaLogging.info(marker, "AUDIT " + message, args)

    def debug(message: String): Unit                   = scalaLogging.debug("DEBUG " + message)
    def debug(message: String, cause: Throwable): Unit = scalaLogging.debug("DEBUG " + message, cause)
    def debug(message: String, args: AnyRef*): Unit    = scalaLogging.debug("DEBUG " + message, args)
    def debug(marker: Marker, message: String): Unit   = scalaLogging.debug(marker, "DEBUG " + message)
    def debug(marker: Marker, message: String, cause: Throwable): Unit =
      scalaLogging.debug(marker, "DEBUG " + message, cause)
    def debug(marker: Marker, message: String, args: AnyRef*): Unit =
      scalaLogging.debug(marker, "DEBUG " + message, args)
  }

  object NoLogger extends Logger {

    def fatal(message: String): Unit                                   = {}
    def fatal(message: String, cause: Throwable): Unit                 = {}
    def fatal(message: String, args: AnyRef*): Unit                    = {}
    def fatal(marker: Marker, message: String): Unit                   = {}
    def fatal(marker: Marker, message: String, cause: Throwable): Unit = {}
    def fatal(marker: Marker, message: String, args: AnyRef*): Unit    = {}

    def error(message: String): Unit                                   = {}
    def error(message: String, cause: Throwable): Unit                 = {}
    def error(message: String, args: AnyRef*): Unit                    = {}
    def error(marker: Marker, message: String): Unit                   = {}
    def error(marker: Marker, message: String, cause: Throwable): Unit = {}
    def error(marker: Marker, message: String, args: AnyRef*): Unit    = {}

    def audit(message: String): Unit                                   = {}
    def audit(message: String, cause: Throwable): Unit                 = {}
    def audit(message: String, args: AnyRef*): Unit                    = {}
    def audit(marker: Marker, message: String): Unit                   = {}
    def audit(marker: Marker, message: String, cause: Throwable): Unit = {}
    def audit(marker: Marker, message: String, args: AnyRef*): Unit    = {}

    def debug(message: String): Unit                                   = {}
    def debug(message: String, cause: Throwable): Unit                 = {}
    def debug(message: String, args: AnyRef*): Unit                    = {}
    def debug(marker: Marker, message: String): Unit                   = {}
    def debug(marker: Marker, message: String, cause: Throwable): Unit = {}
    def debug(marker: Marker, message: String, args: AnyRef*): Unit    = {}
  }

  class DriverLayout extends LayoutBase[ILoggingEvent] {
    import scala.collection.JavaConverters._

    private val FieldSeparator        = "="
    private val DateFormatString      = "MM/dd/yyyy HH:mm:ss"
    private val newline               = System.getProperty("line.separator")
    private val IgnoredClassesInStack = Set("org.apache.catalina", "org.apache.coyote", "sun.reflect", "javax.servlet")

    override def doLayout(loggingEvent: ILoggingEvent): String = {

      val date  = new SimpleDateFormat(DateFormatString).format(new Date(loggingEvent.getTimeStamp))
      val level = StringUtils.rightPad(loggingEvent.getLevel.toString, 5)

      val message = new StringBuilder(s"$date [$level] - ${loggingEvent.getMessage}$newline")

      logContext(message, loggingEvent)

      Option(loggingEvent.getCallerData) foreach { stacktrace =>
        val stacktraceLength = stacktrace.length

        if (stacktraceLength > 0) {
          val location = stacktrace.head

          val _ = message
            .append(s"Location: ${location.getClassName}.${location.getMethodName}:${location.getLineNumber}$newline")
            .append(s"Exception: ${location.toString}$newline")

          if (stacktraceLength > 1) {
            message.append(stacktrace.tail.filterNot { e =>
              IgnoredClassesInStack.forall(ignored => !e.getClassName.startsWith(ignored))
            } map {
              _.toString
            } mkString newline)
          }
        }
      }

      message.toString
    }

    private def logContext(message: StringBuilder, loggingEvent: ILoggingEvent) = {
      Option(loggingEvent.getMDCPropertyMap).map(_.asScala).filter(_.nonEmpty).foreach { context =>
        message.append(
          context map { case (key, value) => s"$key$FieldSeparator$value" } mkString ("Context: ", " ", newline)
        )
      }
    }
  }
}