aboutsummaryrefslogtreecommitdiff
path: root/src/main/scala/logger/Logger.scala
diff options
context:
space:
mode:
authorChick Markley2016-10-25 00:23:32 -0700
committerGitHub2016-10-25 00:23:32 -0700
commitd344f4400ad5e9c71c97229e33660bbe067260a0 (patch)
treee0426f4c9cc608db5c5f3a6a81f3873197424511 /src/main/scala/logger/Logger.scala
parentaca23a617999287183effea0272a4c95b27ff4b2 (diff)
Logger 1 (#338)
* Create a simple system for executions and command line parameters New model for tracking parameters and having those parameters register scopt command to allow the parameters to be set by command line args. Create composable forms of the these parameters to allow separate elements of the chisel3 toolchain to combine these parameters Create execution return structures that simplify return values to earlier toolchain elements * just a little bit of cleanup * Fixes for Adam's comments on PR * knuckled under to self-pressure to allow former -i and -o to work * knuckled under to self-pressure to allow former -i and -o to work * show defaults for command line args with them * A couple of fixes from merging latest master * Implement a log4scala like logging system This system has the rather remarkable property that it is possible to turn it on conveniently when you want it. It also provides for class level granularity as well as the traditional Error, Warn, Info, Debug * some style fixes and change infoMode default to append per PR #328 * some style fixes and change infoMode default to append per PR #328 * support -i -o and -X a couple of indentation and spacing fixes
Diffstat (limited to 'src/main/scala/logger/Logger.scala')
-rw-r--r--src/main/scala/logger/Logger.scala101
1 files changed, 101 insertions, 0 deletions
diff --git a/src/main/scala/logger/Logger.scala b/src/main/scala/logger/Logger.scala
new file mode 100644
index 00000000..07855c47
--- /dev/null
+++ b/src/main/scala/logger/Logger.scala
@@ -0,0 +1,101 @@
+// 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)
+ }
+ def warn(message: => String): Unit = {
+ Logger.showMessage(LogLevel.Warn, containerClass, message)
+ }
+ def info(message: => String): Unit = {
+ Logger.showMessage(LogLevel.Info, containerClass, message)
+ }
+ def debug(message: => String): Unit = {
+ Logger.showMessage(LogLevel.Debug, containerClass, message)
+ }
+ def trace(message: => String): Unit = {
+ Logger.showMessage(LogLevel.Trace, containerClass, message)
+ }
+}