Skip to content

Commit

Permalink
airspec (feature): Support -L(wildcard pattern)=(log level) (#3559)
Browse files Browse the repository at this point in the history
  • Loading branch information
xerial authored Jun 7, 2024
1 parent ef866fe commit 77cc634
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 8 deletions.
22 changes: 22 additions & 0 deletions airframe-log/src/main/scala/wvlet/log/Logger.scala
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,28 @@ object Logger {
}
}

/**
* Reset log level set by the given pattern
* @param pattern
*/
def resetLogLevel(pattern: String): Unit = {
if (pattern.contains("*")) {
val regexPattern = pattern.replaceAll("\\.", "\\\\.").replaceAll("\\*", ".*").r
val regexPatternStr = regexPattern.regex
synchronized {
logLevelPatterns = logLevelPatterns.filter(x => x._1.regex != regexPatternStr)
}
// Reset the log level of already created loggers matching the removed pattern
loggerCache.values.foreach { l =>
if (regexPattern.findFirstIn(l.getName).isDefined) {
l.resetLogLevel
}
}
} else {
Logger(pattern).resetLogLevel
}
}

def setDefaultFormatter(formatter: LogFormatter): Unit = {
synchronized {
rootLogger.resetHandler(new ConsoleLogHandler(formatter))
Expand Down
8 changes: 8 additions & 0 deletions airframe-log/src/test/scala/wvlet/log/LogLevelTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,12 @@ class LogLevelTest extends Spec {
Logger.setLogLevel("example.app", LogLevel.WARN)
l.getLogLevel shouldBe LogLevel.WARN
}

test("Reset log level set by a pattern") {
val l = Logger.setLogLevel("example.*", LogLevel.WARN)
Logger("example.app").getLogLevel shouldBe LogLevel.WARN

Logger.resetLogLevel("example.*")
Logger("example.app").getLogLevel shouldBe LogLevel.INFO
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -87,19 +87,18 @@ private[airspec] class AirSpecTaskRunner(
* Run this AirSpec task
*/
def runTask: Future[Unit] = {
val startTimeNanos = System.nanoTime()
val prevLogLevel = Map.newBuilder[String, LogLevel]
prevLogLevel += testClassName -> Logger(testClassName).getLogLevel
val startTimeNanos = System.nanoTime()
var loggerNamePatterns: List[String] = List(testClassName)

Future
.apply {
// Set the default log level for the class
Logger(testClassName).setLogLevel(config.defaultLogLevel)

// Set log level for other classes
config.additionalLogLevels.foreach { case (pkg, level) =>
prevLogLevel += pkg -> Logger(pkg).getLogLevel
Logger(pkg).setLogLevel(level)
config.additionalLogLevels.foreach { case (pattern, level) =>
loggerNamePatterns = pattern :: loggerNamePatterns
Logger.setLogLevel(pattern, level)
}

// Start a background log level scanner thread. If a thread is already running, reuse it.
Expand All @@ -121,8 +120,8 @@ private[airspec] class AirSpecTaskRunner(
compat.stopLogScanner

// Reset log levels
prevLogLevel.result().foreach { case (pkg, level) =>
Logger(pkg).setLogLevel(level)
loggerNamePatterns.foreach { pattern =>
Logger.resetLogLevel(pattern)
}
ret
}
Expand Down
5 changes: 5 additions & 0 deletions docs/airspec.md
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,11 @@ To change the log level only for a specific package or a class, use `-L(package
```
You can use multiple `-L` options to set different log levels for multiple packages.

You can also use wildcard `*` with `-L` option for the ease of setting log levels for specific classes:
```scala
> testOnly -- -Lmyapp.*=debug
> testOnly -- -L*.MyClass=debug
```

### Configure Log Levels in log-test.properties

Expand Down

0 comments on commit 77cc634

Please sign in to comment.