[CORDA-2522] Improve error reporting around failed flows (#5000)

* Improve error reporting around failed flows

* Fix an index to start from 1 when printed

* Address first set of review comments
This commit is contained in:
JamesHR3 2019-04-11 14:10:20 +01:00 committed by Anthony Keenan
parent a38891fc44
commit 24699cd7f4
5 changed files with 13 additions and 7 deletions

View File

@ -292,7 +292,7 @@ abstract class TransactionVerificationException(val txId: SecureHash, message: S
class UntrustedAttachmentsException(val txId: SecureHash, val ids: List<SecureHash>) :
CordaException("Attempting to load untrusted transaction attachments: $ids. " +
"At this time these are not loadable because the DJVM sandbox has not yet been integrated. " +
"You will need to install that app version yourself, to whitelist it for use. " +
"You will need to manually install the CorDapp to whitelist it for use. " +
"Please follow the operational steps outlined in https://docs.corda.net/cordapp-build-systems.html#cordapp-contract-attachments to learn more and continue.")
/*

View File

@ -125,8 +125,12 @@ class AttachmentsClassLoader(attachments: List<Attachment>,
}
.map(Attachment::id)
if (untrusted.isNotEmpty())
if (untrusted.isNotEmpty()) {
log.warn("Cannot verify transaction $sampleTxId as the following attachment IDs are untrusted: $untrusted." +
"You will need to manually install the CorDapp to whitelist it for use. " +
"Please follow the operational steps outlined in https://docs.corda.net/cordapp-build-systems.html#cordapp-contract-attachments to learn more and continue.")
throw TransactionVerificationException.UntrustedAttachmentsException(sampleTxId, untrusted)
}
// Enforce the no-overlap and package ownership rules.
checkAttachments(attachments)

View File

@ -243,7 +243,7 @@ class FlowStateMachineImpl<R>(override val id: StateMachineRunId,
if(t.isUnrecoverable()) {
errorAndTerminate("Caught unrecoverable error from flow. Forcibly terminating the JVM, this might leave resources open, and most likely will.", t)
}
logger.info("Flow raised an error... sending it to flow hospital", t)
logger.info("Flow raised an error: ${t.message}. Sending it to flow hospital to be triaged.")
Try.Failure<R>(t)
}
val softLocksId = if (hasSoftLockedStates) logic.runId.uuid else null

View File

@ -160,7 +160,8 @@ class StaffedFlowHospital(private val flowMessaging: FlowMessaging, private val
return errors
.asSequence()
.mapIndexed { index, error ->
log.info("Flow ${flowFiber.id} has error [$index]", error)
// Rely on the logging context to print details of the flow ID.
log.warn("Error ${index + 1} of ${errors.size}:", error)
val diagnoses: Map<Diagnosis, List<Staff>> = staff.groupBy { it.consult(flowFiber, currentState, error, medicalHistory) }
// We're only interested in the highest priority diagnosis for the error
val (diagnosis, by) = diagnoses.entries.minBy { it.key }!!

View File

@ -39,11 +39,12 @@ class DumpHistoryOnErrorInterceptor(val delegate: TransitionExecutor) : Transiti
(record ?: ArrayList()).apply { add(transitionRecord) }
}
// Just if we decide to propagate, and not if just on the way to the hospital.
// Just if we decide to propagate, and not if just on the way to the hospital. Only log at debug level here - the flow transition
// information is often unhelpful in the logs, and the actual cause of the problem will be logged elsewhere.
if (nextState.checkpoint.errorState is ErrorState.Errored && nextState.checkpoint.errorState.propagating) {
log.warn("Flow ${fiber.id} errored, dumping all transitions:\n${record!!.joinToString("\n")}")
log.debug("Flow ${fiber.id} errored, dumping all transitions:\n${record!!.joinToString("\n")}")
for (error in nextState.checkpoint.errorState.errors) {
log.warn("Flow ${fiber.id} error", error.exception)
log.debug("Flow ${fiber.id} error", error.exception)
}
}