From 190c1eca8b8576774b02813deb744cbb89dedb7a Mon Sep 17 00:00:00 2001 From: "Pedro S. Lopez" Date: Tue, 25 Jun 2024 19:10:24 -0400 Subject: [PATCH] fix: parse sentry stacktraces including kotlin code (#12938) --- .../errorreporter/SentryExceptionHelper.java | 4 +- .../SentryExceptionHelperTest.java | 62 +++++++++++++++++++ 2 files changed, 64 insertions(+), 2 deletions(-) diff --git a/airbyte-persistence/job-persistence/src/main/java/io/airbyte/persistence/job/errorreporter/SentryExceptionHelper.java b/airbyte-persistence/job-persistence/src/main/java/io/airbyte/persistence/job/errorreporter/SentryExceptionHelper.java index ac44f0fb8a6..3a87bdda096 100644 --- a/airbyte-persistence/job-persistence/src/main/java/io/airbyte/persistence/job/errorreporter/SentryExceptionHelper.java +++ b/airbyte-persistence/job-persistence/src/main/java/io/airbyte/persistence/job/errorreporter/SentryExceptionHelper.java @@ -84,7 +84,7 @@ public Optional buildSentryExceptions(final String stackt if (stacktrace.startsWith("Traceback (most recent call last):")) { return buildPythonSentryExceptions(stacktrace); } - if (stacktrace.contains("\tat ") && stacktrace.contains(".java")) { + if (stacktrace.contains("\tat ") && (stacktrace.contains(".java") || stacktrace.contains(".kt"))) { return buildJavaSentryExceptions(stacktrace); } if (stacktrace.startsWith("AirbyteDbtError: ")) { @@ -173,7 +173,7 @@ private static Optional buildJavaSentryExceptions(final S @SuppressWarnings("LineLength") // Use a regex to grab stack trace frame information final Pattern framePattern = Pattern.compile( - "\n\tat (?:[\\w.$/]+/)?(?[\\w$.]+)\\.(?[\\w<>$]+)\\((?:(?[\\w]+\\.java):(?\\d+)\\)|(?[\\w\\s]*))"); + "\n\tat (?:[\\w.$/]+/)?(?[\\w$.]+)\\.(?[\\w<>$]+)\\((?:(?[\\w]+\\.(?java|kt)):(?\\d+)\\)|(?[\\w\\s]*))"); final Matcher matcher = framePattern.matcher(exceptionStr); while (matcher.find()) { diff --git a/airbyte-persistence/job-persistence/src/test/java/io/airbyte/persistence/job/errorreporter/SentryExceptionHelperTest.java b/airbyte-persistence/job-persistence/src/test/java/io/airbyte/persistence/job/errorreporter/SentryExceptionHelperTest.java index ecae3fa75b8..8d9c4e39b8f 100644 --- a/airbyte-persistence/job-persistence/src/test/java/io/airbyte/persistence/job/errorreporter/SentryExceptionHelperTest.java +++ b/airbyte-persistence/job-persistence/src/test/java/io/airbyte/persistence/job/errorreporter/SentryExceptionHelperTest.java @@ -307,6 +307,68 @@ void testBuildSentryExceptionsJavaChained() { FUNCTION, "lambda$getDestinationOutputRunnable$7"))); } + @Test + void testBuildSentryExceptionsKotlin() { + final String stacktrace = + """ + io.airbyte.commons.exceptions.ConfigErrorException: Some error message + at io.airbyte.cdk.integrations.destination.staging.StagingConsumerFactory$Companion.streamDescToWriteConfig(StagingConsumerFactory.kt:226) + at io.airbyte.cdk.integrations.destination.staging.StagingConsumerFactory$Companion.access$streamDescToWriteConfig(StagingConsumerFactory.kt:159) + at io.airbyte.cdk.integrations.destination.staging.StagingConsumerFactory.createAsync(StagingConsumerFactory.kt:124) + at io.airbyte.integrations.destination.snowflake.SnowflakeDestination.getSerializedMessageConsumer(SnowflakeDestination.kt:194) + at io.airbyte.cdk.integrations.base.IntegrationRunner.run(IntegrationRunner.kt:116) + at io.airbyte.cdk.integrations.base.adaptive.AdaptiveDestinationRunner$Runner.run(AdaptiveDestinationRunner.kt:68) + at io.airbyte.integrations.destination.snowflake.SnowflakeDestinationKt.main(SnowflakeDestination.kt:279) + """; + + final Optional optionalSentryExceptions = exceptionHelper.buildSentryExceptions(stacktrace); + Assertions.assertTrue(optionalSentryExceptions.isPresent()); + + final SentryParsedException parsedException = optionalSentryExceptions.get(); + final List exceptionList = parsedException.exceptions(); + Assertions.assertEquals(SentryExceptionPlatform.JAVA, parsedException.platform()); + Assertions.assertEquals(1, exceptionList.size()); + + assertExceptionContent(exceptionList.get(0), "io.airbyte.commons.exceptions.ConfigErrorException", "Some error message", + List.of( + Map.of( + FILENAME, "SnowflakeDestination.kt", + LINE_NO, 279, + MODULE, "io.airbyte.integrations.destination.snowflake.SnowflakeDestinationKt", + FUNCTION, "main"), + Map.of( + FILENAME, "AdaptiveDestinationRunner.kt", + LINE_NO, 68, + MODULE, "io.airbyte.cdk.integrations.base.adaptive.AdaptiveDestinationRunner$Runner", + FUNCTION, "run"), + Map.of( + FILENAME, "IntegrationRunner.kt", + LINE_NO, 116, + MODULE, "io.airbyte.cdk.integrations.base.IntegrationRunner", + FUNCTION, "run"), + Map.of( + FILENAME, "SnowflakeDestination.kt", + LINE_NO, 194, + MODULE, "io.airbyte.integrations.destination.snowflake.SnowflakeDestination", + FUNCTION, "getSerializedMessageConsumer"), + Map.of( + FILENAME, "StagingConsumerFactory.kt", + LINE_NO, 124, + MODULE, "io.airbyte.cdk.integrations.destination.staging.StagingConsumerFactory", + FUNCTION, "createAsync"), + Map.of( + FILENAME, "StagingConsumerFactory.kt", + LINE_NO, 159, + MODULE, "io.airbyte.cdk.integrations.destination.staging.StagingConsumerFactory$Companion", + FUNCTION, "access$streamDescToWriteConfig"), + Map.of( + FILENAME, "StagingConsumerFactory.kt", + LINE_NO, 226, + MODULE, "io.airbyte.cdk.integrations.destination.staging.StagingConsumerFactory$Companion", + FUNCTION, "streamDescToWriteConfig"))); + + } + @Test void testBuildSentryExceptionsJavaMultilineValue() { final String stacktrace =