aboutsummaryrefslogtreecommitdiff
path: root/src/main/scala/xyz/driver/core/logging/DriverLayout.scala
blob: 5e6c7df93b208682a7c436b4fdc52ec012504b68 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
package xyz.driver.core
package logging

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

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)
      )
    }
  }
}