From 98912d22b3b8be38a53a2a12a4186d58f9f888fd Mon Sep 17 00:00:00 2001 From: Ruslan Burdeniuk Date: Thu, 12 Feb 2026 18:00:12 +0200 Subject: [PATCH 1/2] DRMCDU-1548: add into details exception data. update version to 0.0.4 --- build.gradle.kts | 2 +- library/failure/api/failure-library.api | 6 ++ .../uframework/failure/Failure.kt | 11 +++- .../uframework/failure/TypeFailure.kt | 3 + .../failure/AllDetailsFailureTest.kt | 59 ++++++++++++++----- 5 files changed, 64 insertions(+), 17 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 6120fef1..42c2821d 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -28,7 +28,7 @@ allprojects { } } - version = "0.0.3" + version = "0.0.4" group = "io.github.ustudiocompany" configurations.all { diff --git a/library/failure/api/failure-library.api b/library/failure/api/failure-library.api index dc8d7597..a4409236 100644 --- a/library/failure/api/failure-library.api +++ b/library/failure/api/failure-library.api @@ -119,12 +119,18 @@ public final class io/github/ustudiocompany/uframework/failure/FailureKt { public abstract interface class io/github/ustudiocompany/uframework/failure/TypeFailure : io/github/ustudiocompany/uframework/failure/Failure { public static final field ACTUAL_VALUE_DETAIL_KEY Ljava/lang/String; public static final field Companion Lio/github/ustudiocompany/uframework/failure/TypeFailure$Companion; + public static final field EXCEPTION_CAUSE Ljava/lang/String; + public static final field EXCEPTION_MESSAGE Ljava/lang/String; + public static final field EXCEPTION_STACKTRACE Ljava/lang/String; public static final field PATTERN_DETAIL_KEY Ljava/lang/String; public abstract fun getType-uX7CcE4 ()Ljava/lang/Class; } public final class io/github/ustudiocompany/uframework/failure/TypeFailure$Companion { public static final field ACTUAL_VALUE_DETAIL_KEY Ljava/lang/String; + public static final field EXCEPTION_CAUSE Ljava/lang/String; + public static final field EXCEPTION_MESSAGE Ljava/lang/String; + public static final field EXCEPTION_STACKTRACE Ljava/lang/String; public static final field PATTERN_DETAIL_KEY Ljava/lang/String; } diff --git a/library/failure/src/main/kotlin/io/github/ustudiocompany/uframework/failure/Failure.kt b/library/failure/src/main/kotlin/io/github/ustudiocompany/uframework/failure/Failure.kt index 44747939..c1b53c7c 100644 --- a/library/failure/src/main/kotlin/io/github/ustudiocompany/uframework/failure/Failure.kt +++ b/library/failure/src/main/kotlin/io/github/ustudiocompany/uframework/failure/Failure.kt @@ -2,6 +2,9 @@ package io.github.ustudiocompany.uframework.failure import io.github.ustudiocompany.uframework.failure.Failure.Cause import io.github.ustudiocompany.uframework.failure.Failure.Details +import io.github.ustudiocompany.uframework.failure.TypeFailure.Companion.EXCEPTION_CAUSE +import io.github.ustudiocompany.uframework.failure.TypeFailure.Companion.EXCEPTION_MESSAGE +import io.github.ustudiocompany.uframework.failure.TypeFailure.Companion.EXCEPTION_STACKTRACE public interface Failure { /** @@ -122,13 +125,19 @@ public fun Failure.fullCode(delimiter: String = "."): String = }.toString() /** - * Returns all details of the failure and its causes. + * Returns all details of the failure, its causes, and root exception details if it exists. * @return the all details. */ public fun Failure.allDetails(): Details { val allDetails = fold(initial = { mutableListOf().apply { addAll(it.details) } }) { acc, failure -> acc.apply { addAll(failure.details) } } + val exception = root().exceptionOrNull() + if (exception != null) { + allDetails.add(Details.Item(key = EXCEPTION_CAUSE, value = exception.cause.toString())) + allDetails.add(Details.Item(key = EXCEPTION_MESSAGE, value = exception.message ?: "null")) + allDetails.add(Details.Item(key = EXCEPTION_STACKTRACE, value = exception.stackTraceToString())) + } return if (allDetails.isEmpty()) Details.NONE else diff --git a/library/failure/src/main/kotlin/io/github/ustudiocompany/uframework/failure/TypeFailure.kt b/library/failure/src/main/kotlin/io/github/ustudiocompany/uframework/failure/TypeFailure.kt index c7bf258f..1302eeb8 100644 --- a/library/failure/src/main/kotlin/io/github/ustudiocompany/uframework/failure/TypeFailure.kt +++ b/library/failure/src/main/kotlin/io/github/ustudiocompany/uframework/failure/TypeFailure.kt @@ -6,5 +6,8 @@ public interface TypeFailure : Failure { public companion object { public const val ACTUAL_VALUE_DETAIL_KEY: String = "actual-value" public const val PATTERN_DETAIL_KEY: String = "pattern" + public const val EXCEPTION_CAUSE: String = "exception-cause" + public const val EXCEPTION_MESSAGE: String = "exception-message" + public const val EXCEPTION_STACKTRACE: String = "exception-stackTrace" } } diff --git a/library/failure/src/test/kotlin/io/github/ustudiocompany/uframework/failure/AllDetailsFailureTest.kt b/library/failure/src/test/kotlin/io/github/ustudiocompany/uframework/failure/AllDetailsFailureTest.kt index 5ab74a51..1cebf03d 100644 --- a/library/failure/src/test/kotlin/io/github/ustudiocompany/uframework/failure/AllDetailsFailureTest.kt +++ b/library/failure/src/test/kotlin/io/github/ustudiocompany/uframework/failure/AllDetailsFailureTest.kt @@ -2,6 +2,9 @@ package io.github.ustudiocompany.uframework.failure import io.github.ustudiocompany.uframework.failure.Failure.Cause import io.github.ustudiocompany.uframework.failure.Failure.Details +import io.github.ustudiocompany.uframework.failure.TypeFailure.Companion.EXCEPTION_CAUSE +import io.github.ustudiocompany.uframework.failure.TypeFailure.Companion.EXCEPTION_MESSAGE +import io.github.ustudiocompany.uframework.failure.TypeFailure.Companion.EXCEPTION_STACKTRACE import io.github.ustudiocompany.uframework.test.kotest.UnitTest import io.kotest.datatest.withData import io.kotest.matchers.collections.shouldContainOnly @@ -14,29 +17,40 @@ internal class AllDetailsFailureTest : UnitTest() { withData( nameFn = { (failure, _) -> failure.toString() }, listOf( - failure(code = CODE_1) to Details.NONE, - failure(code = CODE_1, details = Details.of(KEY_1 to VALUE_1)) to Details.of(KEY_1 to VALUE_1), - failure(code = CODE_2, cause = failure(code = CODE_1)) to Details.NONE, - failure( + failureRoot(code = CODE_1) to + Details.NONE, + failureRootException(details = Details.of(KEY_1 to VALUE_1)) to + Details.of( + KEY_1 to VALUE_1, + EXCEPTION_CAUSE to VALUE_3, + EXCEPTION_MESSAGE to VALUE_4, + EXCEPTION_STACKTRACE to VALUE_5 + ), + failureChild(code = CODE_2, cause = failureRoot(code = CODE_1)) to + Details.NONE, + failureChild( code = CODE_2, - cause = failure(CODE_1), + cause = failureRoot(CODE_1), details = Details.of(KEY_1 to VALUE_1) - ) to Details.of(KEY_1 to VALUE_1), - failure( + ) to + Details.of(KEY_1 to VALUE_1), + failureChild( code = CODE_2, - cause = failure( + cause = failureRoot( code = CODE_1, details = Details.of(KEY_1 to VALUE_1) ) - ) to Details.of(KEY_1 to VALUE_1), - failure( + ) to + Details.of(KEY_1 to VALUE_1), + failureChild( code = CODE_2, - cause = failure( + cause = failureRoot( code = CODE_1, details = Details.of(KEY_1 to VALUE_1) ), details = Details.of(KEY_2 to VALUE_2) - ) to Details.of(KEY_1 to VALUE_1, KEY_2 to VALUE_2) + ) to + Details.of(KEY_1 to VALUE_1, KEY_2 to VALUE_2) ) ) { (failure, expected) -> failure.allDetails() shouldContainOnly expected @@ -44,8 +58,13 @@ internal class AllDetailsFailureTest : UnitTest() { } } - private fun failure(code: String, details: Details = Details.NONE): Failure = Root(code = code, details = details) - private fun failure(code: String, cause: Failure, details: Details = Details.NONE): Failure = + private fun failureRoot(code: String, details: Details = Details.NONE): Failure = + Root(code = code, details = details) + + private fun failureRootException(code: String = CODE_1, details: Details = Details.NONE): Failure = + RootException(code = code, details = details) + + private fun failureChild(code: String, cause: Failure, details: Details = Details.NONE): Failure = Child(code = code, cause = Cause.Failure(cause), details = details) private companion object { @@ -56,11 +75,21 @@ internal class AllDetailsFailureTest : UnitTest() { private const val KEY_2 = "key-2" private const val VALUE_1 = "value-1" private const val VALUE_2 = "value-2" + private const val VALUE_3 = "null" + private const val VALUE_4 = "value-4" + private val testException = Exception(VALUE_4) + private val VALUE_5 = testException.stackTraceToString() } private data class Root( override val code: String, - override val details: Details = Details.NONE + override val details: Details = Details.NONE, + ) : Failure + + private data class RootException( + override val code: String, + override val details: Details = Details.NONE, + override val cause: Cause = Cause.Exception(testException) ) : Failure private data class Child( From e5f252862f2f849abd442add0be7448ac45c2456 Mon Sep 17 00:00:00 2001 From: Ruslan Burdeniuk Date: Fri, 13 Feb 2026 14:31:12 +0200 Subject: [PATCH 2/2] DRMCDU-1548: remove extra details --- library/failure/api/failure-library.api | 4 ---- .../ustudiocompany/uframework/failure/Failure.kt | 7 +------ .../uframework/failure/TypeFailure.kt | 2 -- .../uframework/failure/AllDetailsFailureTest.kt | 13 ++++--------- 4 files changed, 5 insertions(+), 21 deletions(-) diff --git a/library/failure/api/failure-library.api b/library/failure/api/failure-library.api index a4409236..782b651f 100644 --- a/library/failure/api/failure-library.api +++ b/library/failure/api/failure-library.api @@ -119,8 +119,6 @@ public final class io/github/ustudiocompany/uframework/failure/FailureKt { public abstract interface class io/github/ustudiocompany/uframework/failure/TypeFailure : io/github/ustudiocompany/uframework/failure/Failure { public static final field ACTUAL_VALUE_DETAIL_KEY Ljava/lang/String; public static final field Companion Lio/github/ustudiocompany/uframework/failure/TypeFailure$Companion; - public static final field EXCEPTION_CAUSE Ljava/lang/String; - public static final field EXCEPTION_MESSAGE Ljava/lang/String; public static final field EXCEPTION_STACKTRACE Ljava/lang/String; public static final field PATTERN_DETAIL_KEY Ljava/lang/String; public abstract fun getType-uX7CcE4 ()Ljava/lang/Class; @@ -128,8 +126,6 @@ public abstract interface class io/github/ustudiocompany/uframework/failure/Type public final class io/github/ustudiocompany/uframework/failure/TypeFailure$Companion { public static final field ACTUAL_VALUE_DETAIL_KEY Ljava/lang/String; - public static final field EXCEPTION_CAUSE Ljava/lang/String; - public static final field EXCEPTION_MESSAGE Ljava/lang/String; public static final field EXCEPTION_STACKTRACE Ljava/lang/String; public static final field PATTERN_DETAIL_KEY Ljava/lang/String; } diff --git a/library/failure/src/main/kotlin/io/github/ustudiocompany/uframework/failure/Failure.kt b/library/failure/src/main/kotlin/io/github/ustudiocompany/uframework/failure/Failure.kt index c1b53c7c..9c1580d2 100644 --- a/library/failure/src/main/kotlin/io/github/ustudiocompany/uframework/failure/Failure.kt +++ b/library/failure/src/main/kotlin/io/github/ustudiocompany/uframework/failure/Failure.kt @@ -2,8 +2,6 @@ package io.github.ustudiocompany.uframework.failure import io.github.ustudiocompany.uframework.failure.Failure.Cause import io.github.ustudiocompany.uframework.failure.Failure.Details -import io.github.ustudiocompany.uframework.failure.TypeFailure.Companion.EXCEPTION_CAUSE -import io.github.ustudiocompany.uframework.failure.TypeFailure.Companion.EXCEPTION_MESSAGE import io.github.ustudiocompany.uframework.failure.TypeFailure.Companion.EXCEPTION_STACKTRACE public interface Failure { @@ -133,11 +131,8 @@ public fun Failure.allDetails(): Details { acc.apply { addAll(failure.details) } } val exception = root().exceptionOrNull() - if (exception != null) { - allDetails.add(Details.Item(key = EXCEPTION_CAUSE, value = exception.cause.toString())) - allDetails.add(Details.Item(key = EXCEPTION_MESSAGE, value = exception.message ?: "null")) + if (exception != null) allDetails.add(Details.Item(key = EXCEPTION_STACKTRACE, value = exception.stackTraceToString())) - } return if (allDetails.isEmpty()) Details.NONE else diff --git a/library/failure/src/main/kotlin/io/github/ustudiocompany/uframework/failure/TypeFailure.kt b/library/failure/src/main/kotlin/io/github/ustudiocompany/uframework/failure/TypeFailure.kt index 1302eeb8..ab1d9daf 100644 --- a/library/failure/src/main/kotlin/io/github/ustudiocompany/uframework/failure/TypeFailure.kt +++ b/library/failure/src/main/kotlin/io/github/ustudiocompany/uframework/failure/TypeFailure.kt @@ -6,8 +6,6 @@ public interface TypeFailure : Failure { public companion object { public const val ACTUAL_VALUE_DETAIL_KEY: String = "actual-value" public const val PATTERN_DETAIL_KEY: String = "pattern" - public const val EXCEPTION_CAUSE: String = "exception-cause" - public const val EXCEPTION_MESSAGE: String = "exception-message" public const val EXCEPTION_STACKTRACE: String = "exception-stackTrace" } } diff --git a/library/failure/src/test/kotlin/io/github/ustudiocompany/uframework/failure/AllDetailsFailureTest.kt b/library/failure/src/test/kotlin/io/github/ustudiocompany/uframework/failure/AllDetailsFailureTest.kt index 1cebf03d..f12c72dd 100644 --- a/library/failure/src/test/kotlin/io/github/ustudiocompany/uframework/failure/AllDetailsFailureTest.kt +++ b/library/failure/src/test/kotlin/io/github/ustudiocompany/uframework/failure/AllDetailsFailureTest.kt @@ -2,8 +2,6 @@ package io.github.ustudiocompany.uframework.failure import io.github.ustudiocompany.uframework.failure.Failure.Cause import io.github.ustudiocompany.uframework.failure.Failure.Details -import io.github.ustudiocompany.uframework.failure.TypeFailure.Companion.EXCEPTION_CAUSE -import io.github.ustudiocompany.uframework.failure.TypeFailure.Companion.EXCEPTION_MESSAGE import io.github.ustudiocompany.uframework.failure.TypeFailure.Companion.EXCEPTION_STACKTRACE import io.github.ustudiocompany.uframework.test.kotest.UnitTest import io.kotest.datatest.withData @@ -22,9 +20,7 @@ internal class AllDetailsFailureTest : UnitTest() { failureRootException(details = Details.of(KEY_1 to VALUE_1)) to Details.of( KEY_1 to VALUE_1, - EXCEPTION_CAUSE to VALUE_3, - EXCEPTION_MESSAGE to VALUE_4, - EXCEPTION_STACKTRACE to VALUE_5 + EXCEPTION_STACKTRACE to VALUE_4 ), failureChild(code = CODE_2, cause = failureRoot(code = CODE_1)) to Details.NONE, @@ -75,10 +71,9 @@ internal class AllDetailsFailureTest : UnitTest() { private const val KEY_2 = "key-2" private const val VALUE_1 = "value-1" private const val VALUE_2 = "value-2" - private const val VALUE_3 = "null" - private const val VALUE_4 = "value-4" - private val testException = Exception(VALUE_4) - private val VALUE_5 = testException.stackTraceToString() + private const val VALUE_3 = "value-3" + private val testException = Exception(VALUE_3) + private val VALUE_4 = testException.stackTraceToString() } private data class Root(