From 74db9b7c1b3d7e7c235f6f8f8bafb6da49ca4706 Mon Sep 17 00:00:00 2001 From: Alexander Dinauer Date: Mon, 4 Aug 2025 09:13:05 +0200 Subject: [PATCH 1/4] Add E2E tests for Log4j2 --- .../sentry-samples-log4j2/build.gradle.kts | 73 ++++++++++++++++++- .../src/test/kotlin/io/sentry/DummyTest.kt | 12 +++ .../ConsoleApplicationSystemTest.kt | 62 ++++++++++++++++ test/system-test-runner.py | 2 + 4 files changed, 147 insertions(+), 2 deletions(-) create mode 100644 sentry-samples/sentry-samples-log4j2/src/test/kotlin/io/sentry/DummyTest.kt create mode 100644 sentry-samples/sentry-samples-log4j2/src/test/kotlin/io/sentry/systemtest/ConsoleApplicationSystemTest.kt diff --git a/sentry-samples/sentry-samples-log4j2/build.gradle.kts b/sentry-samples/sentry-samples-log4j2/build.gradle.kts index cf85847a57c..6cbd5640f7d 100644 --- a/sentry-samples/sentry-samples-log4j2/build.gradle.kts +++ b/sentry-samples/sentry-samples-log4j2/build.gradle.kts @@ -1,18 +1,87 @@ +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile + plugins { java application + kotlin("jvm") alias(libs.plugins.gradle.versions) + id("com.github.johnrengelman.shadow") version "8.1.1" } application { mainClass.set("io.sentry.samples.log4j2.Main") } +java.sourceCompatibility = JavaVersion.VERSION_17 + +java.targetCompatibility = JavaVersion.VERSION_17 + +repositories { mavenCentral() } + configure { - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 +} + +tasks.withType().configureEach { + kotlinOptions.jvmTarget = JavaVersion.VERSION_17.toString() +} + +tasks.withType().configureEach { + kotlinOptions { + freeCompilerArgs = listOf("-Xjsr305=strict") + jvmTarget = JavaVersion.VERSION_17.toString() + } } dependencies { implementation(projects.sentryLog4j2) implementation(libs.log4j.api) implementation(libs.log4j.core) + + testImplementation(kotlin(Config.kotlinStdLib)) + testImplementation(projects.sentry) + testImplementation(projects.sentrySystemTestSupport) + testImplementation(libs.kotlin.test.junit) + testImplementation(libs.slf4j.api) + testImplementation(libs.slf4j.jdk14) +} + +// Configure the Shadow JAR (executable JAR with all dependencies) +tasks.shadowJar { + manifest { attributes["Main-Class"] = "io.sentry.samples.log4j2.Main" } + archiveClassifier.set("") // Remove the classifier so it replaces the regular JAR + mergeServiceFiles() + // Use Log4j2 cache transformer to properly handle plugin files + transform(com.github.jengelman.gradle.plugins.shadow.transformers.Log4j2PluginsCacheFileTransformer()) +} + +// Make the regular jar task depend on shadowJar +tasks.jar { + enabled = false + dependsOn(tasks.shadowJar) +} + +// Fix the startScripts task dependency +tasks.startScripts { dependsOn(tasks.shadowJar) } + +configure { test { java.srcDir("src/test/java") } } + +tasks.register("systemTest").configure { + group = "verification" + description = "Runs the System tests" + + outputs.upToDateWhen { false } + + maxParallelForks = 1 + + // Cap JVM args per test + minHeapSize = "128m" + maxHeapSize = "1g" + + filter { includeTestsMatching("io.sentry.systemtest*") } +} + +tasks.named("test").configure { + require(this is Test) + + filter { excludeTestsMatching("io.sentry.systemtest.*") } } diff --git a/sentry-samples/sentry-samples-log4j2/src/test/kotlin/io/sentry/DummyTest.kt b/sentry-samples/sentry-samples-log4j2/src/test/kotlin/io/sentry/DummyTest.kt new file mode 100644 index 00000000000..331f462c55e --- /dev/null +++ b/sentry-samples/sentry-samples-log4j2/src/test/kotlin/io/sentry/DummyTest.kt @@ -0,0 +1,12 @@ +package io.sentry + +import kotlin.test.Test +import kotlin.test.assertTrue + +class DummyTest { + @Test + fun `the only test`() { + // only needed to have more than 0 tests and not fail the build + assertTrue(true) + } +} \ No newline at end of file diff --git a/sentry-samples/sentry-samples-log4j2/src/test/kotlin/io/sentry/systemtest/ConsoleApplicationSystemTest.kt b/sentry-samples/sentry-samples-log4j2/src/test/kotlin/io/sentry/systemtest/ConsoleApplicationSystemTest.kt new file mode 100644 index 00000000000..75ad7c13eaa --- /dev/null +++ b/sentry-samples/sentry-samples-log4j2/src/test/kotlin/io/sentry/systemtest/ConsoleApplicationSystemTest.kt @@ -0,0 +1,62 @@ +package io.sentry.systemtest.io.sentry.systemtest + +import io.sentry.SentryLevel +import io.sentry.systemtest.util.TestHelper +import org.junit.Assert +import org.junit.Before +import org.junit.Test +import java.util.concurrent.TimeUnit + +class ConsoleApplicationSystemTest { + lateinit var testHelper: TestHelper + + @Before + fun setup() { + testHelper = TestHelper("http://localhost:8000") + testHelper.reset() + } + + @Test + fun `log4j2 application sends expected events when run as JAR`() { + val jarFile = testHelper.findJar("sentry-samples-log4j2") + val process = + testHelper.launch( + jarFile, + mapOf( + "SENTRY_DSN" to testHelper.dsn, + "SENTRY_TRACES_SAMPLE_RATE" to "1.0", + "SENTRY_ENABLE_PRETTY_SERIALIZATION_OUTPUT" to "false", + "SENTRY_DEBUG" to "true", + ), + ) + + process.waitFor(30, TimeUnit.SECONDS) + Assert.assertEquals(0, process.exitValue()) + + // Verify that we received the expected events + verifyExpectedEvents() + } + + private fun verifyExpectedEvents() { + // Verify we received the RuntimeException + testHelper.ensureErrorReceived { event -> + event.exceptions?.any { ex -> ex.type == "RuntimeException" && ex.value == "Invalid productId=445" } == + true && + event.message?.formatted == "Something went wrong" && + event.level?.name == "ERROR" + } + + testHelper.ensureErrorReceived { event -> + event.breadcrumbs?.firstOrNull { it.message == "Hello Sentry!" && it.level == SentryLevel.DEBUG } != null + } + + testHelper.ensureErrorReceived { event -> + event.breadcrumbs?.firstOrNull { it.message == "User has made a purchase of product: 445" && it.level == SentryLevel.INFO } != null + } + + testHelper.ensureLogsReceived { logs, _ -> + testHelper.doesContainLogWithBody(logs, "User has made a purchase of product: 445") && + testHelper.doesContainLogWithBody(logs, "Something went wrong") + } + } +} \ No newline at end of file diff --git a/test/system-test-runner.py b/test/system-test-runner.py index fda5042c819..be9a1875f77 100644 --- a/test/system-test-runner.py +++ b/test/system-test-runner.py @@ -588,6 +588,8 @@ def get_available_modules(self) -> List[ModuleConfig]: ModuleConfig("sentry-samples-spring-boot-jakarta-opentelemetry", "true", "false", "false"), ModuleConfig("sentry-samples-console", "false", "true", "false"), ModuleConfig("sentry-samples-console-opentelemetry-noagent", "false", "true", "false"), + ModuleConfig("sentry-samples-logback", "false", "true", "false"), + ModuleConfig("sentry-samples-log4j2", "false", "true", "false"), ] def _find_module_number(self, module_name: str, agent: str, auto_init: str) -> int: From 2ab1c1e041247ba17a42cd0914f88417f9b897fd Mon Sep 17 00:00:00 2001 From: Sentry Github Bot Date: Mon, 4 Aug 2025 11:31:57 +0000 Subject: [PATCH 2/4] Format code --- .../sentry-samples-log4j2/build.gradle.kts | 4 +++- .../src/test/kotlin/io/sentry/DummyTest.kt | 2 +- .../systemtest/ConsoleApplicationSystemTest.kt | 17 +++++++++++------ 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/sentry-samples/sentry-samples-log4j2/build.gradle.kts b/sentry-samples/sentry-samples-log4j2/build.gradle.kts index 6cbd5640f7d..a52a5720d5f 100644 --- a/sentry-samples/sentry-samples-log4j2/build.gradle.kts +++ b/sentry-samples/sentry-samples-log4j2/build.gradle.kts @@ -51,7 +51,9 @@ tasks.shadowJar { archiveClassifier.set("") // Remove the classifier so it replaces the regular JAR mergeServiceFiles() // Use Log4j2 cache transformer to properly handle plugin files - transform(com.github.jengelman.gradle.plugins.shadow.transformers.Log4j2PluginsCacheFileTransformer()) + transform( + com.github.jengelman.gradle.plugins.shadow.transformers.Log4j2PluginsCacheFileTransformer() + ) } // Make the regular jar task depend on shadowJar diff --git a/sentry-samples/sentry-samples-log4j2/src/test/kotlin/io/sentry/DummyTest.kt b/sentry-samples/sentry-samples-log4j2/src/test/kotlin/io/sentry/DummyTest.kt index 331f462c55e..6f762b7e453 100644 --- a/sentry-samples/sentry-samples-log4j2/src/test/kotlin/io/sentry/DummyTest.kt +++ b/sentry-samples/sentry-samples-log4j2/src/test/kotlin/io/sentry/DummyTest.kt @@ -9,4 +9,4 @@ class DummyTest { // only needed to have more than 0 tests and not fail the build assertTrue(true) } -} \ No newline at end of file +} diff --git a/sentry-samples/sentry-samples-log4j2/src/test/kotlin/io/sentry/systemtest/ConsoleApplicationSystemTest.kt b/sentry-samples/sentry-samples-log4j2/src/test/kotlin/io/sentry/systemtest/ConsoleApplicationSystemTest.kt index 75ad7c13eaa..97691fed7fe 100644 --- a/sentry-samples/sentry-samples-log4j2/src/test/kotlin/io/sentry/systemtest/ConsoleApplicationSystemTest.kt +++ b/sentry-samples/sentry-samples-log4j2/src/test/kotlin/io/sentry/systemtest/ConsoleApplicationSystemTest.kt @@ -2,10 +2,10 @@ package io.sentry.systemtest.io.sentry.systemtest import io.sentry.SentryLevel import io.sentry.systemtest.util.TestHelper +import java.util.concurrent.TimeUnit import org.junit.Assert import org.junit.Before import org.junit.Test -import java.util.concurrent.TimeUnit class ConsoleApplicationSystemTest { lateinit var testHelper: TestHelper @@ -40,18 +40,23 @@ class ConsoleApplicationSystemTest { private fun verifyExpectedEvents() { // Verify we received the RuntimeException testHelper.ensureErrorReceived { event -> - event.exceptions?.any { ex -> ex.type == "RuntimeException" && ex.value == "Invalid productId=445" } == - true && + event.exceptions?.any { ex -> + ex.type == "RuntimeException" && ex.value == "Invalid productId=445" + } == true && event.message?.formatted == "Something went wrong" && event.level?.name == "ERROR" } testHelper.ensureErrorReceived { event -> - event.breadcrumbs?.firstOrNull { it.message == "Hello Sentry!" && it.level == SentryLevel.DEBUG } != null + event.breadcrumbs?.firstOrNull { + it.message == "Hello Sentry!" && it.level == SentryLevel.DEBUG + } != null } testHelper.ensureErrorReceived { event -> - event.breadcrumbs?.firstOrNull { it.message == "User has made a purchase of product: 445" && it.level == SentryLevel.INFO } != null + event.breadcrumbs?.firstOrNull { + it.message == "User has made a purchase of product: 445" && it.level == SentryLevel.INFO + } != null } testHelper.ensureLogsReceived { logs, _ -> @@ -59,4 +64,4 @@ class ConsoleApplicationSystemTest { testHelper.doesContainLogWithBody(logs, "Something went wrong") } } -} \ No newline at end of file +} From 1b71e7cbecb0f03d419a6dc945a66e37c7f20652 Mon Sep 17 00:00:00 2001 From: Alexander Dinauer Date: Wed, 13 Aug 2025 09:05:13 +0200 Subject: [PATCH 3/4] codereview fixes --- sentry-samples/sentry-samples-log4j2/build.gradle.kts | 4 ---- .../io/sentry/systemtest/ConsoleApplicationSystemTest.kt | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/sentry-samples/sentry-samples-log4j2/build.gradle.kts b/sentry-samples/sentry-samples-log4j2/build.gradle.kts index a52a5720d5f..75b2a991fa2 100644 --- a/sentry-samples/sentry-samples-log4j2/build.gradle.kts +++ b/sentry-samples/sentry-samples-log4j2/build.gradle.kts @@ -21,10 +21,6 @@ configure { targetCompatibility = JavaVersion.VERSION_17 } -tasks.withType().configureEach { - kotlinOptions.jvmTarget = JavaVersion.VERSION_17.toString() -} - tasks.withType().configureEach { kotlinOptions { freeCompilerArgs = listOf("-Xjsr305=strict") diff --git a/sentry-samples/sentry-samples-log4j2/src/test/kotlin/io/sentry/systemtest/ConsoleApplicationSystemTest.kt b/sentry-samples/sentry-samples-log4j2/src/test/kotlin/io/sentry/systemtest/ConsoleApplicationSystemTest.kt index 97691fed7fe..eed0354863f 100644 --- a/sentry-samples/sentry-samples-log4j2/src/test/kotlin/io/sentry/systemtest/ConsoleApplicationSystemTest.kt +++ b/sentry-samples/sentry-samples-log4j2/src/test/kotlin/io/sentry/systemtest/ConsoleApplicationSystemTest.kt @@ -1,4 +1,4 @@ -package io.sentry.systemtest.io.sentry.systemtest +package io.sentry.systemtest import io.sentry.SentryLevel import io.sentry.systemtest.util.TestHelper From b8fe65fc3457d393d4e983cf5408bd329119275c Mon Sep 17 00:00:00 2001 From: Alexander Dinauer Date: Wed, 13 Aug 2025 09:06:57 +0200 Subject: [PATCH 4/4] add to CI matrix --- .github/workflows/system-tests-backend.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/system-tests-backend.yml b/.github/workflows/system-tests-backend.yml index 5b00a00d507..7a321474eac 100644 --- a/.github/workflows/system-tests-backend.yml +++ b/.github/workflows/system-tests-backend.yml @@ -57,6 +57,9 @@ jobs: - sample: "sentry-samples-logback" agent: "false" agent-auto-init: "true" + - sample: "sentry-samples-log4j2" + agent: "false" + agent-auto-init: "true" steps: - uses: actions/checkout@v4 with: