Skip to content

Commit 93b881d

Browse files
authored
Merge pull request #83 from pwliwanow/master
Added Logger that takes an implicit parameter (e.g. CorrelationId)
2 parents 3e948c0 + a640207 commit 93b881d

File tree

6 files changed

+1001
-0
lines changed

6 files changed

+1001
-0
lines changed

README.md

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,49 @@ class MyClass extends LazyLogging {
7979
}
8080
```
8181

82+
`LoggerTakingImplicit` provides the same methods as `Logger` class, but with additional implicit parameter `A`.
83+
During creation of the `LoggerTakingImplicit` evidence `CanLog[A]` is required.
84+
It may be useful when contextual parameter (e.g. _Correlation ID_) is being passed around and you would like to include it in the log messages:
85+
86+
```scala
87+
case class CorrelationId(value: String)
88+
implicit case object CanLogCorrelationId extends CanLog[CorrelationId] {
89+
override def logMessage(originalMsg: String, a: CorrelationId): String = s"${a.value} $originalMsg"
90+
}
91+
92+
implicit val correlationId = CorrelationId("ID")
93+
94+
val logger = Logger.takingImplicit[CorrelationId]("test")
95+
logger.info("Test") // takes implicit correlationId and logs "ID Test"
96+
```
97+
98+
It's possible to use `MDC` through `CanLog` without any troubles with execution context.
99+
100+
```scala
101+
case class CorrelationId(value: String)
102+
implicit case object CanLogCorrelationId extends CanLog[CorrelationId] {
103+
override def logMessage(originalMsg: String, a: CorrelationId): String = {
104+
MDC.put("correlationId", a.value)
105+
originalMsg
106+
}
107+
108+
override def afterLog(a: A): Unit = {
109+
MDC.remove("correlationId")
110+
}
111+
}
112+
113+
implicit val correlationId = CorrelationId("ID")
114+
115+
val logger = Logger.takingImplicit[CorrelationId]("test")
116+
117+
def serviceMethod(implicit correlationId: CorrelationId): Future[Result] = {
118+
dbCall.map { value =>
119+
logger.trace(s"Received value $value from db") // takes implicit correlationId
120+
toResult(value)
121+
}
122+
}
123+
```
124+
82125
### What's new?
83126

84127
#### 3.7.2

src/main/scala/com/typesafe/scalalogging/Logger.scala

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,12 @@ object Logger {
3131
def apply(underlying: Underlying): Logger =
3232
new Logger(underlying)
3333

34+
/**
35+
* Create a [[LoggerTakingImplicit]] wrapping the given underlying `org.slf4j.Logger`.
36+
*/
37+
def takingImplicit[A](underlying: Underlying)(implicit ev: CanLog[A]): LoggerTakingImplicit[A] =
38+
new LoggerTakingImplicit[A](underlying)
39+
3440
/**
3541
* Create a [[Logger]] for the given name.
3642
* Example:
@@ -41,12 +47,28 @@ object Logger {
4147
def apply(name: String): Logger =
4248
new Logger(LoggerFactory.getLogger(name))
4349

50+
/**
51+
* Create a [[LoggerTakingImplicit]] for the given name.
52+
* Example:
53+
* {{{
54+
* val logger = Logger.takingImplicit[CorrelationId]("application")
55+
* }}}
56+
*/
57+
def takingImplicit[A](name: String)(implicit ev: CanLog[A]): LoggerTakingImplicit[A] =
58+
new LoggerTakingImplicit[A](LoggerFactory.getLogger(name))
59+
4460
/**
4561
* Create a [[Logger]] wrapping the created underlying `org.slf4j.Logger`.
4662
*/
4763
def apply(clazz: Class[_]): Logger =
4864
new Logger(LoggerFactory.getLogger(clazz.getName))
4965

66+
/**
67+
* Create a [[LoggerTakingImplicit]] wrapping the created underlying `org.slf4j.Logger`.
68+
*/
69+
def takingImplicit[A](clazz: Class[_])(implicit ev: CanLog[A]): LoggerTakingImplicit[A] =
70+
new LoggerTakingImplicit[A](LoggerFactory.getLogger(clazz.getName))
71+
5072
/**
5173
* Create a [[Logger]] for the runtime class wrapped by the implicit class
5274
* tag parameter.
@@ -57,6 +79,17 @@ object Logger {
5779
*/
5880
def apply[T](implicit ct: ClassTag[T]): Logger =
5981
new Logger(LoggerFactory.getLogger(ct.runtimeClass.getName.stripSuffix("$")))
82+
83+
/**
84+
* Create a [[LoggerTakingImplicit]] for the runtime class wrapped by the implicit class
85+
* tag parameter.
86+
* Example:
87+
* {{{
88+
* val logger = Logger.takingImplicit[MyClass, CorrelationId]
89+
* }}}
90+
*/
91+
def takingImplicit[T, A](implicit ct: ClassTag[T], ev: CanLog[A]): LoggerTakingImplicit[A] =
92+
new LoggerTakingImplicit[A](LoggerFactory.getLogger(ct.runtimeClass.getName.stripSuffix("$")))
6093
}
6194

6295
/**
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
package com.typesafe.scalalogging
2+
3+
import org.slf4j.{ Marker, Logger => Underlying }
4+
5+
trait CanLog[A] {
6+
def logMessage(originalMsg: String, a: A): String
7+
def afterLog(a: A): Unit = ()
8+
}
9+
10+
@SerialVersionUID(957385465L)
11+
final class LoggerTakingImplicit[A] private[scalalogging] (val underlying: Underlying)(implicit val canLogEv: CanLog[A]) extends Serializable {
12+
13+
// Error
14+
15+
def error(message: String)(implicit a: A): Unit = macro LoggerTakingImplicitMacro.errorMessage[A]
16+
17+
def error(message: String, cause: Throwable)(implicit a: A): Unit = macro LoggerTakingImplicitMacro.errorMessageCause[A]
18+
19+
def error(message: String, args: Any*)(implicit a: A): Unit = macro LoggerTakingImplicitMacro.errorMessageArgs[A]
20+
21+
def error(marker: Marker, message: String)(implicit a: A): Unit = macro LoggerTakingImplicitMacro.errorMessageMarker[A]
22+
23+
def error(marker: Marker, message: String, cause: Throwable)(implicit a: A): Unit = macro LoggerTakingImplicitMacro.errorMessageCauseMarker[A]
24+
25+
def error(marker: Marker, message: String, args: Any*)(implicit a: A): Unit = macro LoggerTakingImplicitMacro.errorMessageArgsMarker[A]
26+
27+
// Warn
28+
29+
def warn(message: String)(implicit a: A): Unit = macro LoggerTakingImplicitMacro.warnMessage[A]
30+
31+
def warn(message: String, cause: Throwable)(implicit a: A): Unit = macro LoggerTakingImplicitMacro.warnMessageCause[A]
32+
33+
def warn(message: String, args: Any*)(implicit a: A): Unit = macro LoggerTakingImplicitMacro.warnMessageArgs[A]
34+
35+
def warn(marker: Marker, message: String)(implicit a: A): Unit = macro LoggerTakingImplicitMacro.warnMessageMarker[A]
36+
37+
def warn(marker: Marker, message: String, cause: Throwable)(implicit a: A): Unit = macro LoggerTakingImplicitMacro.warnMessageCauseMarker[A]
38+
39+
def warn(marker: Marker, message: String, args: Any*)(implicit a: A): Unit = macro LoggerTakingImplicitMacro.warnMessageArgsMarker[A]
40+
41+
// Info
42+
43+
def info(message: String)(implicit a: A): Unit = macro LoggerTakingImplicitMacro.infoMessage[A]
44+
45+
def info(message: String, cause: Throwable)(implicit a: A): Unit = macro LoggerTakingImplicitMacro.infoMessageCause[A]
46+
47+
def info(message: String, args: Any*)(implicit a: A): Unit = macro LoggerTakingImplicitMacro.infoMessageArgs[A]
48+
49+
def info(marker: Marker, message: String)(implicit a: A): Unit = macro LoggerTakingImplicitMacro.infoMessageMarker[A]
50+
51+
def info(marker: Marker, message: String, cause: Throwable)(implicit a: A): Unit = macro LoggerTakingImplicitMacro.infoMessageCauseMarker[A]
52+
53+
def info(marker: Marker, message: String, args: Any*)(implicit a: A): Unit = macro LoggerTakingImplicitMacro.infoMessageArgsMarker[A]
54+
55+
// Debug
56+
57+
def debug(message: String)(implicit a: A): Unit = macro LoggerTakingImplicitMacro.debugMessage[A]
58+
59+
def debug(message: String, cause: Throwable)(implicit a: A): Unit = macro LoggerTakingImplicitMacro.debugMessageCause[A]
60+
61+
def debug(message: String, args: Any*)(implicit a: A): Unit = macro LoggerTakingImplicitMacro.debugMessageArgs[A]
62+
63+
def debug(marker: Marker, message: String)(implicit a: A): Unit = macro LoggerTakingImplicitMacro.debugMessageMarker[A]
64+
65+
def debug(marker: Marker, message: String, cause: Throwable)(implicit a: A): Unit = macro LoggerTakingImplicitMacro.debugMessageCauseMarker[A]
66+
67+
def debug(marker: Marker, message: String, args: Any*)(implicit a: A): Unit = macro LoggerTakingImplicitMacro.debugMessageArgsMarker[A]
68+
69+
// Trace
70+
71+
def trace(message: String)(implicit a: A): Unit = macro LoggerTakingImplicitMacro.traceMessage[A]
72+
73+
def trace(message: String, cause: Throwable)(implicit a: A): Unit = macro LoggerTakingImplicitMacro.traceMessageCause[A]
74+
75+
def trace(message: String, args: Any*)(implicit a: A): Unit = macro LoggerTakingImplicitMacro.traceMessageArgs[A]
76+
77+
def trace(marker: Marker, message: String)(implicit a: A): Unit = macro LoggerTakingImplicitMacro.traceMessageMarker[A]
78+
79+
def trace(marker: Marker, message: String, cause: Throwable)(implicit a: A): Unit = macro LoggerTakingImplicitMacro.traceMessageCauseMarker[A]
80+
81+
def trace(marker: Marker, message: String, args: Any*)(implicit a: A): Unit = macro LoggerTakingImplicitMacro.traceMessageArgsMarker[A]
82+
83+
}

0 commit comments

Comments
 (0)