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
|
// See LICENSE for license details.
package logger
import java.io.{PrintStream, File, FileOutputStream}
import firrtl.ExecutionOptionsManager
/**
* This provides a facility for a log4scala* type logging system. Why did we write our own? Because
* the canned ones are just to darned hard to turn on, particularly when embedded in a distribution.
* This one can be turned on programmatically or with the options exposed in the [[firrtl.CommonOptions]]
* and [[ExecutionOptionsManager]] API's in firrtl.
* There are 4 main options.
* * a simple global option to turn on all in scope (and across threads, might want to fix this)
* * turn on specific levels for specific fully qualified class names
* * set a file to write things to, default is just to use stdout
* * include the class names and level in the output. This is useful to figure out what
* the class names that extend LazyLogger are
*
* This is not overly optimized but does pass the string as () => String to avoid string interpolation
* occurring if the the logging level is not sufficiently high. This could be further optimized by playing
* with methods
*/
/**
* The supported log levels, what do they mean? Whatever you want them to.
*/
object LogLevel extends Enumeration {
val Error, Warn, Info, Debug, Trace = Value
}
/**
* extend this trait to enable logging in a class you are implementing
*/
trait LazyLogging {
val logger = new Logger(this.getClass.getName)
}
/**
* Singleton in control of what is supposed to get logged, how it's to be logged and where it is to be logged
*/
object Logger {
var globalLevel = LogLevel.Error
val classLevels = new scala.collection.mutable.HashMap[String, LogLevel.Value]
var logClassNames = false
def showMessage(level: LogLevel.Value, className: String, message: => String): Unit = {
if(globalLevel == level || (classLevels.nonEmpty && classLevels.getOrElse(className, LogLevel.Error) >= level)) {
if(logClassNames) {
stream.println(s"[$level:$className] $message")
}
else {
stream.println(message)
}
}
}
var stream: PrintStream = System.out
def setOutput(fileName: String): Unit = {
stream = new PrintStream(new FileOutputStream(new File(fileName)))
}
def setConsole(): Unit = {
stream = Console.out
}
def setClassLogLevels(namesToLevel: Map[String, LogLevel.Value]): Unit = {
classLevels ++= namesToLevel
}
def setOptions(optionsManager: ExecutionOptionsManager): Unit = {
val commonOptions = optionsManager.commonOptions
globalLevel = commonOptions.globalLogLevel
setClassLogLevels(commonOptions.classLogLevels)
if(commonOptions.logToFile) {
setOutput(commonOptions.getLogFileName(optionsManager))
}
logClassNames = commonOptions.logClassNames
}
}
/**
* Classes implementing [[LazyLogging]] will have logger of this type
* @param containerClass passed in from the LazyLogging trait in order to provide class level logging granularity
*/
class Logger(containerClass: String) {
def error(message: => String): Unit = {
Logger.showMessage(LogLevel.Error, containerClass, message)
Logger.showMessage(LogLevel.Debug, containerClass, message)
}
def warn(message: => String): Unit = {
Logger.showMessage(LogLevel.Warn, containerClass, message)
Logger.showMessage(LogLevel.Debug, containerClass, message)
}
def info(message: => String): Unit = {
Logger.showMessage(LogLevel.Info, containerClass, message)
Logger.showMessage(LogLevel.Debug, containerClass, message)
}
def debug(message: => String): Unit = {
Logger.showMessage(LogLevel.Debug, containerClass, message)
}
def trace(message: => String): Unit = {
Logger.showMessage(LogLevel.Trace, containerClass, message)
Logger.showMessage(LogLevel.Debug, containerClass, message)
}
}
|