diff --git a/base/src/main/kotlin/de/staropensource/engine/base/implementation/logging/crashcategory/InfoCrashCategory.kt b/base/src/main/kotlin/de/staropensource/engine/base/implementation/logging/crashcategory/InfoCrashCategory.kt index 50de723..d654ce3 100644 --- a/base/src/main/kotlin/de/staropensource/engine/base/implementation/logging/crashcategory/InfoCrashCategory.kt +++ b/base/src/main/kotlin/de/staropensource/engine/base/implementation/logging/crashcategory/InfoCrashCategory.kt @@ -23,6 +23,7 @@ package de.staropensource.engine.base.implementation.logging.crashcategory import de.staropensource.engine.base.implementable.logging.CrashCategory import de.staropensource.engine.base.type.logging.Call import de.staropensource.engine.base.type.logging.ChannelSettings +import de.staropensource.engine.base.utility.misc.StackTraceUtils /** * [CrashCategory] implementation @@ -62,14 +63,14 @@ class InfoCrashCategory private constructor() : CrashCategory { ): LinkedHashMap { return linkedMapOf( Pair("Origin", linkedMapOf( - Pair("Class", call.origin), - Pair("Method", call.methodName), - Pair("Line", call.lineNumber), + Pair("Class", "${call.origin.packageName}.${call.origin.className}"), + Pair("Method", call.origin.methodName), + Pair("Line", call.origin.lineNumber), )), Pair("Channel", call.channel), Pair("Fatal", if (fatal) "yes" else "no"), Pair("Message", call.message), - Pair("Stacktrace", throwable?.toString() ?: "Not available."), // TODO report correct stacktrace + Pair("Stacktrace", if (throwable == null) "Not available." else StackTraceUtils.stacktraceRecursive(throwable)), ) } } diff --git a/base/src/main/kotlin/de/staropensource/engine/base/implementation/logging/formatbuilder/SOSLSv2FormatBuilder.kt b/base/src/main/kotlin/de/staropensource/engine/base/implementation/logging/formatbuilder/SOSLSv2FormatBuilder.kt index 73ee57a..17a9f08 100644 --- a/base/src/main/kotlin/de/staropensource/engine/base/implementation/logging/formatbuilder/SOSLSv2FormatBuilder.kt +++ b/base/src/main/kotlin/de/staropensource/engine/base/implementation/logging/formatbuilder/SOSLSv2FormatBuilder.kt @@ -159,18 +159,22 @@ open class SOSLSv2FormatBuilder(call: Call) : FormatBuilder(call) { */ protected fun addOriginAndMetadata(format: StringBuilder) { if (enabledFeatures.contains(Feature.ORIGIN)) { - format.append(call.origin) + format.append("${call.origin.packageName}.${call.origin.className}") if (enabledFeatures.contains(Feature.METHOD_NAME)) - // TODO sanitization (, )? format .append("#") - .append(call.methodName) + .append( + if (enabledFeatures.contains(Feature.FORMATTING)) + call.origin.methodName.replace("<", "\\<") + else + call.origin.methodName + ) - if (enabledFeatures.contains(Feature.LINE_NUMBER) && call.lineNumber >= 0) + if (enabledFeatures.contains(Feature.LINE_NUMBER)) format .append("~L") - .append(call.lineNumber) + .append(call.origin.lineNumber) } } } diff --git a/base/src/main/kotlin/de/staropensource/engine/base/logging/Logger.kt b/base/src/main/kotlin/de/staropensource/engine/base/logging/Logger.kt index aae90db..6bd72f0 100644 --- a/base/src/main/kotlin/de/staropensource/engine/base/logging/Logger.kt +++ b/base/src/main/kotlin/de/staropensource/engine/base/logging/Logger.kt @@ -24,6 +24,7 @@ import de.staropensource.engine.base.EngineConfiguration import de.staropensource.engine.base.implementable.logging.LoggerThreadingHandler import de.staropensource.engine.base.type.logging.Call import de.staropensource.engine.base.type.logging.Level +import de.staropensource.engine.base.utility.misc.StackTraceUtils import kotlinx.datetime.Clock import kotlinx.datetime.Instant @@ -102,24 +103,13 @@ class Logger { * @param level level to use * @param message message to log * @param levelData data specific to a [Level] - * @param stackTraceDistance determines which [StackTraceElement] will be used as the call's origin. Just fiddle with this number until it's correct. + * @param callerDepth determines the depth at which to discover the method caller * @since v1-alpha10 */ - fun log(level: Level, message: String, levelData: Map = emptyMap(), stackTraceDistance: Int = 0) { - val origin: StackTraceElement - - // Set 'origin' - try { - origin = Throwable().stackTrace[1 + stackTraceDistance] - } catch (_: IndexOutOfBoundsException) { - return - } - + fun log(level: Level, message: String, levelData: Map = emptyMap(), callerDepth: UInt = 0u) { // Create 'Call' instance var call: Call = Call( - origin.className, - origin.methodName, - origin.lineNumber, + StackTraceUtils.getMethodCaller(callerDepth.plus(1u)), level, message, channel @@ -144,7 +134,7 @@ class Logger { * @since v1-alpha10 */ fun diag(message: String) { - log(Level.DIAGNOSTIC, message, stackTraceDistance = 1) + log(Level.DIAGNOSTIC, message, callerDepth = 1u) } /** @@ -154,7 +144,7 @@ class Logger { * @since v1-alpha10 */ fun verb(message: String) { - log(Level.VERBOSE, message, stackTraceDistance = 1) + log(Level.VERBOSE, message, callerDepth = 1u) } /** @@ -164,7 +154,7 @@ class Logger { * @since v1-alpha10 */ fun sarn(message: String) { - log(Level.SILENT_WARNING, message, stackTraceDistance = 1) + log(Level.SILENT_WARNING, message, callerDepth = 1u) } /** @@ -174,7 +164,7 @@ class Logger { * @since v1-alpha10 */ fun info(message: String) { - log(Level.INFORMATIONAL, message, stackTraceDistance = 1) + log(Level.INFORMATIONAL, message, callerDepth = 1u) } /** @@ -184,7 +174,7 @@ class Logger { * @since v1-alpha10 */ fun warn(message: String) { - log(Level.WARNING, message, stackTraceDistance = 1) + log(Level.WARNING, message, callerDepth = 1u) } /** @@ -194,7 +184,7 @@ class Logger { * @since v1-alpha10 */ fun error(message: String) { - log(Level.ERROR, message, stackTraceDistance = 1) + log(Level.ERROR, message, callerDepth = 1u) } /** @@ -209,7 +199,7 @@ class Logger { log(Level.CRASH, error, levelData = mapOf( Pair("throwable", throwable as Object?), Pair("fatal", fatal as Object?) - ), stackTraceDistance = 1) + ), callerDepth = 1u) } diff --git a/base/src/main/kotlin/de/staropensource/engine/base/logging/Processor.kt b/base/src/main/kotlin/de/staropensource/engine/base/logging/Processor.kt index 8bd51a4..07b58f9 100644 --- a/base/src/main/kotlin/de/staropensource/engine/base/logging/Processor.kt +++ b/base/src/main/kotlin/de/staropensource/engine/base/logging/Processor.kt @@ -29,6 +29,7 @@ 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.OperationMode +import de.staropensource.engine.base.utility.misc.StackTraceUtils import kotlin.reflect.full.primaryConstructor /** @@ -101,8 +102,7 @@ class Processor private constructor() { try { format = (EngineConfiguration.logFormatBuilder).primaryConstructor!!.call(call) } catch (throwable: Throwable) { - println("Logger system failure: Configured FormatBuilder implementation '" + ((EngineConfiguration.logFormatBuilder).qualifiedName ?: "") + "' does not have a primary 'constructor(call: Call)'. Log messages cannot be processed.") - // TODO print exception? + println("Logger system failure: Configured FormatBuilder implementation '" + ((EngineConfiguration.logFormatBuilder).qualifiedName ?: "") + "' does not have a primary 'constructor(call: Call)'. Log messages cannot be processed.\n${StackTraceUtils.stacktraceRecursive(throwable)}") return } diff --git a/base/src/main/kotlin/de/staropensource/engine/base/type/Origin.kt b/base/src/main/kotlin/de/staropensource/engine/base/type/Origin.kt new file mode 100644 index 0000000..fe28235 --- /dev/null +++ b/base/src/main/kotlin/de/staropensource/engine/base/type/Origin.kt @@ -0,0 +1,37 @@ +/* + * STAROPENSOURCE ENGINE SOURCE FILE + * Copyright (c) 2024 The StarOpenSource Engine Authors + * Licensed under the GNU Affero General Public License v3 + * with an exception allowing classpath linking. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.staropensource.engine.base.type + +/** + * Holds data about a method caller. + * + * @param packageName fully qualified name of the package where the calling class is in + * @param className name of the calling class + * @param methodName name of the calling method + * @param lineNumber line of the method call + * @since v1-alpha10 + */ +data class Origin( + val packageName: String, + val className: String, + val methodName: String, + val lineNumber: UInt, +) diff --git a/base/src/main/kotlin/de/staropensource/engine/base/type/logging/Call.kt b/base/src/main/kotlin/de/staropensource/engine/base/type/logging/Call.kt index c662efa..844138b 100644 --- a/base/src/main/kotlin/de/staropensource/engine/base/type/logging/Call.kt +++ b/base/src/main/kotlin/de/staropensource/engine/base/type/logging/Call.kt @@ -20,21 +20,19 @@ package de.staropensource.engine.base.type.logging +import de.staropensource.engine.base.type.Origin + /** * Holds information about log calls. * - * @param origin package + class name that made the call - * @param methodName name of the method that made the call - * @param lineNumber line number where the call was made + * @param origin caller origin * @param level level * @param message message * @param channel channel * @since v1-alpha10 */ data class Call( - val origin: String, - val methodName: String, - val lineNumber: Int, + val origin: Origin, val level: Level, var message: String, val channel: String = "default", diff --git a/base/src/main/kotlin/de/staropensource/engine/base/utility/FileAccess.kt b/base/src/main/kotlin/de/staropensource/engine/base/utility/FileAccess.kt index 15ac2f8..fb17eb1 100644 --- a/base/src/main/kotlin/de/staropensource/engine/base/utility/FileAccess.kt +++ b/base/src/main/kotlin/de/staropensource/engine/base/utility/FileAccess.kt @@ -29,6 +29,7 @@ import de.staropensource.engine.base.exception.VerificationFailedException import de.staropensource.engine.base.utility.Environment.OperatingSystem.* import de.staropensource.engine.base.utility.FileAccess.Companion.configDirectory import de.staropensource.engine.base.utility.FileAccess.Companion.format +import de.staropensource.engine.base.utility.misc.StackTraceUtils import java.io.File import java.io.IOException import java.nio.file.* @@ -210,8 +211,7 @@ class FileAccess { logger.sarn("Unable to delete file or directory '${unformatFromPath(path)}' scheduled for deletion manually") } } catch (exception: Exception) { - // TODO add exception printing - logger.sarn("Unable to delete file or directory '${unformatFromPath(path)}' scheduled for deletion.") + logger.sarn("Unable to delete file or directory '${unformatFromPath(path)}' scheduled for deletion.\n${StackTraceUtils.stacktraceRecursive(exception)}") } } diff --git a/base/src/test/kotlin/de/staropensource/engine/base/utility/FileAccessTest.kt b/base/src/test/kotlin/de/staropensource/engine/base/utility/FileAccessTest.kt index c00ef28..140b419 100644 --- a/base/src/test/kotlin/de/staropensource/engine/base/utility/FileAccessTest.kt +++ b/base/src/test/kotlin/de/staropensource/engine/base/utility/FileAccessTest.kt @@ -151,7 +151,6 @@ class FileAccessTest : TestBase() { "test.txt", "+" "configs/default.conf", "+/configs"""" ) - // TODO error / fun parent(supplyValue: String, compareValue: String) { assertEquals( transformToStringPath(compareValue),