Skip to content

Instantly share code, notes, and snippets.

@petitviolet
Created May 12, 2018 14:50
Show Gist options
  • Save petitviolet/c171e3e1b6e397169077c7bc1a10fd41 to your computer and use it in GitHub Desktop.
Save petitviolet/c171e3e1b6e397169077c7bc1a10fd41 to your computer and use it in GitHub Desktop.
import org.slf4j.LoggerFactory
trait LoggerProvider {
protected lazy val logger = new xLogger(this.getClass.getName)
}
private object xLogger {
def apply(name: String): xLogger = new xLogger(name)
}
class xLogger private (name: String) {
private lazy val logger = LoggerFactory.getLogger(name)
private lazy val isDebugEnabled: Boolean = logger.isDebugEnabled
def debugStackTrace(t: => Throwable) = {
if (isDebugEnabled) {
logger.debug("---------------------")
logger.debug(t.getStackTrace.mkString("\n"))
logger.debug("---------------------")
}
}
def debug(msg: => String): Unit =
if (isDebugEnabled) {
logger.debug(msg)
}
def info(msg: => String): Unit =
if (logger.isInfoEnabled) logger.info(msg)
def warn(msg: => String): Unit =
if (logger.isWarnEnabled) logger.warn(msg)
/**
* [[Throwable]]をstack trace出さずにある程度詳細なメッセージを出すための関数
* @param depth メッセージに載せるStackTraceの掘る深さ
* @return
*/
private def throwableMsg(t: Throwable, depth: Int): String = {
@annotation.tailrec
def loop(t: Throwable, stacks: List[String] = Nil): List[String] = {
def getCause(t: Throwable): String = {
val trace = t.getStackTrace
.take(depth)
.map { x =>
s"${x.getFileName}:${x.getLineNumber}"
}
.mkString(" -> ")
s"${t.getMessage} => $trace"
}
Option(t) match {
case None => stacks
case Some(_) => loop(t.getCause, getCause(t) :: stacks)
}
}
loop(t)
.map { msg =>
s"[$msg]"
}
.mkString(" ")
}
def warn(msg: => String, e: => Throwable): Unit =
if (logger.isWarnEnabled) {
logger.warn(s"$msg\n\t${throwableMsg(e, depth = 10)}")
}
def error(msg: => String): Unit =
if (logger.isErrorEnabled) logger.error(msg)
def error(msg: => String, e: => Throwable): Unit =
if (logger.isErrorEnabled) logger.error(msg, e)
def withTimeTrackLog[T](msg: => String)(snippet: => T): T = {
if (isDebugEnabled) {
logger.debug(s"[P][START]$msg")
val start = System.currentTimeMillis()
val _result = snippet
val end = System.currentTimeMillis()
logger.debug(s"[P][END](${end - start} ms) $msg")
_result
} else snippet
}
def withTimeTrackLogWithResult[T](msg: => String)(snippet: => T): T = {
if (isDebugEnabled) {
logger.debug(s"[P][START]$msg")
val start = System.currentTimeMillis()
val _result = snippet
val end = System.currentTimeMillis()
logger.debug(s"[P][END](${end - start} ms) $msg. result = ${_result}")
_result
} else snippet
}
private def log(logLevel: LogLevel): (=> String) => Unit = {
import LogLevel._
logLevel match {
case DEBUG => debug _
case INFO => info _
case WARN => warn _
case ERROR => error
}
}
def withTrackLog[T](msg: => String, logLevel: LogLevel = LogLevel.DEBUG)(snippet: => T): T = {
val _msg = msg
log(logLevel)(s"[START] ${_msg}")
val r = snippet
log(logLevel)(s"[END] ${_msg}")
r
}
}
sealed abstract class LogLevel(val value: String)
object LogLevel {
case object DEBUG extends LogLevel("debug")
case object INFO extends LogLevel("info")
case object WARN extends LogLevel("warn")
case object ERROR extends LogLevel("error")
val values = DEBUG :: INFO :: WARN :: ERROR :: Nil
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment