http://git-wip-us.apache.org/repos/asf/logging-log4j-scala/blob/72fe94f7/src/main/scala/org/apache/logging/log4j/scala/LoggerMacro.scala
----------------------------------------------------------------------
diff --git a/src/main/scala/org/apache/logging/log4j/scala/LoggerMacro.scala 
b/src/main/scala/org/apache/logging/log4j/scala/LoggerMacro.scala
new file mode 100644
index 0000000..3b54db1
--- /dev/null
+++ b/src/main/scala/org/apache/logging/log4j/scala/LoggerMacro.scala
@@ -0,0 +1,425 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.scala
+
+import org.apache.logging.log4j.message.{EntryMessage, Message}
+import org.apache.logging.log4j.spi.AbstractLogger
+import org.apache.logging.log4j.{Level, Marker}
+
+import scala.language.experimental.macros
+import scala.reflect.macros.blackbox
+
+/**
+  * Inspired from [[https://github.com/typesafehub/scalalogging ScalaLogging]].
+  */
+private object LoggerMacro {
+
+  type LoggerContext = blackbox.Context { type PrefixType = Logger }
+
+
+  def fatalMarkerMsg(c: LoggerContext)(marker: c.Expr[Marker], message: 
c.Expr[Message]) =
+    logMarkerMsg(c)(c.universe.reify(Level.FATAL), marker, message)
+
+  def fatalMarkerCseq(c: LoggerContext)(marker: c.Expr[Marker], message: 
c.Expr[CharSequence]) =
+    logMarkerCseq(c)(c.universe.reify(Level.FATAL), marker, message)
+
+  def fatalMarkerObject(c: LoggerContext)(marker: c.Expr[Marker], message: 
c.Expr[AnyRef]) =
+    logMarkerObject(c)(c.universe.reify(Level.FATAL), marker, message)
+
+  def fatalMarkerMsgThrowable(c: LoggerContext)(marker: c.Expr[Marker], 
message: c.Expr[Message], cause: c.Expr[Throwable]) =
+    logMarkerMsgThrowable(c)(c.universe.reify(Level.FATAL), marker, message, 
cause)
+
+  def fatalMarkerCseqThrowable(c: LoggerContext)(marker: c.Expr[Marker], 
message: c.Expr[CharSequence], cause: c.Expr[Throwable]) =
+    logMarkerCseqThrowable(c)(c.universe.reify(Level.FATAL), marker, message, 
cause)
+
+  def fatalMarkerObjectThrowable(c: LoggerContext)(marker: c.Expr[Marker], 
message: c.Expr[AnyRef], cause: c.Expr[Throwable]) =
+    logMarkerObjectThrowable(c)(c.universe.reify(Level.FATAL), marker, 
message, cause)
+
+  def fatalMsg(c: LoggerContext)(message: c.Expr[Message]) =
+    logMsg(c)(c.universe.reify(Level.FATAL), message)
+
+  def fatalCseq(c: LoggerContext)(message: c.Expr[CharSequence]) =
+    logCseq(c)(c.universe.reify(Level.FATAL), message)
+
+  def fatalObject(c: LoggerContext)(message: c.Expr[AnyRef]) =
+    logObject(c)(c.universe.reify(Level.FATAL), message)
+
+  def fatalMsgThrowable(c: LoggerContext)(message: c.Expr[Message], cause: 
c.Expr[Throwable]) =
+    logMsgThrowable(c)(c.universe.reify(Level.FATAL), message, cause)
+
+  def fatalCseqThrowable(c: LoggerContext)(message: c.Expr[CharSequence], 
cause: c.Expr[Throwable]) =
+    logCseqThrowable(c)(c.universe.reify(Level.FATAL), message, cause)
+
+  def fatalObjectThrowable(c: LoggerContext)(message: c.Expr[AnyRef], cause: 
c.Expr[Throwable]) =
+    logObjectThrowable(c)(c.universe.reify(Level.FATAL), message, cause)
+
+
+  def errorMarkerMsg(c: LoggerContext)(marker: c.Expr[Marker], message: 
c.Expr[Message]) =
+    logMarkerMsg(c)(c.universe.reify(Level.ERROR), marker, message)
+
+  def errorMarkerCseq(c: LoggerContext)(marker: c.Expr[Marker], message: 
c.Expr[CharSequence]) =
+    logMarkerCseq(c)(c.universe.reify(Level.ERROR), marker, message)
+
+  def errorMarkerObject(c: LoggerContext)(marker: c.Expr[Marker], message: 
c.Expr[AnyRef]) =
+    logMarkerObject(c)(c.universe.reify(Level.ERROR), marker, message)
+
+  def errorMarkerMsgThrowable(c: LoggerContext)(marker: c.Expr[Marker], 
message: c.Expr[Message], cause: c.Expr[Throwable]) =
+    logMarkerMsgThrowable(c)(c.universe.reify(Level.ERROR), marker, message, 
cause)
+
+  def errorMarkerCseqThrowable(c: LoggerContext)(marker: c.Expr[Marker], 
message: c.Expr[CharSequence], cause: c.Expr[Throwable]) =
+    logMarkerCseqThrowable(c)(c.universe.reify(Level.ERROR), marker, message, 
cause)
+
+  def errorMarkerObjectThrowable(c: LoggerContext)(marker: c.Expr[Marker], 
message: c.Expr[AnyRef], cause: c.Expr[Throwable]) =
+    logMarkerObjectThrowable(c)(c.universe.reify(Level.ERROR), marker, 
message, cause)
+
+  def errorMsg(c: LoggerContext)(message: c.Expr[Message]) =
+    logMsg(c)(c.universe.reify(Level.ERROR), message)
+
+  def errorCseq(c: LoggerContext)(message: c.Expr[CharSequence]) =
+    logCseq(c)(c.universe.reify(Level.ERROR), message)
+
+  def errorObject(c: LoggerContext)(message: c.Expr[AnyRef]) =
+    logObject(c)(c.universe.reify(Level.ERROR), message)
+
+  def errorMsgThrowable(c: LoggerContext)(message: c.Expr[Message], cause: 
c.Expr[Throwable]) =
+    logMsgThrowable(c)(c.universe.reify(Level.ERROR), message, cause)
+
+  def errorCseqThrowable(c: LoggerContext)(message: c.Expr[CharSequence], 
cause: c.Expr[Throwable]) =
+    logCseqThrowable(c)(c.universe.reify(Level.ERROR), message, cause)
+
+  def errorObjectThrowable(c: LoggerContext)(message: c.Expr[AnyRef], cause: 
c.Expr[Throwable]) =
+    logObjectThrowable(c)(c.universe.reify(Level.ERROR), message, cause)
+
+
+  def warnMarkerMsg(c: LoggerContext)(marker: c.Expr[Marker], message: 
c.Expr[Message]) =
+    logMarkerMsg(c)(c.universe.reify(Level.WARN), marker, message)
+
+  def warnMarkerCseq(c: LoggerContext)(marker: c.Expr[Marker], message: 
c.Expr[CharSequence]) =
+    logMarkerCseq(c)(c.universe.reify(Level.WARN), marker, message)
+
+  def warnMarkerObject(c: LoggerContext)(marker: c.Expr[Marker], message: 
c.Expr[AnyRef]) =
+    logMarkerObject(c)(c.universe.reify(Level.WARN), marker, message)
+
+  def warnMarkerMsgThrowable(c: LoggerContext)(marker: c.Expr[Marker], 
message: c.Expr[Message], cause: c.Expr[Throwable]) =
+    logMarkerMsgThrowable(c)(c.universe.reify(Level.WARN), marker, message, 
cause)
+
+  def warnMarkerCseqThrowable(c: LoggerContext)(marker: c.Expr[Marker], 
message: c.Expr[CharSequence], cause: c.Expr[Throwable]) =
+    logMarkerCseqThrowable(c)(c.universe.reify(Level.WARN), marker, message, 
cause)
+
+  def warnMarkerObjectThrowable(c: LoggerContext)(marker: c.Expr[Marker], 
message: c.Expr[AnyRef], cause: c.Expr[Throwable]) =
+    logMarkerObjectThrowable(c)(c.universe.reify(Level.WARN), marker, message, 
cause)
+
+  def warnMsg(c: LoggerContext)(message: c.Expr[Message]) =
+    logMsg(c)(c.universe.reify(Level.WARN), message)
+
+  def warnCseq(c: LoggerContext)(message: c.Expr[CharSequence]) =
+    logCseq(c)(c.universe.reify(Level.WARN), message)
+
+  def warnObject(c: LoggerContext)(message: c.Expr[AnyRef]) =
+    logObject(c)(c.universe.reify(Level.WARN), message)
+
+  def warnMsgThrowable(c: LoggerContext)(message: c.Expr[Message], cause: 
c.Expr[Throwable]) =
+    logMsgThrowable(c)(c.universe.reify(Level.WARN), message, cause)
+
+  def warnCseqThrowable(c: LoggerContext)(message: c.Expr[CharSequence], 
cause: c.Expr[Throwable]) =
+    logCseqThrowable(c)(c.universe.reify(Level.WARN), message, cause)
+
+  def warnObjectThrowable(c: LoggerContext)(message: c.Expr[AnyRef], cause: 
c.Expr[Throwable]) =
+    logObjectThrowable(c)(c.universe.reify(Level.WARN), message, cause)
+
+
+  def infoMarkerMsg(c: LoggerContext)(marker: c.Expr[Marker], message: 
c.Expr[Message]) =
+    logMarkerMsg(c)(c.universe.reify(Level.INFO), marker, message)
+
+  def infoMarkerCseq(c: LoggerContext)(marker: c.Expr[Marker], message: 
c.Expr[CharSequence]) =
+    logMarkerCseq(c)(c.universe.reify(Level.INFO), marker, message)
+
+  def infoMarkerObject(c: LoggerContext)(marker: c.Expr[Marker], message: 
c.Expr[AnyRef]) =
+    logMarkerObject(c)(c.universe.reify(Level.INFO), marker, message)
+
+  def infoMarkerMsgThrowable(c: LoggerContext)(marker: c.Expr[Marker], 
message: c.Expr[Message], cause: c.Expr[Throwable]) =
+    logMarkerMsgThrowable(c)(c.universe.reify(Level.INFO), marker, message, 
cause)
+
+  def infoMarkerCseqThrowable(c: LoggerContext)(marker: c.Expr[Marker], 
message: c.Expr[CharSequence], cause: c.Expr[Throwable]) =
+    logMarkerCseqThrowable(c)(c.universe.reify(Level.INFO), marker, message, 
cause)
+
+  def infoMarkerObjectThrowable(c: LoggerContext)(marker: c.Expr[Marker], 
message: c.Expr[AnyRef], cause: c.Expr[Throwable]) =
+    logMarkerObjectThrowable(c)(c.universe.reify(Level.INFO), marker, message, 
cause)
+
+  def infoMsg(c: LoggerContext)(message: c.Expr[Message]) =
+    logMsg(c)(c.universe.reify(Level.INFO), message)
+
+  def infoCseq(c: LoggerContext)(message: c.Expr[CharSequence]) =
+    logCseq(c)(c.universe.reify(Level.INFO), message)
+
+  def infoObject(c: LoggerContext)(message: c.Expr[AnyRef]) =
+    logObject(c)(c.universe.reify(Level.INFO), message)
+
+  def infoMsgThrowable(c: LoggerContext)(message: c.Expr[Message], cause: 
c.Expr[Throwable]) =
+    logMsgThrowable(c)(c.universe.reify(Level.INFO), message, cause)
+
+  def infoCseqThrowable(c: LoggerContext)(message: c.Expr[CharSequence], 
cause: c.Expr[Throwable]) =
+    logCseqThrowable(c)(c.universe.reify(Level.INFO), message, cause)
+
+  def infoObjectThrowable(c: LoggerContext)(message: c.Expr[AnyRef], cause: 
c.Expr[Throwable]) =
+    logObjectThrowable(c)(c.universe.reify(Level.INFO), message, cause)
+
+
+  def debugMarkerMsg(c: LoggerContext)(marker: c.Expr[Marker], message: 
c.Expr[Message]) =
+    logMarkerMsg(c)(c.universe.reify(Level.DEBUG), marker, message)
+
+  def debugMarkerCseq(c: LoggerContext)(marker: c.Expr[Marker], message: 
c.Expr[CharSequence]) =
+    logMarkerCseq(c)(c.universe.reify(Level.DEBUG), marker, message)
+
+  def debugMarkerObject(c: LoggerContext)(marker: c.Expr[Marker], message: 
c.Expr[AnyRef]) =
+    logMarkerObject(c)(c.universe.reify(Level.DEBUG), marker, message)
+
+  def debugMarkerMsgThrowable(c: LoggerContext)(marker: c.Expr[Marker], 
message: c.Expr[Message], cause: c.Expr[Throwable]) =
+    logMarkerMsgThrowable(c)(c.universe.reify(Level.DEBUG), marker, message, 
cause)
+
+  def debugMarkerCseqThrowable(c: LoggerContext)(marker: c.Expr[Marker], 
message: c.Expr[CharSequence], cause: c.Expr[Throwable]) =
+    logMarkerCseqThrowable(c)(c.universe.reify(Level.DEBUG), marker, message, 
cause)
+
+  def debugMarkerObjectThrowable(c: LoggerContext)(marker: c.Expr[Marker], 
message: c.Expr[AnyRef], cause: c.Expr[Throwable]) =
+    logMarkerObjectThrowable(c)(c.universe.reify(Level.DEBUG), marker, 
message, cause)
+
+  def debugMsg(c: LoggerContext)(message: c.Expr[Message]) =
+    logMsg(c)(c.universe.reify(Level.DEBUG), message)
+
+  def debugCseq(c: LoggerContext)(message: c.Expr[CharSequence]) =
+    logCseq(c)(c.universe.reify(Level.DEBUG), message)
+
+  def debugObject(c: LoggerContext)(message: c.Expr[AnyRef]) =
+    logObject(c)(c.universe.reify(Level.DEBUG), message)
+
+  def debugMsgThrowable(c: LoggerContext)(message: c.Expr[Message], cause: 
c.Expr[Throwable]) =
+    logMsgThrowable(c)(c.universe.reify(Level.DEBUG), message, cause)
+
+  def debugCseqThrowable(c: LoggerContext)(message: c.Expr[CharSequence], 
cause: c.Expr[Throwable]) =
+    logCseqThrowable(c)(c.universe.reify(Level.DEBUG), message, cause)
+
+  def debugObjectThrowable(c: LoggerContext)(message: c.Expr[AnyRef], cause: 
c.Expr[Throwable]) =
+    logObjectThrowable(c)(c.universe.reify(Level.DEBUG), message, cause)
+
+
+  def traceMarkerMsg(c: LoggerContext)(marker: c.Expr[Marker], message: 
c.Expr[Message]) =
+    logMarkerMsg(c)(c.universe.reify(Level.TRACE), marker, message)
+
+  def traceMarkerCseq(c: LoggerContext)(marker: c.Expr[Marker], message: 
c.Expr[CharSequence]) =
+    logMarkerCseq(c)(c.universe.reify(Level.TRACE), marker, message)
+
+  def traceMarkerObject(c: LoggerContext)(marker: c.Expr[Marker], message: 
c.Expr[AnyRef]) =
+    logMarkerObject(c)(c.universe.reify(Level.TRACE), marker, message)
+
+  def traceMarkerMsgThrowable(c: LoggerContext)(marker: c.Expr[Marker], 
message: c.Expr[Message], cause: c.Expr[Throwable]) =
+    logMarkerMsgThrowable(c)(c.universe.reify(Level.TRACE), marker, message, 
cause)
+
+  def traceMarkerCseqThrowable(c: LoggerContext)(marker: c.Expr[Marker], 
message: c.Expr[CharSequence], cause: c.Expr[Throwable]) =
+    logMarkerCseqThrowable(c)(c.universe.reify(Level.TRACE), marker, message, 
cause)
+
+  def traceMarkerObjectThrowable(c: LoggerContext)(marker: c.Expr[Marker], 
message: c.Expr[AnyRef], cause: c.Expr[Throwable]) =
+    logMarkerObjectThrowable(c)(c.universe.reify(Level.TRACE), marker, 
message, cause)
+
+  def traceMsg(c: LoggerContext)(message: c.Expr[Message]) =
+    logMsg(c)(c.universe.reify(Level.TRACE), message)
+
+  def traceCseq(c: LoggerContext)(message: c.Expr[CharSequence]) =
+    logCseq(c)(c.universe.reify(Level.TRACE), message)
+
+  def traceObject(c: LoggerContext)(message: c.Expr[AnyRef]) =
+    logObject(c)(c.universe.reify(Level.TRACE), message)
+
+  def traceMsgThrowable(c: LoggerContext)(message: c.Expr[Message], cause: 
c.Expr[Throwable]) =
+    logMsgThrowable(c)(c.universe.reify(Level.TRACE), message, cause)
+
+  def traceCseqThrowable(c: LoggerContext)(message: c.Expr[CharSequence], 
cause: c.Expr[Throwable]) =
+    logCseqThrowable(c)(c.universe.reify(Level.TRACE), message, cause)
+
+  def traceObjectThrowable(c: LoggerContext)(message: c.Expr[AnyRef], cause: 
c.Expr[Throwable]) =
+    logObjectThrowable(c)(c.universe.reify(Level.TRACE), message, cause)
+
+
+  def logMarkerMsg(c: LoggerContext)(level: c.Expr[Level], marker: 
c.Expr[Marker], message: c.Expr[Message]) =
+    c.universe.reify(
+      if (c.prefix.splice.delegate.isEnabled(level.splice, marker.splice)) {
+        c.prefix.splice.logMessage(level.splice, marker.splice, 
message.splice, null)
+      }
+    )
+
+  def logMarkerCseq(c: LoggerContext)(level: c.Expr[Level], marker: 
c.Expr[Marker], message: c.Expr[CharSequence]) =
+    c.universe.reify(
+      if (c.prefix.splice.delegate.isEnabled(level.splice, marker.splice)) {
+        c.prefix.splice.logMessage(level.splice, marker.splice, 
message.splice, null)
+      }
+    )
+
+  def logMarkerObject(c: LoggerContext)(level: c.Expr[Level], marker: 
c.Expr[Marker], message: c.Expr[AnyRef]) =
+    c.universe.reify(
+      if (c.prefix.splice.delegate.isEnabled(level.splice, marker.splice)) {
+        c.prefix.splice.logMessage(level.splice, marker.splice, 
message.splice, null)
+      }
+    )
+
+  def logMarkerMsgThrowable(c: LoggerContext)(level: c.Expr[Level], marker: 
c.Expr[Marker], message: c.Expr[Message], cause: c.Expr[Throwable]) =
+    c.universe.reify(
+      if (c.prefix.splice.delegate.isEnabled(level.splice, marker.splice)) {
+        c.prefix.splice.logMessage(level.splice, marker.splice, 
message.splice, cause.splice)
+      }
+    )
+
+  def logMarkerCseqThrowable(c: LoggerContext)(level: c.Expr[Level], marker: 
c.Expr[Marker], message: c.Expr[CharSequence], cause: c.Expr[Throwable]) =
+    c.universe.reify(
+      if (c.prefix.splice.delegate.isEnabled(level.splice, marker.splice)) {
+        c.prefix.splice.logMessage(level.splice, marker.splice, 
message.splice, cause.splice)
+      }
+    )
+
+  def logMarkerObjectThrowable(c: LoggerContext)(level: c.Expr[Level], marker: 
c.Expr[Marker], message: c.Expr[AnyRef], cause: c.Expr[Throwable]) =
+    c.universe.reify(
+      if (c.prefix.splice.delegate.isEnabled(level.splice, marker.splice)) {
+        c.prefix.splice.logMessage(level.splice, marker.splice, 
message.splice, cause.splice)
+      }
+    )
+
+  def logMsg(c: LoggerContext)(level: c.Expr[Level], message: c.Expr[Message]) 
=
+    c.universe.reify(
+      if (c.prefix.splice.delegate.isEnabled(level.splice)) {
+        c.prefix.splice.logMessage(level.splice, null, message.splice, null)
+      }
+    )
+
+  def logCseq(c: LoggerContext)(level: c.Expr[Level], message: 
c.Expr[CharSequence]) =
+    c.universe.reify(
+      if (c.prefix.splice.delegate.isEnabled(level.splice)) {
+        c.prefix.splice.logMessage(level.splice, null, message.splice, null)
+      }
+    )
+
+  def logObject(c: LoggerContext)(level: c.Expr[Level], message: 
c.Expr[AnyRef]) =
+    c.universe.reify(
+      if (c.prefix.splice.delegate.isEnabled(level.splice)) {
+        c.prefix.splice.logMessage(level.splice, null, message.splice, null)
+      }
+    )
+
+  def logMsgThrowable(c: LoggerContext)(level: c.Expr[Level], message: 
c.Expr[Message], cause: c.Expr[Throwable]) =
+    c.universe.reify(
+      if (c.prefix.splice.delegate.isEnabled(level.splice)) {
+        c.prefix.splice.logMessage(level.splice, null, message.splice, 
cause.splice)
+      }
+    )
+
+  def logCseqThrowable(c: LoggerContext)(level: c.Expr[Level], message: 
c.Expr[CharSequence], cause: c.Expr[Throwable]) =
+    c.universe.reify(
+      if (c.prefix.splice.delegate.isEnabled(level.splice)) {
+        c.prefix.splice.logMessage(level.splice, null, message.splice, 
cause.splice)
+      }
+    )
+
+  def logObjectThrowable(c: LoggerContext)(level: c.Expr[Level], message: 
c.Expr[AnyRef], cause: c.Expr[Throwable]) =
+    c.universe.reify(
+      if (c.prefix.splice.delegate.isEnabled(level.splice)) {
+        c.prefix.splice.logMessage(level.splice, null, message.splice, 
cause.splice)
+      }
+    )
+
+
+  def traceEntry(c: LoggerContext)(): c.Expr[EntryMessage] =
+    c.universe.reify(
+      c.prefix.splice.delegate.traceEntry()
+    )
+
+  def traceEntryParams(c: LoggerContext)(params: c.Expr[AnyRef]*): 
c.Expr[EntryMessage] = {
+    import c.universe._
+    val isEnabled = Apply(
+      Select(Select(c.prefix.tree, TermName("delegate")), 
TermName("isEnabled")),
+      List(
+        reify(Level.TRACE).tree,
+        reify(AbstractLogger.ENTRY_MARKER).tree,
+        reify(null: AnyRef).tree,
+        reify(null).tree
+      )
+    )
+
+    val log = Apply(
+      Select(Select(c.prefix.tree, TermName("delegate")), 
TermName("traceEntry")),
+      reify(null: String).tree :: (params map (_.tree)).toList
+    )
+    c.Expr[EntryMessage](If(isEnabled, log, reify(null).tree))
+  }
+
+
+  def traceEntryMessage(c: LoggerContext)(message: c.Expr[Message]): 
c.Expr[EntryMessage] =
+    c.universe.reify(
+      if (c.prefix.splice.delegate.isEnabled(Level.TRACE, 
AbstractLogger.ENTRY_MARKER, null: AnyRef, null)) {
+        c.prefix.splice.delegate.traceEntry(message.splice)  // TODO should 
not do ifEnabled check
+      } else {
+        null
+      }
+    )
+
+  def traceExit(c: LoggerContext)(): c.Expr[Unit] =
+    c.universe.reify(
+      c.prefix.splice.delegate.traceExit()
+    )
+
+  def traceExitResult[R: c.WeakTypeTag](c: LoggerContext)(result: c.Expr[R]): 
c.Expr[R] =
+    c.universe.reify(
+      c.prefix.splice.delegate.traceExit(result.splice)
+    )
+
+  def traceExitEntryMessage(c: LoggerContext)(entryMessage: 
c.Expr[EntryMessage]): c.Expr[Unit] =
+    c.universe.reify(
+      c.prefix.splice.delegate.traceExit(entryMessage.splice)
+    )
+
+  def traceExitEntryMessageResult[R: c.WeakTypeTag](c: 
LoggerContext)(entryMessage: c.Expr[EntryMessage], result: c.Expr[R]): 
c.Expr[R] =
+    c.universe.reify(
+      c.prefix.splice.delegate.traceExit(entryMessage.splice, result.splice)
+    )
+
+  def traceExitMessageResult[R: c.WeakTypeTag](c: LoggerContext)(message: 
c.Expr[Message], result: c.Expr[R]): c.Expr[R] =
+    c.universe.reify(
+      {
+        if (message.splice != null && 
c.prefix.splice.delegate.isEnabled(Level.TRACE, AbstractLogger.EXIT_MARKER, 
message.splice, null)) {
+          c.prefix.splice.delegate.traceExit(message.splice, result.splice)  
// TODO should not do ifEnabled check
+        }
+        result.splice
+      }
+    )
+
+  def throwing[T <: Throwable: c.WeakTypeTag](c: LoggerContext)(t: c.Expr[T]): 
c.Expr[T] =
+    c.universe.reify(
+      c.prefix.splice.delegate.throwing(t.splice)
+    )
+
+  def throwingLevel[T <: Throwable: c.WeakTypeTag](c: LoggerContext)(level: 
c.Expr[Level], t: c.Expr[T]): c.Expr[T] =
+    c.universe.reify(
+      c.prefix.splice.delegate.throwing(level.splice, t.splice)
+    )
+
+  def catching(c: LoggerContext)(t: c.Expr[Throwable]): c.Expr[Unit] =
+    c.universe.reify(
+      c.prefix.splice.delegate.catching(t.splice)
+    )
+
+  def catchingLevel(c: LoggerContext)(level: c.Expr[Level], t: 
c.Expr[Throwable]): c.Expr[Unit] =
+    c.universe.reify(
+      c.prefix.splice.delegate.catching(level.splice, t.splice)
+    )
+
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j-scala/blob/72fe94f7/src/main/scala/org/apache/logging/log4j/scala/Logging.scala
----------------------------------------------------------------------
diff --git a/src/main/scala/org/apache/logging/log4j/scala/Logging.scala 
b/src/main/scala/org/apache/logging/log4j/scala/Logging.scala
new file mode 100644
index 0000000..b017de7
--- /dev/null
+++ b/src/main/scala/org/apache/logging/log4j/scala/Logging.scala
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.scala
+
+/**
+  * Mix in this trait into classes from which you want to log,
+  * give you a `logger` value with a [[Logger]] named according to the class.
+  */
+trait Logging {
+
+  /**
+    * A [[Logger]] named according to the class.
+    */
+  protected val logger: Logger = Logger(getClass)
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/logging-log4j-scala/blob/72fe94f7/src/main/scala/org/apache/logging/log4j/scala/LoggingContext.scala
----------------------------------------------------------------------
diff --git a/src/main/scala/org/apache/logging/log4j/scala/LoggingContext.scala 
b/src/main/scala/org/apache/logging/log4j/scala/LoggingContext.scala
new file mode 100644
index 0000000..79efecc
--- /dev/null
+++ b/src/main/scala/org/apache/logging/log4j/scala/LoggingContext.scala
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.scala
+
+import org.apache.logging.log4j.ThreadContext
+
+import scala.collection.JavaConverters._
+import scala.collection.{immutable, mutable}
+
+/** Manages the context data (context map, MDC) that is added to log events.
+  *
+  * A wrapper around `org.apache.logging.log4j.ThreadContext`.
+  */
+object LoggingContext extends mutable.Map[String, String] {
+
+  override def +=(kv: (String, String)): LoggingContext.this.type = {
+    ThreadContext.put(kv._1, kv._2)
+    this
+  }
+
+  override def +=(elem1: (String, String), elem2: (String, String), elems: 
(String, String)*): LoggingContext.this.type = {
+    val builder = immutable.Map.newBuilder[String,String]
+    builder += elem1
+    builder += elem2
+    builder ++= elems
+    ThreadContext.putAll(builder.result.asJava)
+    this
+  }
+
+  override def ++=(xs: TraversableOnce[(String, String)]): 
LoggingContext.this.type = {
+    ThreadContext.putAll(xs.toMap.asJava)
+    this
+  }
+
+  override def -=(key: String): LoggingContext.this.type = {
+    ThreadContext.remove(key)
+    this
+  }
+
+  override def -=(elem1: String, elem2: String, elems: String*): 
LoggingContext.this.type = {
+    val builder = immutable.Seq.newBuilder[String]
+    builder += elem1
+    builder += elem2
+    builder ++= elems
+    ThreadContext.removeAll(builder.result.asJava)
+    this
+  }
+
+  override def --=(xs: TraversableOnce[String]): LoggingContext.this.type = {
+    ThreadContext.removeAll(xs.toSeq.asJava)
+    this
+  }
+
+  override def clear(): Unit = {
+    ThreadContext.clearMap()
+  }
+
+  override def contains(key: String): Boolean = ThreadContext.containsKey(key)
+
+  override def get(key: String): Option[String] = 
Option(ThreadContext.get(key))
+
+  override def iterator: Iterator[(String, String)] = 
ThreadContext.getImmutableContext.asScala.iterator
+
+  override def foreach[U](f: ((String, String)) => U): Unit = 
ThreadContext.getImmutableContext.asScala.foreach(f)
+
+  override def size: Int = ThreadContext.getImmutableContext.size()
+
+  override def isEmpty: Boolean = ThreadContext.isEmpty
+
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j-scala/blob/72fe94f7/src/test/scala/org/apache/logging/log4j/scala/LoggerTest.scala
----------------------------------------------------------------------
diff --git a/src/test/scala/org/apache/logging/log4j/scala/LoggerTest.scala 
b/src/test/scala/org/apache/logging/log4j/scala/LoggerTest.scala
new file mode 100644
index 0000000..bd12742
--- /dev/null
+++ b/src/test/scala/org/apache/logging/log4j/scala/LoggerTest.scala
@@ -0,0 +1,552 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.scala
+
+import org.apache.logging.log4j.message.{DefaultFlowMessageFactory, Message, 
ParameterizedMessage, ParameterizedMessageFactory}
+import org.apache.logging.log4j.spi.{AbstractLogger, ExtendedLogger}
+import org.apache.logging.log4j.{Level, Marker, MarkerManager}
+import org.junit.runner.RunWith
+import org.mockito.Matchers.{any, anyString, eq => eqv}
+import org.mockito.Mockito._
+import org.scalatest.junit.JUnitRunner
+import org.scalatest.mockito.MockitoSugar
+import org.scalatest.{FunSuite, Matchers}
+
+import scala.language.reflectiveCalls  // needed for Mockito mocking
+
+case class Custom(i: Int)
+
+trait Manager {
+  def fetchValue(): Int
+}
+
+@RunWith(classOf[JUnitRunner])
+class LoggerTest extends FunSuite with Matchers with MockitoSugar {
+
+  val msg = new ParameterizedMessage("msg {}", 17)
+  val entryMsg = new DefaultFlowMessageFactory().newEntryMessage(msg)
+  val cseqMsg: CharSequence = new StringBuilder().append("cseq msg")
+  val objectMsg = Custom(17)
+  val cause = new RuntimeException("cause")
+  val marker = MarkerManager.getMarker("marker")
+  val result = "foo"
+
+  def fixture =
+    new {
+      val mockLogger = {
+        val mockLogger = mock[ExtendedLogger]
+        when(mockLogger.getMessageFactory).thenReturn(new 
ParameterizedMessageFactory)
+        mockLogger
+      }
+      val manager = {
+        val mockManager = mock[Manager]
+        when(mockManager.fetchValue()).thenReturn(4711)
+        mockManager
+      }
+    }
+
+  test("fatal enabled with String message") {
+    val f = fixture
+    when(f.mockLogger.isEnabled(Level.FATAL)).thenReturn(true)
+    val logger = Logger(f.mockLogger)
+    logger.fatal(s"string msg with value: ${f.manager.fetchValue()}")
+    verify(f.mockLogger).logMessage(anyString(), eqv(Level.FATAL), eqv(null), 
any[Message], eqv(null))
+    verify(f.manager).fetchValue()
+  }
+
+  test("fatal disabled with String message") {
+    val f = fixture
+    when(f.mockLogger.isEnabled(Level.FATAL)).thenReturn(false)
+    val logger = Logger(f.mockLogger)
+    logger.fatal(s"string msg with value: ${f.manager.fetchValue()}")
+    verify(f.mockLogger, never).logMessage(anyString(), any[Level], 
any[Marker], any[Message], any[Throwable])
+    verify(f.manager, never).fetchValue()
+  }
+
+  test("error enabled with String message") {
+    val f = fixture
+    when(f.mockLogger.isEnabled(Level.ERROR)).thenReturn(true)
+    val logger = Logger(f.mockLogger)
+    logger.error(s"string msg with value: ${f.manager.fetchValue()}")
+    verify(f.mockLogger).logMessage(anyString(), eqv(Level.ERROR), eqv(null), 
any[Message], eqv(null))
+    verify(f.manager).fetchValue()
+  }
+
+  test("error disabled with String message") {
+    val f = fixture
+    when(f.mockLogger.isEnabled(Level.ERROR)).thenReturn(false)
+    val logger = Logger(f.mockLogger)
+    logger.error(s"string msg with value: ${f.manager.fetchValue()}")
+    verify(f.mockLogger, never).logMessage(anyString(), any[Level], 
any[Marker], any[Message], any[Throwable])
+    verify(f.manager, never).fetchValue()
+  }
+
+  test("warn enabled with String message") {
+    val f = fixture
+    when(f.mockLogger.isEnabled(Level.WARN)).thenReturn(true)
+    val logger = Logger(f.mockLogger)
+    logger.warn(s"string msg with value: ${f.manager.fetchValue()}")
+    verify(f.mockLogger).logMessage(anyString(), eqv(Level.WARN), eqv(null), 
any[Message], eqv(null))
+    verify(f.manager).fetchValue()
+  }
+
+  test("warn disabled with String message") {
+    val f = fixture
+    when(f.mockLogger.isEnabled(Level.WARN)).thenReturn(false)
+    val logger = Logger(f.mockLogger)
+    logger.warn(s"string msg with value: ${f.manager.fetchValue()}")
+    verify(f.mockLogger, never).logMessage(anyString(), any[Level], 
any[Marker], any[Message], any[Throwable])
+    verify(f.manager, never).fetchValue()
+  }
+
+  test("info enabled with String message") {
+    val f = fixture
+    when(f.mockLogger.isEnabled(Level.INFO)).thenReturn(true)
+    val logger = Logger(f.mockLogger)
+    logger.info(s"string msg with value: ${f.manager.fetchValue()}")
+    verify(f.mockLogger).logMessage(anyString(), eqv(Level.INFO), eqv(null), 
any[Message], eqv(null))
+    verify(f.manager).fetchValue()
+  }
+
+  test("info disabled with String message") {
+    val f = fixture
+    when(f.mockLogger.isEnabled(Level.INFO)).thenReturn(false)
+    val logger = Logger(f.mockLogger)
+    logger.info(s"string msg with value: ${f.manager.fetchValue()}")
+    verify(f.mockLogger, never).logMessage(anyString(), any[Level], 
any[Marker], any[Message], any[Throwable])
+    verify(f.manager, never).fetchValue()
+  }
+
+  test("debug enabled with String message") {
+    val f = fixture
+    when(f.mockLogger.isEnabled(Level.DEBUG)).thenReturn(true)
+    val logger = Logger(f.mockLogger)
+    logger.debug(s"string msg with value: ${f.manager.fetchValue()}")
+    verify(f.mockLogger).logMessage(anyString(), eqv(Level.DEBUG), eqv(null), 
any[Message], eqv(null))
+    verify(f.manager).fetchValue()
+  }
+
+  test("debug disabled with String message") {
+    val f = fixture
+    when(f.mockLogger.isEnabled(Level.DEBUG)).thenReturn(false)
+    val logger = Logger(f.mockLogger)
+    logger.debug(s"string msg with value: ${f.manager.fetchValue()}")
+    verify(f.mockLogger, never).logMessage(anyString(), any[Level], 
any[Marker], any[Message], any[Throwable])
+    verify(f.manager, never).fetchValue()
+  }
+
+  test("trace enabled with String message") {
+    val f = fixture
+    when(f.mockLogger.isEnabled(Level.TRACE)).thenReturn(true)
+    val logger = Logger(f.mockLogger)
+    logger.trace(s"string msg with value: ${f.manager.fetchValue()}")
+    verify(f.mockLogger).logMessage(anyString(), eqv(Level.TRACE), eqv(null), 
any[Message], eqv(null))
+    verify(f.manager).fetchValue()
+  }
+
+  test("trace disabled with String message") {
+    val f = fixture
+    when(f.mockLogger.isEnabled(Level.TRACE)).thenReturn(false)
+    val logger = Logger(f.mockLogger)
+    logger.trace(s"string msg with value: ${f.manager.fetchValue()}")
+    verify(f.mockLogger, never).logMessage(anyString(), any[Level], 
any[Marker], any[Message], any[Throwable])
+    verify(f.manager, never).fetchValue()
+  }
+
+
+  test("log enabled with Message message and Marker") {
+    val f = fixture
+    when(f.mockLogger.isEnabled(Level.INFO, marker)).thenReturn(true)
+    val logger = Logger(f.mockLogger)
+    logger(Level.INFO, marker, msg)
+    verify(f.mockLogger).logMessage(anyString(), eqv(Level.INFO), eqv(marker), 
eqv(msg), eqv(null))
+  }
+
+  test("log disabled with Message message and Marker") {
+    val f = fixture
+    when(f.mockLogger.isEnabled(Level.INFO, marker)).thenReturn(false)
+    val logger = Logger(f.mockLogger)
+    logger(Level.INFO, marker, msg)
+    verify(f.mockLogger, never).logMessage(anyString(), any[Level], 
any[Marker], any[Message], any[Throwable])
+  }
+
+  test("log enabled with String message and Marker") {
+    val f = fixture
+    when(f.mockLogger.isEnabled(Level.INFO, marker)).thenReturn(true)
+    val logger = Logger(f.mockLogger)
+    logger(Level.INFO, marker, s"string msg with value: 
${f.manager.fetchValue()}")
+    verify(f.mockLogger).logMessage(anyString(), eqv(Level.INFO), eqv(marker), 
any[Message], eqv(null))
+    verify(f.manager).fetchValue()
+  }
+
+  test("log disabled with String message and Marker") {
+    val f = fixture
+    when(f.mockLogger.isEnabled(Level.INFO, marker)).thenReturn(false)
+    val logger = Logger(f.mockLogger)
+    logger(Level.INFO, marker, s"string msg with value: 
${f.manager.fetchValue()}")
+    verify(f.mockLogger, never).logMessage(anyString(), any[Level], 
any[Marker], any[Message], any[Throwable])
+    verify(f.manager, never).fetchValue()
+  }
+
+  test("log enabled with CharSequence message and Marker") {
+    val f = fixture
+    when(f.mockLogger.isEnabled(Level.INFO, marker)).thenReturn(true)
+    val logger = Logger(f.mockLogger)
+    logger(Level.INFO, marker, cseqMsg)
+    verify(f.mockLogger).logMessage(anyString(), eqv(Level.INFO), eqv(marker), 
any[Message], eqv(null))
+  }
+
+  test("log disabled with CharSequence message and Marker") {
+    val f = fixture
+    when(f.mockLogger.isEnabled(Level.INFO, marker)).thenReturn(false)
+    val logger = Logger(f.mockLogger)
+    logger(Level.INFO, marker, cseqMsg)
+    verify(f.mockLogger, never).logMessage(anyString(), any[Level], 
any[Marker], any[Message], any[Throwable])
+  }
+
+  test("log enabled with Object message and Marker") {
+    val f = fixture
+    when(f.mockLogger.isEnabled(Level.INFO, marker)).thenReturn(true)
+    val logger = Logger(f.mockLogger)
+    logger(Level.INFO, marker, objectMsg)
+    verify(f.mockLogger).logMessage(anyString(), eqv(Level.INFO), eqv(marker), 
any[Message], eqv(null))
+  }
+
+  test("log disabled with Object message and Marker") {
+    val f = fixture
+    when(f.mockLogger.isEnabled(Level.INFO, marker)).thenReturn(false)
+    val logger = Logger(f.mockLogger)
+    logger(Level.INFO, marker, objectMsg)
+    verify(f.mockLogger, never).logMessage(anyString(), any[Level], 
any[Marker], any[Message], any[Throwable])
+  }
+
+  test("log enabled with Message message and cause and Marker") {
+    val f = fixture
+    when(f.mockLogger.isEnabled(Level.INFO, marker)).thenReturn(true)
+    val logger = Logger(f.mockLogger)
+    logger(Level.INFO, marker, msg, cause)
+    verify(f.mockLogger).logMessage(anyString(), eqv(Level.INFO), eqv(marker), 
eqv(msg), eqv(cause))
+  }
+
+  test("log disabled with Message message and cause and Marker") {
+    val f = fixture
+    when(f.mockLogger.isEnabled(Level.INFO, marker)).thenReturn(false)
+    val logger = Logger(f.mockLogger)
+    logger(Level.INFO, marker, msg, cause)
+    verify(f.mockLogger, never).logMessage(anyString(), any[Level], 
any[Marker], any[Message], any[Throwable])
+  }
+
+  test("log enabled with String message and cause and Marker") {
+    val f = fixture
+    when(f.mockLogger.isEnabled(Level.INFO, marker)).thenReturn(true)
+    val logger = Logger(f.mockLogger)
+    logger(Level.INFO, marker, s"string msg with value: 
${f.manager.fetchValue()}", cause)
+    verify(f.mockLogger).logMessage(anyString(), eqv(Level.INFO), eqv(marker), 
any[Message], eqv(cause))
+    verify(f.manager).fetchValue()
+  }
+
+  test("log disabled with String message and cause and Marker") {
+    val f = fixture
+    when(f.mockLogger.isEnabled(Level.INFO, marker)).thenReturn(false)
+    val logger = Logger(f.mockLogger)
+    logger(Level.INFO, marker, s"string msg with value: 
${f.manager.fetchValue()}", cause)
+    verify(f.mockLogger, never).logMessage(anyString(), any[Level], 
any[Marker], any[Message], any[Throwable])
+    verify(f.manager, never).fetchValue()
+  }
+
+  test("log enabled with CharSequence message and cause and Marker") {
+    val f = fixture
+    when(f.mockLogger.isEnabled(Level.INFO, marker)).thenReturn(true)
+    val logger = Logger(f.mockLogger)
+    logger(Level.INFO, marker, cseqMsg, cause)
+    verify(f.mockLogger).logMessage(anyString(), eqv(Level.INFO), eqv(marker), 
any[Message], eqv(cause))
+  }
+
+  test("log disabled with CharSequence message and cause and Marker") {
+    val f = fixture
+    when(f.mockLogger.isEnabled(Level.INFO, marker)).thenReturn(false)
+    val logger = Logger(f.mockLogger)
+    logger(Level.INFO, marker, cseqMsg, cause)
+    verify(f.mockLogger, never).logMessage(anyString(), any[Level], 
any[Marker], any[Message], any[Throwable])
+  }
+
+  test("log enabled with Object message and cause and Marker") {
+    val f = fixture
+    when(f.mockLogger.isEnabled(Level.INFO, marker)).thenReturn(true)
+    val logger = Logger(f.mockLogger)
+    logger(Level.INFO, marker, objectMsg, cause)
+    verify(f.mockLogger).logMessage(anyString(), eqv(Level.INFO), eqv(marker), 
any[Message], eqv(cause))
+  }
+
+  test("log disabled with Object message and cause and Marker") {
+    val f = fixture
+    when(f.mockLogger.isEnabled(Level.INFO, marker)).thenReturn(false)
+    val logger = Logger(f.mockLogger)
+    logger(Level.INFO, marker, objectMsg, cause)
+    verify(f.mockLogger, never).logMessage(anyString(), any[Level], 
any[Marker], any[Message], any[Throwable])
+  }
+
+  test("log enabled with Message message") {
+    val f = fixture
+    when(f.mockLogger.isEnabled(Level.INFO)).thenReturn(true)
+    val logger = Logger(f.mockLogger)
+    logger(Level.INFO, msg)
+    verify(f.mockLogger).logMessage(anyString(), eqv(Level.INFO), eqv(null), 
eqv(msg), eqv(null))
+  }
+
+  test("log disabled with Message message") {
+    val f = fixture
+    when(f.mockLogger.isEnabled(Level.INFO)).thenReturn(false)
+    val logger = Logger(f.mockLogger)
+    logger(Level.INFO, msg)
+    verify(f.mockLogger, never).logMessage(anyString(), any[Level], 
any[Marker], any[Message], any[Throwable])
+  }
+
+  test("log enabled with String message") {
+    val f = fixture
+    when(f.mockLogger.isEnabled(Level.INFO)).thenReturn(true)
+    val logger = Logger(f.mockLogger)
+    logger(Level.INFO, s"string msg with value: ${f.manager.fetchValue()}")
+    verify(f.mockLogger).logMessage(anyString(), eqv(Level.INFO), eqv(null), 
any[Message], eqv(null))
+    verify(f.manager).fetchValue()
+  }
+
+  test("log disabled with String message") {
+    val f = fixture
+    when(f.mockLogger.isEnabled(Level.INFO)).thenReturn(false)
+    val logger = Logger(f.mockLogger)
+    logger(Level.INFO, s"string msg with value: ${f.manager.fetchValue()}")
+    verify(f.mockLogger, never).logMessage(anyString(), any[Level], 
any[Marker], any[Message], any[Throwable])
+    verify(f.manager, never).fetchValue()
+  }
+
+  test("log enabled with CharSequence message") {
+    val f = fixture
+    when(f.mockLogger.isEnabled(Level.INFO)).thenReturn(true)
+    val logger = Logger(f.mockLogger)
+    logger(Level.INFO, cseqMsg)
+    verify(f.mockLogger).logMessage(anyString(), eqv(Level.INFO), eqv(null), 
any[Message], eqv(null))
+  }
+
+  test("log disabled with CharSequence message") {
+    val f = fixture
+    when(f.mockLogger.isEnabled(Level.INFO)).thenReturn(false)
+    val logger = Logger(f.mockLogger)
+    logger(Level.INFO, cseqMsg)
+    verify(f.mockLogger, never).logMessage(anyString(), any[Level], 
any[Marker], any[Message], any[Throwable])
+  }
+
+  test("log enabled with Object message") {
+    val f = fixture
+    when(f.mockLogger.isEnabled(Level.INFO)).thenReturn(true)
+    val logger = Logger(f.mockLogger)
+    logger(Level.INFO, objectMsg)
+    verify(f.mockLogger).logMessage(anyString(), eqv(Level.INFO), eqv(null), 
any[Message], eqv(null))
+  }
+
+  test("log disabled with Object message") {
+    val f = fixture
+    when(f.mockLogger.isEnabled(Level.INFO)).thenReturn(false)
+    val logger = Logger(f.mockLogger)
+    logger(Level.INFO, objectMsg)
+    verify(f.mockLogger, never).logMessage(anyString(), any[Level], 
any[Marker], any[Message], any[Throwable])
+  }
+
+  test("log enabled with Message message and cause") {
+    val f = fixture
+    when(f.mockLogger.isEnabled(Level.INFO)).thenReturn(true)
+    val logger = Logger(f.mockLogger)
+    logger(Level.INFO, msg, cause)
+    verify(f.mockLogger).logMessage(anyString(), eqv(Level.INFO), eqv(null), 
eqv(msg), eqv(cause))
+  }
+
+  test("log disabled with Message message and cause") {
+    val f = fixture
+    when(f.mockLogger.isEnabled(Level.INFO)).thenReturn(false)
+    val logger = Logger(f.mockLogger)
+    logger(Level.INFO, msg, cause)
+    verify(f.mockLogger, never).logMessage(anyString(), any[Level], 
any[Marker], any[Message], any[Throwable])
+  }
+
+  test("log enabled with String message and cause") {
+    val f = fixture
+    when(f.mockLogger.isEnabled(Level.INFO)).thenReturn(true)
+    val logger = Logger(f.mockLogger)
+    logger(Level.INFO, s"string msg with value: ${f.manager.fetchValue()}", 
cause)
+    verify(f.mockLogger).logMessage(anyString(), eqv(Level.INFO), eqv(null), 
any[Message], eqv(cause))
+    verify(f.manager).fetchValue()
+  }
+
+  test("log disabled with String message and cause") {
+    val f = fixture
+    when(f.mockLogger.isEnabled(Level.INFO)).thenReturn(false)
+    val logger = Logger(f.mockLogger)
+    logger(Level.INFO, s"string msg with value: ${f.manager.fetchValue()}", 
cause)
+    verify(f.mockLogger, never).logMessage(anyString(), any[Level], 
any[Marker], any[Message], any[Throwable])
+    verify(f.manager, never).fetchValue()
+  }
+
+  test("log enabled with CharSequence message and cause") {
+    val f = fixture
+    when(f.mockLogger.isEnabled(Level.INFO)).thenReturn(true)
+    val logger = Logger(f.mockLogger)
+    logger(Level.INFO, cseqMsg, cause)
+    verify(f.mockLogger).logMessage(anyString(), eqv(Level.INFO), eqv(null), 
any[Message], eqv(cause))
+  }
+
+  test("log disabled with CharSequence message and cause") {
+    val f = fixture
+    when(f.mockLogger.isEnabled(Level.INFO)).thenReturn(false)
+    val logger = Logger(f.mockLogger)
+    logger(Level.INFO, cseqMsg, cause)
+    verify(f.mockLogger, never).logMessage(anyString(), any[Level], 
any[Marker], any[Message], any[Throwable])
+  }
+
+  test("log enabled with Object message and cause") {
+    val f = fixture
+    when(f.mockLogger.isEnabled(Level.INFO)).thenReturn(true)
+    val logger = Logger(f.mockLogger)
+    logger(Level.INFO, objectMsg, cause)
+    verify(f.mockLogger).logMessage(anyString(), eqv(Level.INFO), eqv(null), 
any[Message], eqv(cause))
+  }
+
+  test("log disabled with Object message and cause") {
+    val f = fixture
+    when(f.mockLogger.isEnabled(Level.INFO)).thenReturn(false)
+    val logger = Logger(f.mockLogger)
+    logger(Level.INFO, objectMsg, cause)
+    verify(f.mockLogger, never).logMessage(anyString(), any[Level], 
any[Marker], any[Message], any[Throwable])
+  }
+
+
+  test("traceEntry") {
+    val f = fixture
+    when(f.mockLogger.isEnabled(Level.TRACE, AbstractLogger.ENTRY_MARKER, 
null.asInstanceOf[AnyRef], null)).thenReturn(true)
+    val logger = Logger(f.mockLogger)
+    logger.traceEntry()
+    verify(f.mockLogger).traceEntry()
+  }
+
+  test("traceEntry enabled with params") {
+    val f = fixture
+    when(f.mockLogger.isEnabled(Level.TRACE, AbstractLogger.ENTRY_MARKER, 
null.asInstanceOf[AnyRef], null)).thenReturn(true)
+    val logger = Logger(f.mockLogger)
+    logger.traceEntry("foo", "bar")
+    verify(f.mockLogger).traceEntry(null: String, "foo", "bar")
+  }
+
+  test("traceEntry disabled with params") {
+    val f = fixture
+    when(f.mockLogger.isEnabled(Level.TRACE, AbstractLogger.ENTRY_MARKER, 
null.asInstanceOf[AnyRef], null)).thenReturn(false)
+    val logger = Logger(f.mockLogger)
+    logger.traceEntry("foo", "bar")
+    verify(f.mockLogger, never).traceEntry(anyString(), anyString(), 
anyString())
+  }
+
+  test("traceEntry enabled with message") {
+    val f = fixture
+    when(f.mockLogger.isEnabled(Level.TRACE, AbstractLogger.ENTRY_MARKER, 
null.asInstanceOf[AnyRef], null)).thenReturn(true)
+    val logger = Logger(f.mockLogger)
+    logger.traceEntry(msg)
+    verify(f.mockLogger).traceEntry(eqv(msg))
+  }
+
+  test("traceEntry disabled with message") {
+    val f = fixture
+    when(f.mockLogger.isEnabled(Level.TRACE, AbstractLogger.ENTRY_MARKER, 
null.asInstanceOf[AnyRef], null)).thenReturn(false)
+    val logger = Logger(f.mockLogger)
+    logger.traceEntry(msg)
+    verify(f.mockLogger, never).traceEntry(any[Message])
+  }
+
+  test("traceExit") {
+    val f = fixture
+    when(f.mockLogger.isEnabled(Level.TRACE, AbstractLogger.EXIT_MARKER, msg, 
null)).thenReturn(true)
+    val logger = Logger(f.mockLogger)
+    logger.traceExit()
+    verify(f.mockLogger).traceExit()
+  }
+
+  test("traceExit with result") {
+    val f = fixture
+    when(f.mockLogger.isEnabled(Level.TRACE, AbstractLogger.EXIT_MARKER, msg, 
null)).thenReturn(true)
+    val logger = Logger(f.mockLogger)
+    logger.traceExit(result)
+    verify(f.mockLogger).traceExit(result)
+  }
+
+  test("traceExit with entrymessage") {
+    val f = fixture
+    when(f.mockLogger.isEnabled(Level.TRACE, AbstractLogger.EXIT_MARKER, msg, 
null)).thenReturn(true)
+    val logger = Logger(f.mockLogger)
+    logger.traceExit(entryMsg)
+    verify(f.mockLogger).traceExit(entryMsg)
+  }
+
+  test("traceExit with entrymessage and result") {
+    val f = fixture
+    when(f.mockLogger.isEnabled(Level.TRACE, AbstractLogger.EXIT_MARKER, msg, 
null)).thenReturn(true)
+    val logger = Logger(f.mockLogger)
+    logger.traceExit(entryMsg, result)
+    verify(f.mockLogger).traceExit(entryMsg, result)
+  }
+
+  test("traceExit enabled with message") {
+    val f = fixture
+    when(f.mockLogger.isEnabled(Level.TRACE, AbstractLogger.EXIT_MARKER, msg, 
null)).thenReturn(true)
+    val logger = Logger(f.mockLogger)
+    logger.traceExit(msg, result)
+    verify(f.mockLogger).traceExit(eqv(msg), eqv(result))
+  }
+
+  test("traceExit disabled with message") {
+    val f = fixture
+    when(f.mockLogger.isEnabled(Level.TRACE, AbstractLogger.EXIT_MARKER, msg, 
null)).thenReturn(false)
+    val logger = Logger(f.mockLogger)
+    logger.traceExit(msg, result)
+    verify(f.mockLogger, never).traceExit(any[Message], any[AnyRef])
+  }
+
+  test("throwing") {
+    val f = fixture
+    val logger = Logger(f.mockLogger)
+    logger.throwing(cause)
+    verify(f.mockLogger).throwing(eqv(cause))
+  }
+
+  test("throwing with level") {
+    val f = fixture
+    val logger = Logger(f.mockLogger)
+    logger.throwing(Level.INFO, cause)
+    verify(f.mockLogger).throwing(eqv(Level.INFO), eqv(cause))
+  }
+
+  test("catching") {
+    val f = fixture
+    val logger = Logger(f.mockLogger)
+    logger.catching(cause)
+    verify(f.mockLogger).catching(eqv(cause))
+  }
+
+  test("catching with level") {
+    val f = fixture
+    val logger = Logger(f.mockLogger)
+    logger.catching(Level.INFO, cause)
+    verify(f.mockLogger).catching(eqv(Level.INFO), eqv(cause))
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j-scala/blob/72fe94f7/src/test/scala/org/apache/logging/log4j/scala/LoggingContextTest.scala
----------------------------------------------------------------------
diff --git 
a/src/test/scala/org/apache/logging/log4j/scala/LoggingContextTest.scala 
b/src/test/scala/org/apache/logging/log4j/scala/LoggingContextTest.scala
new file mode 100644
index 0000000..80ca940
--- /dev/null
+++ b/src/test/scala/org/apache/logging/log4j/scala/LoggingContextTest.scala
@@ -0,0 +1,115 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.scala
+
+import org.junit.runner.RunWith
+import org.scalatest.junit.JUnitRunner
+import org.scalatest.{FunSuite, Matchers}
+
+import scala.collection.mutable
+
+@RunWith(classOf[JUnitRunner])
+class LoggingContextTest extends FunSuite with Matchers {
+
+  test("put single, contains, get") {
+    LoggingContext += "key" -> "value"
+
+    LoggingContext.contains("key") shouldBe true
+    LoggingContext.get("key") shouldBe Some("value")
+    LoggingContext.contains("bogus") shouldBe false
+    LoggingContext.get("bogus") shouldBe None
+  }
+
+  test("put multiple 1") {
+    LoggingContext += ("key1" -> "value1", "key2" -> "value2")
+
+    LoggingContext.get("key1") shouldBe Some("value1")
+    LoggingContext.get("key2") shouldBe Some("value2")
+  }
+
+  test("put multiple 2") {
+    LoggingContext ++= Seq("key1" -> "value1", "key2" -> "value2")
+
+    LoggingContext.get("key1") shouldBe Some("value1")
+    LoggingContext.get("key2") shouldBe Some("value2")
+  }
+
+  test("remove single") {
+    LoggingContext += ("key1" -> "value1")
+    LoggingContext += ("key2" -> "value2")
+    LoggingContext += ("key3" -> "value3")
+
+    LoggingContext -= "key1"
+
+    LoggingContext.get("key1") shouldBe None
+    LoggingContext.get("key2") shouldBe Some("value2")
+    LoggingContext.get("key3") shouldBe Some("value3")
+  }
+
+  test("remove multiple 1") {
+    LoggingContext += ("key1" -> "value1")
+    LoggingContext += ("key2" -> "value2")
+    LoggingContext += ("key3" -> "value3")
+
+    LoggingContext -= ("key1", "key2")
+
+    LoggingContext.get("key1") shouldBe None
+    LoggingContext.get("key2") shouldBe None
+    LoggingContext.get("key3") shouldBe Some("value3")
+  }
+
+  test("remove multiple 2") {
+    LoggingContext += ("key1" -> "value1")
+    LoggingContext += ("key2" -> "value2")
+    LoggingContext += ("key3" -> "value3")
+
+    LoggingContext --= Seq("key1", "key2")
+
+    LoggingContext.get("key1") shouldBe None
+    LoggingContext.get("key2") shouldBe None
+    LoggingContext.get("key3") shouldBe Some("value3")
+  }
+
+  test("clear, size, isEmpty") {
+    LoggingContext += ("key" -> "value")
+
+    LoggingContext.clear()
+
+    LoggingContext.contains("key") shouldBe false
+    LoggingContext.size shouldBe 0
+    LoggingContext.isEmpty shouldBe true
+  }
+
+  test("iterator") {
+    LoggingContext += ("key1" -> "value1")
+    LoggingContext += ("key2" -> "value2")
+
+    LoggingContext.iterator.toSet shouldBe Set("key1" -> "value1", "key2" -> 
"value2")
+  }
+
+  test("foreach") {
+    LoggingContext += ("key1" -> "value1")
+    LoggingContext += ("key2" -> "value2")
+
+    val result = mutable.Set.empty[(String, String)]
+
+    LoggingContext.foreach { result += _ }
+
+    result shouldBe Set("key1" -> "value1", "key2" -> "value2")
+  }
+
+}

Reply via email to