package play.api
import java.io.File
import java.net.URL
import org.slf4j.{ LoggerFactory, Logger => Slf4jLogger }
import scala.util.control.NonFatal
trait LoggerLike {
val logger: Slf4jLogger
lazy val underlyingLogger = logger
def isTraceEnabled = logger.isTraceEnabled
def isDebugEnabled = logger.isDebugEnabled
def isInfoEnabled = logger.isInfoEnabled
def isWarnEnabled = logger.isWarnEnabled
def isErrorEnabled = logger.isErrorEnabled
def trace(message: => String) {
if (logger.isTraceEnabled) logger.trace(message)
}
def trace(message: => String, error: => Throwable) {
if (logger.isTraceEnabled) logger.trace(message, error)
}
def debug(message: => String) {
if (logger.isDebugEnabled) logger.debug(message)
}
def debug(message: => String, error: => Throwable) {
if (logger.isDebugEnabled) logger.debug(message, error)
}
def info(message: => String) {
if (logger.isInfoEnabled) logger.info(message)
}
def info(message: => String, error: => Throwable) {
if (logger.isInfoEnabled) logger.info(message, error)
}
def warn(message: => String) {
if (logger.isWarnEnabled) logger.warn(message)
}
def warn(message: => String, error: => Throwable) {
if (logger.isWarnEnabled) logger.warn(message, error)
}
def error(message: => String) {
if (logger.isErrorEnabled) logger.error(message)
}
def error(message: => String, error: => Throwable) {
if (logger.isErrorEnabled) logger.error(message, error)
}
}
class Logger(val logger: Slf4jLogger) extends LoggerLike
object Logger extends LoggerLike {
import ch.qos.logback.classic.{ Level => LogbackLevel }
val logger = LoggerFactory.getLogger("application")
def apply(name: String): Logger = new Logger(LoggerFactory.getLogger(name))
def apply[T](clazz: Class[T]): Logger = new Logger(LoggerFactory.getLogger(clazz))
def init(rootPath: java.io.File, mode: Mode.Mode): Unit = {
val properties = Map("application.home" -> rootPath.getAbsolutePath)
val resourceName = if (mode == Mode.Dev) "logback-play-dev.xml" else "logback-play-default.xml"
val resourceUrl = Option(Logger.getClass.getClassLoader.getResource(resourceName))
configure(properties, resourceUrl)
}
def configure(env: Environment): Unit = {
val properties = Map("application.home" -> env.rootPath.getAbsolutePath)
def explicitResourceUrl = sys.props.get("logger.resource").map { r =>
env.resource(r).getOrElse(new File(env.getFile("conf"), r).toURI.toURL)
}
def explicitFileUrl = sys.props.get("logger.file").map(new File(_).toURI.toURL)
def resourceUrl = env.resource("application-logger.xml")
.orElse(env.resource("logger.xml"))
.orElse(env.resource("logback.xml"))
.orElse(env.resource(
if (env.mode == Mode.Dev) "logback-play-dev.xml" else "logback-play-default.xml"
))
val configUrl = explicitResourceUrl orElse explicitFileUrl orElse resourceUrl
configure(properties, configUrl)
}
def configure(properties: Map[String, String], config: Option[URL]): Unit = synchronized {
{
import org.slf4j.bridge._
import java.util.logging._
Option(java.util.logging.Logger.getLogger("")).map { root =>
root.setLevel(Level.FINEST)
root.getHandlers.foreach(root.removeHandler(_))
}
SLF4JBridgeHandler.install()
}
{
import org.slf4j._
import ch.qos.logback.classic.joran._
import ch.qos.logback.core.util._
import ch.qos.logback.classic._
try {
val ctx = LoggerFactory.getILoggerFactory.asInstanceOf[LoggerContext]
val configurator = new JoranConfigurator
configurator.setContext(ctx)
ctx.reset()
val frameworkPackages = ctx.getFrameworkPackages
frameworkPackages.add(classOf[play.Logger].getName)
frameworkPackages.add(classOf[play.api.Logger].getName)
properties.foreach {
case (name, value) => ctx.putProperty(name, value)
}
try {
config match {
case Some(url) => configurator.doConfigure(url)
case None =>
System.err.println("Could not detect a logback configuration file, not configuring logback")
}
} catch {
case NonFatal(e) =>
System.err.println("Error encountered while configuring logback:")
e.printStackTrace()
}
StatusPrinter.printIfErrorsOccured(ctx)
} catch {
case NonFatal(_) =>
}
}
}
def shutdown() {
import ch.qos.logback.classic._
val ctx = LoggerFactory.getILoggerFactory.asInstanceOf[LoggerContext]
ctx.stop()
}
import ch.qos.logback.classic._
import ch.qos.logback.classic.spi._
import ch.qos.logback.classic.pattern._
class ColoredLevel extends ClassicConverter {
import play.utils.Colors
def convert(event: ILoggingEvent): String = {
event.getLevel match {
case Level.TRACE => "[" + Colors.blue("trace") + "]"
case Level.DEBUG => "[" + Colors.cyan("debug") + "]"
case Level.INFO => "[" + Colors.white("info") + "]"
case Level.WARN => "[" + Colors.yellow("warn") + "]"
case Level.ERROR => "[" + Colors.red("error") + "]"
}
}
}
}