Implemented logging and adding to MessageLogEntry job number, dialog number and account
This commit is contained in:
parent
c2b3a8fb5f
commit
d6305b52be
|
@ -0,0 +1,12 @@
|
||||||
|
package net.dankito.banking.fints.log
|
||||||
|
|
||||||
|
import net.dankito.banking.fints.model.AccountData
|
||||||
|
import net.dankito.banking.fints.model.BankData
|
||||||
|
|
||||||
|
|
||||||
|
class MessageContext(
|
||||||
|
val jobNumber: Int,
|
||||||
|
val dialogNumber: Int,
|
||||||
|
val bank: BankData,
|
||||||
|
val account: AccountData?
|
||||||
|
)
|
|
@ -7,6 +7,7 @@ import net.dankito.utils.multiplatform.log.Logger
|
||||||
import net.dankito.utils.multiplatform.log.LoggerFactory
|
import net.dankito.utils.multiplatform.log.LoggerFactory
|
||||||
import net.dankito.utils.multiplatform.Date
|
import net.dankito.utils.multiplatform.Date
|
||||||
import net.dankito.utils.multiplatform.StackTraceHelper
|
import net.dankito.utils.multiplatform.StackTraceHelper
|
||||||
|
import net.dankito.utils.multiplatform.StringHelper
|
||||||
import net.dankito.utils.multiplatform.getInnerException
|
import net.dankito.utils.multiplatform.getInnerException
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
|
@ -27,37 +28,60 @@ open class MessageLogCollector {
|
||||||
|
|
||||||
// in either case remove sensitive data after response is parsed as otherwise some information like account holder name and accounts may is not set yet on BankData
|
// in either case remove sensitive data after response is parsed as otherwise some information like account holder name and accounts may is not set yet on BankData
|
||||||
open val messageLogWithoutSensitiveData: List<MessageLogEntry>
|
open val messageLogWithoutSensitiveData: List<MessageLogEntry>
|
||||||
get() = messageLog.map { MessageLogEntry(safelyRemoveSensitiveDataFromMessage(it.message, it.bank), it.type, it.time, it.bank) }
|
get() = messageLog.map { MessageLogEntry(it.type, safelyRemoveSensitiveDataFromMessage(it.message, it.context.bank), it.time, it.context) }
|
||||||
|
|
||||||
|
|
||||||
protected open val stackTraceHelper = StackTraceHelper()
|
protected open val stackTraceHelper = StackTraceHelper()
|
||||||
|
|
||||||
|
|
||||||
open fun addMessageLog(bank: BankData, type: MessageLogEntryType, message: String) {
|
open fun addMessageLog(type: MessageLogEntryType, message: String, context: MessageContext) {
|
||||||
val timeStamp = Date()
|
val timeStamp = Date()
|
||||||
val prettyPrintMessage = prettyPrintHbciMessage(message)
|
val prettyPrintMessage = prettyPrintHbciMessage(message)
|
||||||
|
|
||||||
messageLog.add(MessageLogEntry(prettyPrintMessage, type, timeStamp, bank))
|
messageLog.add(MessageLogEntry(type, prettyPrintMessage, timeStamp, context))
|
||||||
|
|
||||||
log.debug { "${if (type == MessageLogEntryType.Sent) "[${bank.bankCode}-${bank.customerId}] Sending" else "Received"} message:\r\n" + prettyPrintMessage }
|
val messageTrace = createMessageTraceString(type, context)
|
||||||
}
|
log.debug { "$messageTrace\r\n$prettyPrintMessage" }
|
||||||
|
|
||||||
protected open fun prettyPrintHbciMessage(message: String): String {
|
|
||||||
return message.replace("'", "'\r\n")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
open fun logError(loggingClass: KClass<*>, bank: BankData, message: String, e: Exception? = null) {
|
open fun logError(loggingClass: KClass<*>, message: String, context: MessageContext, e: Exception? = null) {
|
||||||
|
val type = MessageLogEntryType.Error
|
||||||
|
val messageTrace = createMessageTraceString(type, context) + " "
|
||||||
|
|
||||||
if (e != null) {
|
if (e != null) {
|
||||||
getLogger(loggingClass).error(e) { message }
|
getLogger(loggingClass).error(e) { messageTrace + message }
|
||||||
} else {
|
} else {
|
||||||
getLogger(loggingClass).error(message)
|
getLogger(loggingClass).error(messageTrace + message)
|
||||||
}
|
}
|
||||||
|
|
||||||
val errorStackTrace = if (e != null) "\r\n" + getStackTrace(e) else ""
|
val errorStackTrace = if (e != null) "\r\n" + getStackTrace(e) else ""
|
||||||
|
|
||||||
// TODO: what to do when bank is not set?
|
messageLog.add(MessageLogEntry(type, message + errorStackTrace, Date(), context))
|
||||||
messageLog.add(MessageLogEntry(message + errorStackTrace, MessageLogEntryType.Error, Date(), bank))
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected open fun createMessageTraceString(type: MessageLogEntryType, context: MessageContext): String {
|
||||||
|
return "${twoDigits(context.jobNumber)}_${twoDigits(context.dialogNumber)}_" +
|
||||||
|
"${context.bank.bankCode}_${context.bank.customerId}" +
|
||||||
|
"${ context.account?.let { "_${it.accountIdentifier}" } ?: "" } " +
|
||||||
|
"${getTypeString(type)}:"
|
||||||
|
}
|
||||||
|
|
||||||
|
protected open fun twoDigits(number: Int): String {
|
||||||
|
return StringHelper.format("%02d", number)
|
||||||
|
}
|
||||||
|
|
||||||
|
protected open fun getTypeString(type: MessageLogEntryType): String {
|
||||||
|
return when (type) {
|
||||||
|
MessageLogEntryType.Sent -> "Sending message"
|
||||||
|
MessageLogEntryType.Received -> "Received message"
|
||||||
|
MessageLogEntryType.Error -> "Error"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected open fun prettyPrintHbciMessage(message: String): String {
|
||||||
|
return message.replace("'", "'\r\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -6,14 +6,9 @@ import net.dankito.banking.fints.response.BankResponse
|
||||||
|
|
||||||
|
|
||||||
open class DialogContext(
|
open class DialogContext(
|
||||||
val closeDialog: Boolean = true,
|
open val closeDialog: Boolean = true,
|
||||||
var abortIfTanIsRequired: Boolean = false,
|
open var dialogId: String = InitialDialogId,
|
||||||
var currentMessage: MessageBuilderResult? = null,
|
open var chunkedResponseHandler: ((BankResponse) -> Unit)? = null
|
||||||
var dialogId: String = InitialDialogId,
|
|
||||||
var response: BankResponse? = null,
|
|
||||||
var didBankCloseDialog: Boolean = false,
|
|
||||||
var previousMessageInDialog: MessageBuilderResult? = null, // for PinTan almost always the case except for getting a user's TAN methods
|
|
||||||
var chunkedResponseHandler: ((BankResponse) -> Unit)? = null
|
|
||||||
) {
|
) {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
@ -22,9 +17,22 @@ open class DialogContext(
|
||||||
const val InitialMessageNumber = 0
|
const val InitialMessageNumber = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
open var currentMessage: MessageBuilderResult? = null
|
||||||
|
protected set
|
||||||
|
|
||||||
|
open var previousMessageInDialog: MessageBuilderResult? = null
|
||||||
|
protected set
|
||||||
|
|
||||||
open var messageNumber: Int = InitialMessageNumber
|
open var messageNumber: Int = InitialMessageNumber
|
||||||
protected set
|
protected set
|
||||||
|
|
||||||
|
open var abortIfTanIsRequired: Boolean = false
|
||||||
|
|
||||||
|
open var response: BankResponse? = null
|
||||||
|
|
||||||
|
open var didBankCloseDialog: Boolean = false
|
||||||
|
|
||||||
|
|
||||||
open fun increaseMessageNumber() {
|
open fun increaseMessageNumber() {
|
||||||
messageNumber++
|
messageNumber++
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package net.dankito.banking.fints.model
|
||||||
|
|
||||||
import net.dankito.banking.fints.callback.FinTsClientCallback
|
import net.dankito.banking.fints.callback.FinTsClientCallback
|
||||||
import net.dankito.banking.fints.log.IMessageLogAppender
|
import net.dankito.banking.fints.log.IMessageLogAppender
|
||||||
|
import net.dankito.banking.fints.log.MessageContext
|
||||||
import net.dankito.banking.fints.log.MessageLogCollector
|
import net.dankito.banking.fints.log.MessageLogCollector
|
||||||
import net.dankito.banking.fints.messages.datenelemente.implementierte.signatur.VersionDesSicherheitsverfahrens
|
import net.dankito.banking.fints.messages.datenelemente.implementierte.signatur.VersionDesSicherheitsverfahrens
|
||||||
import net.dankito.banking.fints.response.BankResponse
|
import net.dankito.banking.fints.response.BankResponse
|
||||||
|
@ -23,6 +24,10 @@ open class JobContext(
|
||||||
protected open val messageLogCollector: MessageLogCollector = MessageLogCollector()
|
protected open val messageLogCollector: MessageLogCollector = MessageLogCollector()
|
||||||
) : MessageBaseData(bank, product), IMessageLogAppender {
|
) : MessageBaseData(bank, product), IMessageLogAppender {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private var JobCount = 0 // this is not thread safe so job number may not be 100 % accurate
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
protected open val _dialogs = mutableListOf<DialogContext>()
|
protected open val _dialogs = mutableListOf<DialogContext>()
|
||||||
|
|
||||||
|
@ -39,10 +44,14 @@ open class JobContext(
|
||||||
get() = ArrayList(_dialogs) // create a copy
|
get() = ArrayList(_dialogs) // create a copy
|
||||||
|
|
||||||
|
|
||||||
|
protected open val jobNumber: Int = ++JobCount
|
||||||
|
|
||||||
|
|
||||||
open fun startNewDialog(closeDialog: Boolean = true, dialogId: String = DialogContext.InitialDialogId,
|
open fun startNewDialog(closeDialog: Boolean = true, dialogId: String = DialogContext.InitialDialogId,
|
||||||
versionOfSecurityProcedure: VersionDesSicherheitsverfahrens = VersionDesSicherheitsverfahrens.Version_2,
|
versionOfSecurityProcedure: VersionDesSicherheitsverfahrens = VersionDesSicherheitsverfahrens.Version_2,
|
||||||
chunkedResponseHandler: ((BankResponse) -> Unit)? = null) : DialogContext {
|
chunkedResponseHandler: ((BankResponse) -> Unit)? = null) : DialogContext {
|
||||||
val newDialogContext = DialogContext(closeDialog, dialogId = dialogId, chunkedResponseHandler = chunkedResponseHandler)
|
|
||||||
|
val newDialogContext = DialogContext(closeDialog, dialogId, chunkedResponseHandler)
|
||||||
|
|
||||||
this.versionOfSecurityProcedure = versionOfSecurityProcedure
|
this.versionOfSecurityProcedure = versionOfSecurityProcedure
|
||||||
|
|
||||||
|
@ -55,11 +64,15 @@ open class JobContext(
|
||||||
|
|
||||||
|
|
||||||
open fun addMessageLog(type: MessageLogEntryType, message: String) {
|
open fun addMessageLog(type: MessageLogEntryType, message: String) {
|
||||||
messageLogCollector.addMessageLog(bank, type, message)
|
messageLogCollector.addMessageLog(type, message, createMessageContext())
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun logError(loggingClass: KClass<*>, message: String, e: Exception?) {
|
override fun logError(loggingClass: KClass<*>, message: String, e: Exception?) {
|
||||||
messageLogCollector.logError(loggingClass, bank, message, e)
|
messageLogCollector.logError(loggingClass, message, createMessageContext(), e)
|
||||||
|
}
|
||||||
|
|
||||||
|
protected open fun createMessageContext(): MessageContext {
|
||||||
|
return MessageContext(jobNumber, dialog.messageNumber, bank, account)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -8,7 +8,7 @@ open class MessageBaseData(
|
||||||
open val product: ProductData
|
open val product: ProductData
|
||||||
) {
|
) {
|
||||||
|
|
||||||
open var versionOfSecurityProcedure: VersionDesSicherheitsverfahrens = VersionDesSicherheitsverfahrens.PinTanDefaultVersion
|
open var versionOfSecurityProcedure: VersionDesSicherheitsverfahrens = VersionDesSicherheitsverfahrens.PinTanDefaultVersion // for PinTan almost always the case except for getting a user's TAN methods
|
||||||
protected set
|
protected set
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,13 +1,14 @@
|
||||||
package net.dankito.banking.fints.model
|
package net.dankito.banking.fints.model
|
||||||
|
|
||||||
|
import net.dankito.banking.fints.log.MessageContext
|
||||||
import net.dankito.utils.multiplatform.Date
|
import net.dankito.utils.multiplatform.Date
|
||||||
|
|
||||||
|
|
||||||
open class MessageLogEntry(
|
open class MessageLogEntry(
|
||||||
open val message: String,
|
|
||||||
open val type: MessageLogEntryType,
|
open val type: MessageLogEntryType,
|
||||||
|
open val message: String,
|
||||||
open val time: Date,
|
open val time: Date,
|
||||||
open val bank: BankData?
|
open val context: MessageContext
|
||||||
) {
|
) {
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
|
|
|
@ -7,7 +7,10 @@ open class MessageLogEntry(
|
||||||
open val message: String,
|
open val message: String,
|
||||||
open val type: MessageLogEntryType,
|
open val type: MessageLogEntryType,
|
||||||
open val time: Date,
|
open val time: Date,
|
||||||
open val bank: TypedBankData
|
open val jobNumber: Int,
|
||||||
|
open val dialogNumber: Int,
|
||||||
|
open val bank: TypedBankData,
|
||||||
|
open val account: TypedBankAccount?
|
||||||
) {
|
) {
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
|
|
|
@ -215,7 +215,8 @@ open class fints4kBankingClient(
|
||||||
protected open fun saveData(response: FinTsClientResponse) {
|
protected open fun saveData(response: FinTsClientResponse) {
|
||||||
try {
|
try {
|
||||||
_messageLogWithoutSensitiveData.addAll(response.messageLogWithoutSensitiveData
|
_messageLogWithoutSensitiveData.addAll(response.messageLogWithoutSensitiveData
|
||||||
.map { MessageLogEntry(it.message, map(it.type), it.time, bank) })
|
.map { MessageLogEntry(it.message, map(it.type), it.time, it.context.jobNumber,
|
||||||
|
it.context.dialogNumber, bank, it.context.account?.let { mapper.findMatchingAccount(bank, it) } ) })
|
||||||
|
|
||||||
// TODO: fix that real (child) class get serialized and re-enable again
|
// TODO: fix that real (child) class get serialized and re-enable again
|
||||||
// val clientDataFile = getFints4kClientDataFile(fintsBank.bankCode, fintsBank.customerId)
|
// val clientDataFile = getFints4kClientDataFile(fintsBank.bankCode, fintsBank.customerId)
|
||||||
|
|
Loading…
Reference in New Issue