Skip to content

Commit 96301df

Browse files
Add E2E tests for Log4j2 (#4600)
* Add E2E tests for Log4j2 * Format code * codereview fixes * add to CI matrix --------- Co-authored-by: Sentry Github Bot <[email protected]>
1 parent 2dbdf6c commit 96301df

File tree

5 files changed

+152
-2
lines changed

5 files changed

+152
-2
lines changed

.github/workflows/system-tests-backend.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@ jobs:
5757
- sample: "sentry-samples-logback"
5858
agent: "false"
5959
agent-auto-init: "true"
60+
- sample: "sentry-samples-log4j2"
61+
agent: "false"
62+
agent-auto-init: "true"
6063
steps:
6164
- uses: actions/checkout@v4
6265
with:
Lines changed: 69 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,85 @@
1+
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
2+
13
plugins {
24
java
35
application
6+
kotlin("jvm")
47
alias(libs.plugins.gradle.versions)
8+
id("com.github.johnrengelman.shadow") version "8.1.1"
59
}
610

711
application { mainClass.set("io.sentry.samples.log4j2.Main") }
812

13+
java.sourceCompatibility = JavaVersion.VERSION_17
14+
15+
java.targetCompatibility = JavaVersion.VERSION_17
16+
17+
repositories { mavenCentral() }
18+
919
configure<JavaPluginExtension> {
10-
sourceCompatibility = JavaVersion.VERSION_1_8
11-
targetCompatibility = JavaVersion.VERSION_1_8
20+
sourceCompatibility = JavaVersion.VERSION_17
21+
targetCompatibility = JavaVersion.VERSION_17
22+
}
23+
24+
tasks.withType<KotlinCompile>().configureEach {
25+
kotlinOptions {
26+
freeCompilerArgs = listOf("-Xjsr305=strict")
27+
jvmTarget = JavaVersion.VERSION_17.toString()
28+
}
1229
}
1330

1431
dependencies {
1532
implementation(projects.sentryLog4j2)
1633
implementation(libs.log4j.api)
1734
implementation(libs.log4j.core)
35+
36+
testImplementation(kotlin(Config.kotlinStdLib))
37+
testImplementation(projects.sentry)
38+
testImplementation(projects.sentrySystemTestSupport)
39+
testImplementation(libs.kotlin.test.junit)
40+
testImplementation(libs.slf4j.api)
41+
testImplementation(libs.slf4j.jdk14)
42+
}
43+
44+
// Configure the Shadow JAR (executable JAR with all dependencies)
45+
tasks.shadowJar {
46+
manifest { attributes["Main-Class"] = "io.sentry.samples.log4j2.Main" }
47+
archiveClassifier.set("") // Remove the classifier so it replaces the regular JAR
48+
mergeServiceFiles()
49+
// Use Log4j2 cache transformer to properly handle plugin files
50+
transform(
51+
com.github.jengelman.gradle.plugins.shadow.transformers.Log4j2PluginsCacheFileTransformer()
52+
)
53+
}
54+
55+
// Make the regular jar task depend on shadowJar
56+
tasks.jar {
57+
enabled = false
58+
dependsOn(tasks.shadowJar)
59+
}
60+
61+
// Fix the startScripts task dependency
62+
tasks.startScripts { dependsOn(tasks.shadowJar) }
63+
64+
configure<SourceSetContainer> { test { java.srcDir("src/test/java") } }
65+
66+
tasks.register<Test>("systemTest").configure {
67+
group = "verification"
68+
description = "Runs the System tests"
69+
70+
outputs.upToDateWhen { false }
71+
72+
maxParallelForks = 1
73+
74+
// Cap JVM args per test
75+
minHeapSize = "128m"
76+
maxHeapSize = "1g"
77+
78+
filter { includeTestsMatching("io.sentry.systemtest*") }
79+
}
80+
81+
tasks.named("test").configure {
82+
require(this is Test)
83+
84+
filter { excludeTestsMatching("io.sentry.systemtest.*") }
1885
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package io.sentry
2+
3+
import kotlin.test.Test
4+
import kotlin.test.assertTrue
5+
6+
class DummyTest {
7+
@Test
8+
fun `the only test`() {
9+
// only needed to have more than 0 tests and not fail the build
10+
assertTrue(true)
11+
}
12+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
package io.sentry.systemtest
2+
3+
import io.sentry.SentryLevel
4+
import io.sentry.systemtest.util.TestHelper
5+
import java.util.concurrent.TimeUnit
6+
import org.junit.Assert
7+
import org.junit.Before
8+
import org.junit.Test
9+
10+
class ConsoleApplicationSystemTest {
11+
lateinit var testHelper: TestHelper
12+
13+
@Before
14+
fun setup() {
15+
testHelper = TestHelper("http://localhost:8000")
16+
testHelper.reset()
17+
}
18+
19+
@Test
20+
fun `log4j2 application sends expected events when run as JAR`() {
21+
val jarFile = testHelper.findJar("sentry-samples-log4j2")
22+
val process =
23+
testHelper.launch(
24+
jarFile,
25+
mapOf(
26+
"SENTRY_DSN" to testHelper.dsn,
27+
"SENTRY_TRACES_SAMPLE_RATE" to "1.0",
28+
"SENTRY_ENABLE_PRETTY_SERIALIZATION_OUTPUT" to "false",
29+
"SENTRY_DEBUG" to "true",
30+
),
31+
)
32+
33+
process.waitFor(30, TimeUnit.SECONDS)
34+
Assert.assertEquals(0, process.exitValue())
35+
36+
// Verify that we received the expected events
37+
verifyExpectedEvents()
38+
}
39+
40+
private fun verifyExpectedEvents() {
41+
// Verify we received the RuntimeException
42+
testHelper.ensureErrorReceived { event ->
43+
event.exceptions?.any { ex ->
44+
ex.type == "RuntimeException" && ex.value == "Invalid productId=445"
45+
} == true &&
46+
event.message?.formatted == "Something went wrong" &&
47+
event.level?.name == "ERROR"
48+
}
49+
50+
testHelper.ensureErrorReceived { event ->
51+
event.breadcrumbs?.firstOrNull {
52+
it.message == "Hello Sentry!" && it.level == SentryLevel.DEBUG
53+
} != null
54+
}
55+
56+
testHelper.ensureErrorReceived { event ->
57+
event.breadcrumbs?.firstOrNull {
58+
it.message == "User has made a purchase of product: 445" && it.level == SentryLevel.INFO
59+
} != null
60+
}
61+
62+
testHelper.ensureLogsReceived { logs, _ ->
63+
testHelper.doesContainLogWithBody(logs, "User has made a purchase of product: 445") &&
64+
testHelper.doesContainLogWithBody(logs, "Something went wrong")
65+
}
66+
}
67+
}

test/system-test-runner.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -615,6 +615,7 @@ def get_available_modules(self) -> List[ModuleConfig]:
615615
ModuleConfig("sentry-samples-console", "false", "true", "false"),
616616
ModuleConfig("sentry-samples-console-opentelemetry-noagent", "false", "true", "false"),
617617
ModuleConfig("sentry-samples-logback", "false", "true", "false"),
618+
ModuleConfig("sentry-samples-log4j2", "false", "true", "false"),
618619
]
619620

620621
def _find_module_number(self, module_name: str, agent: str, auto_init: str) -> int:

0 commit comments

Comments
 (0)