[CORDA-1996]: Apply error code to exceptions that do not propagate to NodeStartup. (#3964)

This commit is contained in:
Michele Sollecito
2018-09-19 14:24:21 +02:00
committed by GitHub
parent 4fd8a8fb29
commit 19b8f70117
7 changed files with 67 additions and 8 deletions

View File

@ -8,7 +8,6 @@ import net.corda.core.flows.InitiatingFlow
import net.corda.core.flows.StartableByRPC
import net.corda.core.identity.Party
import net.corda.core.internal.concurrent.map
import net.corda.core.messaging.CordaRPCOps
import net.corda.core.messaging.startFlow
import net.corda.core.utilities.contextLogger
import net.corda.core.utilities.getOrThrow
@ -28,7 +27,6 @@ import org.assertj.core.api.AssertionsForInterfaceTypes.assertThat
import org.junit.After
import org.junit.Before
import org.junit.Test
import rx.Observable
import java.util.concurrent.CountDownLatch
import java.util.concurrent.Executors
import java.util.concurrent.ScheduledExecutorService

View File

@ -154,9 +154,9 @@ open class NodeStartup : CordaCliWrapper("corda", "Runs a Corda Node") {
private val startNodeExpectedErrors = setOf(MultipleCordappsForFlowException::class, CheckpointIncompatibleException::class, AddressBindingException::class, NetworkParametersReader::class, DatabaseIncompatibleException::class)
private fun Exception.logAsExpected(message: String? = this.message, print: (String?) -> Unit = logger::error) = print("$message [errorCode=${errorCode()}]")
private fun Exception.logAsExpected(message: String? = this.message, print: (String?) -> Unit = logger::error) = print(message)
private fun Exception.logAsUnexpected(message: String? = this.message, error: Exception = this, print: (String?, Throwable) -> Unit = logger::error) = print("$message${this.message?.let { ": $it" } ?: ""} [errorCode=${errorCode()}]", error)
private fun Exception.logAsUnexpected(message: String? = this.message, error: Exception = this, print: (String?, Throwable) -> Unit = logger::error) = print("$message${this.message?.let { ": $it" } ?: ""}", error)
private fun Exception.isOpenJdkKnownIssue() = message?.startsWith("Unknown named curve:") == true

View File

@ -735,9 +735,11 @@ class DriverDSLImpl(
val systemProperties = mutableMapOf(
"name" to config.corda.myLegalName,
"visualvm.display.name" to "corda-${config.corda.myLegalName}",
"log4j2.debug" to if (debugPort != null) "true" else "false"
"visualvm.display.name" to "corda-${config.corda.myLegalName}"
)
debugPort?.let {
systemProperties += "log4j2.debug" to "true"
}
systemProperties += inheritFromParentProcess()
systemProperties += overriddenSystemProperties

View File

@ -11,6 +11,7 @@ dependencies {
compile "info.picocli:picocli:$picocli_version"
compile "com.jcabi:jcabi-manifests:$jcabi_manifests_version"
compile "org.slf4j:slf4j-api:$slf4j_version"
compile "org.apache.logging.log4j:log4j-slf4j-impl:$log4j_version"
// JAnsi: for drawing things to the terminal in nicely coloured ways.
compile "org.fusesource.jansi:jansi:$jansi_version"

View File

@ -0,0 +1,35 @@
package net.corda.cliutils
import org.apache.logging.log4j.core.LoggerContext
import org.apache.logging.log4j.core.config.Configuration
import org.apache.logging.log4j.core.config.ConfigurationFactory
import org.apache.logging.log4j.core.config.ConfigurationSource
import org.apache.logging.log4j.core.config.Order
import org.apache.logging.log4j.core.config.plugins.Plugin
import org.apache.logging.log4j.core.config.xml.XmlConfiguration
import org.apache.logging.log4j.core.impl.LogEventFactory
@Plugin(name = "CordaLog4j2ConfigFactory", category = "ConfigurationFactory")
@Order(10)
class CordaLog4j2ConfigFactory : ConfigurationFactory() {
private companion object {
private val SUPPORTED_TYPES = arrayOf(".xml", "*")
}
override fun getConfiguration(loggerContext: LoggerContext, source: ConfigurationSource): Configuration = ErrorCodeAppendingConfiguration(loggerContext, source)
override fun getSupportedTypes() = SUPPORTED_TYPES
private class ErrorCodeAppendingConfiguration(loggerContext: LoggerContext, source: ConfigurationSource) : XmlConfiguration(loggerContext, source) {
override fun doConfigure() {
super.doConfigure()
loggers.values.forEach {
val existingFactory = it.logEventFactory
it.logEventFactory = LogEventFactory { loggerName, marker, fqcn, level, message, properties, error -> existingFactory.createEvent(loggerName, marker, fqcn, level, message?.withErrorCodeFor(error, level), properties, error) }
}
}
}
}

View File

@ -1,13 +1,26 @@
package net.corda.node.internal
package net.corda.cliutils
import org.apache.logging.log4j.Level
import org.apache.logging.log4j.message.Message
import org.apache.logging.log4j.message.SimpleMessage
import java.util.*
fun Exception.errorCode(hashedFields: (Throwable) -> Array<out Any?> = Throwable::defaultHashedFields): String {
internal fun Message.withErrorCodeFor(error: Throwable?, level: Level): Message {
return when {
error != null && level.isInRange(Level.FATAL, Level.WARN) -> CompositeMessage("$formattedMessage [errorCode=${error.errorCode()}]", format, parameters, throwable)
else -> this
}
}
private fun Throwable.errorCode(hashedFields: (Throwable) -> Array<out Any?> = Throwable::defaultHashedFields): String {
val hash = staticLocationBasedHash(hashedFields)
return hash.toBase(36)
}
private fun Throwable.staticLocationBasedHash(hashedFields: (Throwable) -> Array<out Any?>, visited: Set<Throwable> = setOf(this)): Int {
val cause = this.cause
val fields = hashedFields.invoke(this)
return when {
@ -37,3 +50,12 @@ private fun StackTraceElement.defaultHashedFields(): Array<out Any?> {
return arrayOf(className, methodName)
}
private class CompositeMessage(message: String?, private val formatArg: String?, private val parameters: Array<out Any?>?, private val error: Throwable?) : SimpleMessage(message) {
override fun getThrowable(): Throwable? = error
override fun getParameters(): Array<out Any?>? = parameters
override fun getFormat(): String? = formatArg
}

View File

@ -0,0 +1 @@
log4j.configurationFactory=net.corda.cliutils.CordaLog4j2ConfigFactory