-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathLogger.scala
118 lines (102 loc) · 3.08 KB
/
Logger.scala
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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
package frankenpaxos
import Ordering.Implicits._
sealed trait LogLevel
object LogDebug extends LogLevel
object LogInfo extends LogLevel
object LogWarn extends LogLevel
object LogError extends LogLevel
object LogFatal extends LogLevel
object LogLevel {
implicit val read: scopt.Read[LogLevel] = scopt.Read.reads({
case "debug" => LogDebug
case "info" => LogInfo
case "warn" => LogWarn
case "error" => LogError
case "fatal" => LogFatal
case x =>
throw new IllegalArgumentException(
s"$x is not one of debug, info, warn, error, or fatal."
)
})
}
// A logger can be used to log messages and check that certain invariants hold.
//
// A logger can log messages with five different severities (or levels): debug,
// info, warn, error, and fatal. The `logLevel` parameter passed to a Logger
// can selectively disable the logging of certain log levels. For example, a
// logger constructed with log level warn will log messages with level warn,
// error, or fatal. It will not log debug or info messages. If you think a
// message might be logged often, it's best to make it debug so that it can be
// turned off for benchmarking.
abstract class Logger(logLevel: LogLevel) {
// Logging.
def fatal(message: String): Nothing = {
fatalImpl(message)
}
def error(message: => String): Unit = {
logLevel match {
case LogDebug | LogInfo | LogWarn | LogError => errorImpl(message)
case LogFatal =>
}
}
def warn(message: => String): Unit = {
logLevel match {
case LogDebug | LogInfo | LogWarn => warnImpl(message)
case LogError | LogFatal =>
}
}
def info(message: => String): Unit = {
logLevel match {
case LogDebug | LogInfo => infoImpl(message)
case LogWarn | LogError | LogFatal =>
}
}
def debug(message: => String): Unit = {
logLevel match {
case LogDebug => debugImpl(message)
case LogInfo | LogWarn | LogError | LogFatal =>
}
}
// Logging implementations.
def fatalImpl(message: String): Nothing
def errorImpl(message: String): Unit
def warnImpl(message: String): Unit
def infoImpl(message: String): Unit
def debugImpl(message: String): Unit
// Checking.
def check(b: Boolean): Unit = {
if (!b) {
fatal("Check failed!")
}
}
def checkEq[A](lhs: A, rhs: A): Unit = {
if (lhs != rhs) {
fatal(s"Check failed: $lhs != $rhs.")
}
}
def checkNe[A](lhs: A, rhs: A): Unit = {
if (lhs == rhs) {
fatal(s"Check failed: $lhs == $rhs.")
}
}
def checkLt[A: Ordering](lhs: A, rhs: A): Unit = {
if (lhs >= rhs) {
fatal(s"Check failed: $lhs >= $rhs.")
}
}
def checkLe[A: Ordering](lhs: A, rhs: A): Unit = {
if (lhs > rhs) {
fatal(s"Check failed: $lhs > $rhs.")
}
}
def checkGt[A: Ordering](lhs: A, rhs: A): Unit = {
if (lhs <= rhs) {
fatal(s"Check failed: $lhs <= $rhs.")
}
}
def checkGe[A: Ordering](lhs: A, rhs: A): Unit = {
if (lhs < rhs) {
fatal(s"Check failed: $lhs < $rhs.")
}
}
}