Add formatting to SOSLSv2FormatBuilder

This commit is contained in:
JeremyStar™ 2024-12-20 21:47:15 +01:00
parent 01c91244aa
commit e483e5c3f1
Signed by: JeremyStarTM
GPG key ID: E366BAEF67E4704D
3 changed files with 104 additions and 42 deletions

View file

@ -20,15 +20,17 @@
package de.staropensource.engine.base.implementable.logging package de.staropensource.engine.base.implementable.logging
import de.staropensource.engine.base.type.logging.Call import de.staropensource.engine.base.type.logging.Call
import de.staropensource.engine.base.type.logging.ChannelSettings
import de.staropensource.engine.base.type.logging.Feature import de.staropensource.engine.base.type.logging.Feature
/** /**
* Builds log formats. * Builds log formats.
* *
* @param call [Call] to build a format for * @param call [Call] to build a format for
* @param channelSettings appropriate [ChannelSettings] instance
* @since v1-alpha10 * @since v1-alpha10
*/ */
abstract class FormatBuilder(protected val call: Call) { abstract class FormatBuilder(protected val call: Call, protected val channelSettings: ChannelSettings?) {
/** /**
* Contains all enabled features. * Contains all enabled features.
* *

View file

@ -23,11 +23,13 @@ import de.staropensource.engine.base.EngineConfiguration
import de.staropensource.engine.base.logging.Logger import de.staropensource.engine.base.logging.Logger
import de.staropensource.engine.base.implementable.logging.FormatBuilder import de.staropensource.engine.base.implementable.logging.FormatBuilder
import de.staropensource.engine.base.type.logging.Call import de.staropensource.engine.base.type.logging.Call
import de.staropensource.engine.base.type.logging.ChannelSettings
import de.staropensource.engine.base.type.logging.Feature import de.staropensource.engine.base.type.logging.Feature
import de.staropensource.engine.base.type.logging.Level import de.staropensource.engine.base.type.logging.Level
import kotlinx.datetime.Clock import kotlinx.datetime.Clock
import kotlinx.datetime.LocalDateTime import kotlinx.datetime.LocalDateTime
import kotlinx.datetime.toLocalDateTime import kotlinx.datetime.toLocalDateTime
import kotlin.time.Duration
/** /**
* Builds the format as specified in the * Builds the format as specified in the
@ -39,42 +41,64 @@ import kotlinx.datetime.toLocalDateTime
* [505ms] [03.10.1990 23:23:23] [INFO de.staropensource.engine.testapp.Main#sayHi~42] Hello World! * [505ms] [03.10.1990 23:23:23] [INFO de.staropensource.engine.testapp.Main#sayHi~42] Hello World!
* ``` * ```
* *
* @param call [Call] to build a format for * @param call [Call] to build a format for
* @param channelSettings appropriate [ChannelSettings] instance
* @since v1-alpha10 * @since v1-alpha10
*/ */
open class SOSLSv2FormatBuilder(call: Call) : FormatBuilder(call) { open class SOSLSv2FormatBuilder(call: Call, channelSettings: ChannelSettings?) : FormatBuilder(call, channelSettings) {
override fun toString(): String { override fun toString(): String {
return format(message = true) return format(message = true, allowFormatting = true)
} }
override fun toStringShadow(): Int { override fun toStringShadow(): Int {
return format(message = false).length return format(message = false, allowFormatting = false).length
} }
/** /**
* Runs the actual formatting step. * Runs the actual formatting step.
* *
* @param message add the message to the finalized format? * @param message if to add the [message] to the finalized format
* @param allowFormatting if to allow formatting (see [Feature.FORMATTING])
* @return finalized format * @return finalized format
* @since v1-alpha10 * @since v1-alpha10
*/ */
fun format(message: Boolean): String = buildString { fun format(message: Boolean, allowFormatting: Boolean): String = buildString {
addRuntime(this) val enabledFeatures: MutableSet<Feature> = this@SOSLSv2FormatBuilder.enabledFeatures.toMutableSet()
addDateTime(this)
if (!allowFormatting)
enabledFeatures.remove(Feature.FORMATTING)
addRuntime(this, enabledFeatures)
addDateTime(this, enabledFeatures)
// Add level, origin & other metadata // Add level, origin & other metadata
if (enabledFeatures.contains(Feature.LEVEL) || enabledFeatures.contains(Feature.ORIGIN)) { if (enabledFeatures.contains(Feature.LEVEL) || enabledFeatures.contains(Feature.ORIGIN)) {
append("[") if (enabledFeatures.contains(Feature.FORMATTING))
addLevel(this) append("<gray>[<italic>")
else
append("[")
addLevel(this, enabledFeatures)
if (enabledFeatures.contains(Feature.LEVEL) && enabledFeatures.contains(Feature.ORIGIN)) if (enabledFeatures.contains(Feature.LEVEL) && enabledFeatures.contains(Feature.ORIGIN))
append(" ") append(" ")
addOriginAndMetadata(this) addOriginAndMetadata(this, enabledFeatures)
append("] ") if (enabledFeatures.contains(Feature.FORMATTING))
append("<reset><gray>] ")
else
append("] ")
} }
// Message // Message
if (message) if (message) {
append(this@SOSLSv2FormatBuilder.message) var messageFormat: String = this@SOSLSv2FormatBuilder.message
if (ChannelSettings.getSetting(channelSettings, "sanitizeMessage") == false)
messageFormat = messageFormat.replace("\n", "<reset>\n")
if (enabledFeatures.contains(Feature.FORMATTING))
append("<reset>${messageFormat}")
else
append(messageFormat)
}
} }
/** /**
@ -83,13 +107,21 @@ open class SOSLSv2FormatBuilder(call: Call) : FormatBuilder(call) {
* @param format [StringBuilder] to operate on * @param format [StringBuilder] to operate on
* @since v1-alpha10 * @since v1-alpha10
*/ */
protected fun addRuntime(format: StringBuilder) { protected fun addRuntime(format: StringBuilder, enabledFeatures: MutableSet<Feature>) {
if (enabledFeatures.contains(Feature.RUNTIME)) if (enabledFeatures.contains(Feature.RUNTIME)) {
format if (enabledFeatures.contains(Feature.FORMATTING))
.append("[") format.append("<gray>[<italic>")
.append(Logger.Companion.initializationTime) else
.append("ms") format.append("[")
.append("] ")
val differenceTime: Duration = Clock.System.now().minus(Logger.Companion.initializationTime)
format.append("${differenceTime.inWholeSeconds}.${differenceTime.inWholeMilliseconds.minus(differenceTime.inWholeSeconds.times(1000))}s")
if (enabledFeatures.contains(Feature.FORMATTING))
format.append("<reset><gray>")
format.append("] ")
}
} }
/** /**
@ -98,20 +130,27 @@ open class SOSLSv2FormatBuilder(call: Call) : FormatBuilder(call) {
* @param format [StringBuilder] to operate on * @param format [StringBuilder] to operate on
* @since v1-alpha10 * @since v1-alpha10
*/ */
protected fun addDateTime(format: StringBuilder) { protected fun addDateTime(format: StringBuilder, enabledFeatures: MutableSet<Feature>) {
val datetime: LocalDateTime = Clock.System.now().toLocalDateTime(EngineConfiguration.timezone) val datetime: LocalDateTime = Clock.System.now().toLocalDateTime(EngineConfiguration.timezone)
if (enabledFeatures.contains(Feature.DATE) || enabledFeatures.contains(Feature.TIME)) if (enabledFeatures.contains(Feature.DATE) || enabledFeatures.contains(Feature.TIME)) {
format.append("[") if (enabledFeatures.contains(Feature.FORMATTING))
format.append("<gray>[<italic>")
else
format.append("[")
}
if (enabledFeatures.contains(Feature.DATE)) if (enabledFeatures.contains(Feature.DATE))
format format
.append("%02d".format(datetime.dayOfMonth.toString())) .append("%02d".format(datetime.dayOfMonth))
.append(".") .append(".")
.append("%02d".format(datetime.monthNumber)) .append("%02d".format(datetime.monthNumber))
.append(".") .append(".")
.append("%04d".format(datetime.year)) .append("%04d".format(datetime.year))
if (enabledFeatures.contains(Feature.DATE) && enabledFeatures.contains(Feature.TIME)) if (enabledFeatures.contains(Feature.DATE) && enabledFeatures.contains(Feature.TIME))
format.append(" ") format.append(" ")
if (enabledFeatures.contains(Feature.TIME)) if (enabledFeatures.contains(Feature.TIME))
format format
.append("%02d".format(datetime.hour)) .append("%02d".format(datetime.hour))
@ -119,8 +158,13 @@ open class SOSLSv2FormatBuilder(call: Call) : FormatBuilder(call) {
.append("%02d".format(datetime.minute)) .append("%02d".format(datetime.minute))
.append(":") .append(":")
.append("%02d".format(datetime.second)) .append("%02d".format(datetime.second))
if (enabledFeatures.contains(Feature.DATE) || enabledFeatures.contains(Feature.TIME))
format.append("] ") if (enabledFeatures.contains(Feature.DATE) || enabledFeatures.contains(Feature.TIME)) {
if (enabledFeatures.contains(Feature.FORMATTING))
format.append("<reset><gray>] ")
else
format.append("] ")
}
} }
/** /**
@ -129,8 +173,20 @@ open class SOSLSv2FormatBuilder(call: Call) : FormatBuilder(call) {
* @param format [StringBuilder] to operate on * @param format [StringBuilder] to operate on
* @since v1-alpha10 * @since v1-alpha10
*/ */
protected fun addLevel(format: StringBuilder) { @Suppress("CyclomaticComplexMethod")
if (enabledFeatures.contains(Feature.LEVEL)) protected fun addLevel(format: StringBuilder, enabledFeatures: MutableSet<Feature>) {
if (enabledFeatures.contains(Feature.LEVEL)) {
if (enabledFeatures.contains(Feature.FORMATTING))
format.append(when (call.level) {
Level.DIAGNOSTIC -> "<light_blue>"
Level.VERBOSE -> "<blue>"
Level.SILENT_WARNING -> "<yellow>"
Level.INFORMATIONAL -> "<white>"
Level.WARNING -> "<orange>"
Level.ERROR -> "<red>"
Level.CRASH -> "<bold><red>"
})
format.append( format.append(
when (call.level) { when (call.level) {
Level.DIAGNOSTIC -> "DIAG" Level.DIAGNOSTIC -> "DIAG"
@ -142,6 +198,10 @@ open class SOSLSv2FormatBuilder(call: Call) : FormatBuilder(call) {
Level.CRASH -> "CRSH" Level.CRASH -> "CRSH"
} }
) )
if (enabledFeatures.contains(Feature.FORMATTING) && call.level == Level.CRASH)
format.append("<reset><red>")
}
} }
/** /**
@ -152,7 +212,7 @@ open class SOSLSv2FormatBuilder(call: Call) : FormatBuilder(call) {
* @param format [StringBuilder] to operate on * @param format [StringBuilder] to operate on
* @since v1-alpha10 * @since v1-alpha10
*/ */
protected fun addOriginAndMetadata(format: StringBuilder) { protected fun addOriginAndMetadata(format: StringBuilder, enabledFeatures: MutableSet<Feature>) {
if (enabledFeatures.contains(Feature.ORIGIN)) { if (enabledFeatures.contains(Feature.ORIGIN)) {
format.append("${call.origin.packageName}.${call.origin.className}") format.append("${call.origin.packageName}.${call.origin.className}")

View file

@ -94,19 +94,19 @@ class Processor private constructor() {
fun process(call: Call) { fun process(call: Call) {
val format: FormatBuilder val format: FormatBuilder
var formatFinalized: String = "" var formatFinalized: String = ""
val channelconf: ChannelSettings? = EngineConfiguration.logChannelSettings[call.channel] val channelSettings: ChannelSettings? = EngineConfiguration.logChannelSettings[call.channel]
var message: String = call.message var message: String = call.message
// Set 'format' // Set 'format'
try { try {
format = (EngineConfiguration.logFormatBuilder).primaryConstructor!!.call(call) format = (EngineConfiguration.logFormatBuilder).primaryConstructor!!.call(call, channelSettings)
} catch (throwable: Throwable) { } catch (throwable: Throwable) {
println("Logger system failure: Configured FormatBuilder implementation '" + ((EngineConfiguration.logFormatBuilder).qualifiedName ?: "<anonymous>") + "' does not have a primary 'constructor(call: Call)'. Log messages cannot be processed.\n${StackTraceUtils.stacktraceRecursive(throwable)}") println("Logger system failure: Configured FormatBuilder implementation '" + ((EngineConfiguration.logFormatBuilder).qualifiedName ?: "<anonymous>") + "' does not have a primary 'constructor(Call, ChannelSettings?)'. Log messages cannot be processed.\n${StackTraceUtils.stacktraceRecursive(throwable)}")
return return
} }
// Stop if channel does not permit execution // Stop if channel does not permit execution
if (!(ChannelSettings.getSetting(channelconf, "enable") as Boolean)) if (!(ChannelSettings.getSetting(channelSettings, "enable") as Boolean))
return return
// Build format // Build format
@ -116,11 +116,11 @@ class Processor private constructor() {
// Update message // Update message
if ( if (
ChannelSettings.getSetting(channelconf, "sanitizeMessage") as Boolean ChannelSettings.getSetting(channelSettings, "sanitizeMessage") as Boolean
&& ChannelSettings.getSetting(channelconf, "permitFormatting") as Boolean && ChannelSettings.getSetting(channelSettings, "permitFormatting") as Boolean
) message = message.replace("<", "\\<") ) message = message.replace("<", "\\<")
if ( if (
ChannelSettings.getSetting(channelconf, "permitFormatting") as Boolean ChannelSettings.getSetting(channelSettings, "permitFormatting") as Boolean
&& EngineConfiguration.logFeatures.contains(Feature.FORMATTING) && EngineConfiguration.logFeatures.contains(Feature.FORMATTING)
) format.addFeature(Feature.FORMATTING) ) format.addFeature(Feature.FORMATTING)
@ -131,14 +131,14 @@ class Processor private constructor() {
format.message = message format.message = message
// Format format // Format format
formatFinalized = if (ChannelSettings.getSetting(channelconf, "permitFormatting") as Boolean) formatFinalized = if (ChannelSettings.getSetting(channelSettings, "permitFormatting") as Boolean)
(ChannelSettings.getSetting(channelconf, "formatter") as Formatter).formatString(format.toString()) (ChannelSettings.getSetting(channelSettings, "formatter") as Formatter).formatString(format.toString())
else else
format.toString() format.toString()
// Pass format to adapters // Pass format to adapters
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
for (adapter: Adapter in ChannelSettings.getSetting(channelconf, "adapters") as Set<Adapter>) for (adapter: Adapter in ChannelSettings.getSetting(channelSettings, "adapters") as Set<Adapter>)
adapter.handle(call, formatFinalized) adapter.handle(call, formatFinalized)
} }
} }