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
import de.staropensource.engine.base.type.logging.Call
import de.staropensource.engine.base.type.logging.ChannelSettings
import de.staropensource.engine.base.type.logging.Feature
/**
* 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
*/
abstract class FormatBuilder(protected val call: Call) {
abstract class FormatBuilder(protected val call: Call, protected val channelSettings: ChannelSettings?) {
/**
* 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.implementable.logging.FormatBuilder
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.Level
import kotlinx.datetime.Clock
import kotlinx.datetime.LocalDateTime
import kotlinx.datetime.toLocalDateTime
import kotlin.time.Duration
/**
* 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!
* ```
*
* @param call [Call] to build a format for
* @param call [Call] to build a format for
* @param channelSettings appropriate [ChannelSettings] instance
* @since v1-alpha10
*/
open class SOSLSv2FormatBuilder(call: Call) : FormatBuilder(call) {
open class SOSLSv2FormatBuilder(call: Call, channelSettings: ChannelSettings?) : FormatBuilder(call, channelSettings) {
override fun toString(): String {
return format(message = true)
return format(message = true, allowFormatting = true)
}
override fun toStringShadow(): Int {
return format(message = false).length
return format(message = false, allowFormatting = false).length
}
/**
* 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
* @since v1-alpha10
*/
fun format(message: Boolean): String = buildString {
addRuntime(this)
addDateTime(this)
fun format(message: Boolean, allowFormatting: Boolean): String = buildString {
val enabledFeatures: MutableSet<Feature> = this@SOSLSv2FormatBuilder.enabledFeatures.toMutableSet()
if (!allowFormatting)
enabledFeatures.remove(Feature.FORMATTING)
addRuntime(this, enabledFeatures)
addDateTime(this, enabledFeatures)
// Add level, origin & other metadata
if (enabledFeatures.contains(Feature.LEVEL) || enabledFeatures.contains(Feature.ORIGIN)) {
append("[")
addLevel(this)
if (enabledFeatures.contains(Feature.FORMATTING))
append("<gray>[<italic>")
else
append("[")
addLevel(this, enabledFeatures)
if (enabledFeatures.contains(Feature.LEVEL) && enabledFeatures.contains(Feature.ORIGIN))
append(" ")
addOriginAndMetadata(this)
append("] ")
addOriginAndMetadata(this, enabledFeatures)
if (enabledFeatures.contains(Feature.FORMATTING))
append("<reset><gray>] ")
else
append("] ")
}
// Message
if (message)
append(this@SOSLSv2FormatBuilder.message)
if (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
* @since v1-alpha10
*/
protected fun addRuntime(format: StringBuilder) {
if (enabledFeatures.contains(Feature.RUNTIME))
format
.append("[")
.append(Logger.Companion.initializationTime)
.append("ms")
.append("] ")
protected fun addRuntime(format: StringBuilder, enabledFeatures: MutableSet<Feature>) {
if (enabledFeatures.contains(Feature.RUNTIME)) {
if (enabledFeatures.contains(Feature.FORMATTING))
format.append("<gray>[<italic>")
else
format.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
* @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)
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("<gray>[<italic>")
else
format.append("[")
}
if (enabledFeatures.contains(Feature.DATE))
format
.append("%02d".format(datetime.dayOfMonth.toString()))
.append("%02d".format(datetime.dayOfMonth))
.append(".")
.append("%02d".format(datetime.monthNumber))
.append(".")
.append("%04d".format(datetime.year))
if (enabledFeatures.contains(Feature.DATE) && enabledFeatures.contains(Feature.TIME))
format.append(" ")
if (enabledFeatures.contains(Feature.TIME))
format
.append("%02d".format(datetime.hour))
@ -119,8 +158,13 @@ open class SOSLSv2FormatBuilder(call: Call) : FormatBuilder(call) {
.append("%02d".format(datetime.minute))
.append(":")
.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
* @since v1-alpha10
*/
protected fun addLevel(format: StringBuilder) {
if (enabledFeatures.contains(Feature.LEVEL))
@Suppress("CyclomaticComplexMethod")
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(
when (call.level) {
Level.DIAGNOSTIC -> "DIAG"
@ -142,6 +198,10 @@ open class SOSLSv2FormatBuilder(call: Call) : FormatBuilder(call) {
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
* @since v1-alpha10
*/
protected fun addOriginAndMetadata(format: StringBuilder) {
protected fun addOriginAndMetadata(format: StringBuilder, enabledFeatures: MutableSet<Feature>) {
if (enabledFeatures.contains(Feature.ORIGIN)) {
format.append("${call.origin.packageName}.${call.origin.className}")

View file

@ -94,19 +94,19 @@ class Processor private constructor() {
fun process(call: Call) {
val format: FormatBuilder
var formatFinalized: String = ""
val channelconf: ChannelSettings? = EngineConfiguration.logChannelSettings[call.channel]
val channelSettings: ChannelSettings? = EngineConfiguration.logChannelSettings[call.channel]
var message: String = call.message
// Set 'format'
try {
format = (EngineConfiguration.logFormatBuilder).primaryConstructor!!.call(call)
format = (EngineConfiguration.logFormatBuilder).primaryConstructor!!.call(call, channelSettings)
} 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
}
// Stop if channel does not permit execution
if (!(ChannelSettings.getSetting(channelconf, "enable") as Boolean))
if (!(ChannelSettings.getSetting(channelSettings, "enable") as Boolean))
return
// Build format
@ -116,11 +116,11 @@ class Processor private constructor() {
// Update message
if (
ChannelSettings.getSetting(channelconf, "sanitizeMessage") as Boolean
&& ChannelSettings.getSetting(channelconf, "permitFormatting") as Boolean
ChannelSettings.getSetting(channelSettings, "sanitizeMessage") as Boolean
&& ChannelSettings.getSetting(channelSettings, "permitFormatting") as Boolean
) message = message.replace("<", "\\<")
if (
ChannelSettings.getSetting(channelconf, "permitFormatting") as Boolean
ChannelSettings.getSetting(channelSettings, "permitFormatting") as Boolean
&& EngineConfiguration.logFeatures.contains(Feature.FORMATTING)
) format.addFeature(Feature.FORMATTING)
@ -131,14 +131,14 @@ class Processor private constructor() {
format.message = message
// Format format
formatFinalized = if (ChannelSettings.getSetting(channelconf, "permitFormatting") as Boolean)
(ChannelSettings.getSetting(channelconf, "formatter") as Formatter).formatString(format.toString())
formatFinalized = if (ChannelSettings.getSetting(channelSettings, "permitFormatting") as Boolean)
(ChannelSettings.getSetting(channelSettings, "formatter") as Formatter).formatString(format.toString())
else
format.toString()
// Pass format to adapters
@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)
}
}