Skip to content

Add E2E tests for JUL #4598

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Aug 13, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/system-tests-backend.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ jobs:
- sample: "sentry-samples-log4j2"
agent: "false"
agent-auto-init: "true"
- sample: "sentry-samples-jul"
agent: "false"
agent-auto-init: "true"
steps:
- uses: actions/checkout@v4
with:
Expand Down
67 changes: 65 additions & 2 deletions sentry-samples/sentry-samples-jul/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,17 +1,80 @@
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.jul.Main") }

java.sourceCompatibility = JavaVersion.VERSION_17

java.targetCompatibility = JavaVersion.VERSION_17

repositories { mavenCentral() }

configure<JavaPluginExtension> {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}

tasks.withType<KotlinCompile>().configureEach {
kotlinOptions {
freeCompilerArgs = listOf("-Xjsr305=strict")
jvmTarget = JavaVersion.VERSION_17.toString()
}
}

dependencies {
implementation(projects.sentryJul)
implementation(libs.slf4j.jdk14)

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.jul.Main" }
archiveClassifier.set("") // Remove the classifier so it replaces the regular JAR
mergeServiceFiles()
}

// 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<SourceSetContainer> { test { java.srcDir("src/test/java") } }

tasks.register<Test>("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*") }
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Jar Task Disabled, ShadowJar Not Integrated

The jar task is disabled, and the shadowJar isn't integrated into the assemble or build lifecycle. The dependsOn on the disabled jar task has no effect. This means assemble doesn't produce a runnable JAR, causing system tests to fail when they look for the application JAR.

Fix in Cursor Fix in Web


tasks.named("test").configure {
require(this is Test)

filter { excludeTestsMatching("io.sentry.systemtest.*") }
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
io.sentry.jul.SentryHandler.minimumEventLevel=FINE
io.sentry.jul.SentryHandler.minimumEventLevel=INFO
io.sentry.jul.SentryHandler.minimumBreadcrumbLevel=CONFIG
io.sentry.jul.SentryHandler.minimumLevel=FINE
io.sentry.jul.SentryHandler.minimumLevel=INFO
io.sentry.jul.SentryHandler.printfStyle=true
io.sentry.jul.SentryHandler.level=CONFIG
io.sentry.jul.SentryHandler.level=FINEST
java.util.logging.ConsoleHandler.level = FINE
handlers=io.sentry.jul.SentryHandler
level=CONFIG
level=FINEST
io.sentry.samples.jul.Main.level=FINEST
Original file line number Diff line number Diff line change
@@ -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)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package 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

class ConsoleApplicationSystemTest {
lateinit var testHelper: TestHelper

@Before
fun setup() {
testHelper = TestHelper("http://localhost:8000")
testHelper.reset()
}

@Test
fun `jul application sends expected events when run as JAR`() {
val jarFile = testHelper.findJar("sentry-samples-jul")
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?.message == "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")
}
}
}
1 change: 1 addition & 0 deletions test/system-test-runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -616,6 +616,7 @@ def get_available_modules(self) -> List[ModuleConfig]:
ModuleConfig("sentry-samples-console-opentelemetry-noagent", "false", "true", "false"),
ModuleConfig("sentry-samples-logback", "false", "true", "false"),
ModuleConfig("sentry-samples-log4j2", "false", "true", "false"),
ModuleConfig("sentry-samples-jul", "false", "true", "false"),
]

def _find_module_number(self, module_name: str, agent: str, auto_init: str) -> int:
Expand Down
Loading