-
Notifications
You must be signed in to change notification settings - Fork 360
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Like log4j was replaced also replace commons-logging with slf4j. - Cromwell redirects java.util.logging calls to slf4j, only known to affect Liquibase as of now. - Separate Liquibase workaround to print to logger instead of System.out. - In Cromwell/Cromiam log the time Akka events are generated, not the time they arrive at slf4j. - In Cromwell/Cromiam log the thread where Akka events are generated, not the thread performing the logging.
- Loading branch information
Showing
12 changed files
with
206 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
70 changes: 70 additions & 0 deletions
70
core/src/main/scala/cromwell/core/logging/EnhancedDateConverter.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
package cromwell.core.logging | ||
|
||
import ch.qos.logback.classic.pattern.DateConverter | ||
import ch.qos.logback.classic.spi.ILoggingEvent | ||
import ch.qos.logback.core.CoreConstants | ||
import ch.qos.logback.core.util.CachingDateFormatter | ||
|
||
import java.util.TimeZone | ||
import scala.jdk.CollectionConverters._ | ||
|
||
/** | ||
* Log the Akka akkaTimestamp if found in the MDC, otherwise log the original event timestamp. | ||
* | ||
* - https://doc.akka.io/docs/akka/current/logging.html#more-accurate-timestamps-for-log-output-in-mdc | ||
* - https://logback.qos.ch/manual/layouts.html#customConversionSpecifier | ||
* | ||
* NOTE: For proper configuration both this EnhancedDateConverter should be configured into the logback.xml AND the | ||
* configuration file should set akka.loggers = ["cromwell.core.logging.EnhancedSlf4jLogger"]. | ||
*/ | ||
class EnhancedDateConverter extends DateConverter { | ||
protected var cachingDateFormatterProtected: CachingDateFormatter = _ | ||
|
||
/* Duplicated from ch.qos.logback.classic.pattern.DateConverter as cachingDateFormatter is package private. */ | ||
override def start(): Unit = { | ||
cachingDateFormatterProtected = Option(getFirstOption) match { | ||
case Some(CoreConstants.ISO8601_STR) | None => new CachingDateFormatter(CoreConstants.ISO8601_PATTERN) | ||
case Some(datePattern) => | ||
try { | ||
new CachingDateFormatter(datePattern) | ||
} catch { | ||
case e: IllegalArgumentException => | ||
addWarn("Could not instantiate SimpleDateFormat with pattern " + datePattern, e) | ||
// default to the ISO8601 format | ||
new CachingDateFormatter(CoreConstants.ISO8601_PATTERN) | ||
} | ||
} | ||
// if the option list contains a TZ option, then set it. | ||
Option(getOptionList) | ||
.toList | ||
.flatMap(_.asScala) | ||
.drop(1) | ||
.headOption | ||
.map(TimeZone.getTimeZone) | ||
.foreach(cachingDateFormatterProtected.setTimeZone) | ||
|
||
// Allow the parent class to start/initialize its private members. | ||
super.start() | ||
} | ||
|
||
/** | ||
* Look for the Akka timestamp and use that to format the date. | ||
* | ||
* Until this (currently 6+ year) issue is resolved, formatting the date as a Long requires using the | ||
* [[EnhancedSlf4jLogger]] versus Akka's basic Slf4jLogger. | ||
* | ||
* - https://github.com/akka/akka/issues/18079#issuecomment-125175884 | ||
*/ | ||
override def convert(event: ILoggingEvent): String = { | ||
val mdc = event.getMDCPropertyMap | ||
if (mdc.containsKey("akkaTimestamp")) { | ||
val timestamp = mdc.get("akkaTimestamp") | ||
timestamp.toLongOption match { | ||
case Some(value) => cachingDateFormatterProtected.format(value) | ||
case None => timestamp // Return the original timestamp string. | ||
} | ||
} else { | ||
super.convert(event) | ||
} | ||
} | ||
} |
16 changes: 16 additions & 0 deletions
16
core/src/main/scala/cromwell/core/logging/EnhancedSlf4jLogger.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package cromwell.core.logging | ||
|
||
import akka.event.slf4j.Slf4jLogger | ||
|
||
class EnhancedSlf4jLogger extends Slf4jLogger { | ||
/** | ||
* Format the timestamp as a simple long. Allows the akkaTimestamp to be retrieved later from the MDC by custom | ||
* converters. | ||
* | ||
* NOTE: Should not be necessary once this issue is resolved: | ||
* - https://github.com/akka/akka/issues/18079#issuecomment-125175884 | ||
* | ||
* @see [[EnhancedDateConverter.convert()]] | ||
*/ | ||
override protected def formatTimestamp(timestamp: Long): String = String.valueOf(timestamp) | ||
} |
21 changes: 21 additions & 0 deletions
21
core/src/main/scala/cromwell/core/logging/EnhancedThreadConverter.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
package cromwell.core.logging | ||
|
||
import ch.qos.logback.classic.pattern.ThreadConverter | ||
import ch.qos.logback.classic.spi.ILoggingEvent | ||
|
||
/** | ||
* Log the Akka sourceThread if found, otherwise log the event thread. | ||
* | ||
* - https://doc.akka.io/docs/akka/current/logging.html#logging-thread-akka-source-and-actor-system-in-mdc | ||
* - https://logback.qos.ch/manual/layouts.html#customConversionSpecifier | ||
*/ | ||
class EnhancedThreadConverter extends ThreadConverter { | ||
override def convert(event: ILoggingEvent): String = { | ||
val mdc = event.getMDCPropertyMap | ||
if (mdc.containsKey("sourceThread")) { | ||
mdc.get("sourceThread") | ||
} else { | ||
super.convert(event) | ||
} | ||
} | ||
} |
39 changes: 39 additions & 0 deletions
39
core/src/main/scala/cromwell/core/logging/JavaLoggingBridge.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
package cromwell.core.logging | ||
|
||
import ch.qos.logback.classic.LoggerContext | ||
import ch.qos.logback.classic.jul.LevelChangePropagator | ||
import org.slf4j.LoggerFactory | ||
import org.slf4j.bridge.SLF4JBridgeHandler | ||
|
||
import scala.jdk.CollectionConverters._ | ||
|
||
object JavaLoggingBridge { | ||
/** | ||
* Replace java.util.logging with SLF4J while ensuring Logback is configured with a LevelChangePropogator. | ||
* | ||
* One likely won't need to do this but just in case: note that any libraries using JUL running BEFORE this | ||
* initialization which require increasing or decreasing verbosity must be configured via JUL not Logback. | ||
* | ||
* See also: | ||
* - https://www.slf4j.org/api/org/slf4j/bridge/SLF4JBridgeHandler.html | ||
* - https://docs.oracle.com/en/java/javase/11/docs/api/java.logging/java/util/logging/LogManager.html | ||
*/ | ||
def init(): Unit = { | ||
// Retrieve the Logback context, and as a side effect initialize Logback. | ||
val ctx = LoggerFactory.getILoggerFactory.asInstanceOf[LoggerContext] | ||
|
||
// Ensure that Logback has a LevelChangePropagator, either here or via a logback.xml. | ||
val listeners = ctx.getCopyOfListenerList.asScala | ||
if (!listeners.exists(_.isInstanceOf[LevelChangePropagator])) { | ||
val propagator = new LevelChangePropagator() | ||
propagator.setContext(ctx) | ||
propagator.start() | ||
} | ||
|
||
// Remove all the JUL logging handlers. | ||
SLF4JBridgeHandler.removeHandlersForRootLogger() | ||
|
||
// Send all JUL logging to SLF4J. | ||
SLF4JBridgeHandler.install() | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters