Skip to content

Commit 658e082

Browse files
adinauerclaude
andcommitted
feat(samples): Add cache tracing to all Spring Boot 3 Jakarta samples
Add CacheController, TodoService with @Cacheable/@CachePut/@CacheEvict, Caffeine cache config, and CacheSystemTest e2e tests to all four Jakarta sample modules: - sentry-samples-spring-boot-jakarta - sentry-samples-spring-boot-jakarta-opentelemetry - sentry-samples-spring-boot-jakarta-opentelemetry-noagent - sentry-samples-spring-boot-webflux-jakarta Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 4d9f683 commit 658e082

File tree

25 files changed

+501
-0
lines changed

25 files changed

+501
-0
lines changed

gradle/libs.versions.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,7 @@ springboot3-starter-aop = { module = "org.springframework.boot:spring-boot-start
181181
springboot3-starter-security = { module = "org.springframework.boot:spring-boot-starter-security", version.ref = "springboot3" }
182182
springboot3-starter-jdbc = { module = "org.springframework.boot:spring-boot-starter-jdbc", version.ref = "springboot3" }
183183
springboot3-starter-actuator = { module = "org.springframework.boot:spring-boot-starter-actuator", version.ref = "springboot3" }
184+
springboot3-starter-cache = { module = "org.springframework.boot:spring-boot-starter-cache", version.ref = "springboot3" }
184185
springboot4-otel = { module = "io.opentelemetry.instrumentation:opentelemetry-spring-boot-starter", version.ref = "otelInstrumentation" }
185186
springboot4-resttestclient = { module = "org.springframework.boot:spring-boot-resttestclient", version.ref = "springboot4" }
186187
springboot4-starter = { module = "org.springframework.boot:spring-boot-starter", version.ref = "springboot4" }

sentry-samples/sentry-samples-spring-boot-jakarta-opentelemetry-noagent/build.gradle.kts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@ dependencies {
5252
implementation(projects.sentryAsyncProfiler)
5353
implementation(projects.sentryOpentelemetry.sentryOpentelemetryAgentlessSpring)
5454

55+
// cache tracing
56+
implementation(libs.springboot3.starter.cache)
57+
implementation(libs.caffeine)
58+
5559
// database query tracing
5660
implementation(projects.sentryJdbc)
5761
runtimeOnly(libs.hsqldb)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package io.sentry.samples.spring.boot.jakarta;
2+
3+
import org.springframework.web.bind.annotation.DeleteMapping;
4+
import org.springframework.web.bind.annotation.GetMapping;
5+
import org.springframework.web.bind.annotation.PathVariable;
6+
import org.springframework.web.bind.annotation.PostMapping;
7+
import org.springframework.web.bind.annotation.RequestBody;
8+
import org.springframework.web.bind.annotation.RequestMapping;
9+
import org.springframework.web.bind.annotation.RestController;
10+
11+
@RestController
12+
@RequestMapping("/cache/")
13+
public class CacheController {
14+
private final TodoService todoService;
15+
16+
public CacheController(TodoService todoService) {
17+
this.todoService = todoService;
18+
}
19+
20+
@GetMapping("{id}")
21+
Todo get(@PathVariable Long id) {
22+
return todoService.get(id);
23+
}
24+
25+
@PostMapping
26+
Todo save(@RequestBody Todo todo) {
27+
return todoService.save(todo);
28+
}
29+
30+
@DeleteMapping("{id}")
31+
void delete(@PathVariable Long id) {
32+
todoService.delete(id);
33+
}
34+
}

sentry-samples/sentry-samples-spring-boot-jakarta-opentelemetry-noagent/src/main/java/io/sentry/samples/spring/boot/jakarta/SentryDemoApplication.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import org.springframework.boot.SpringApplication;
1212
import org.springframework.boot.autoconfigure.SpringBootApplication;
1313
import org.springframework.boot.web.client.RestTemplateBuilder;
14+
import org.springframework.cache.annotation.EnableCaching;
1415
import org.springframework.context.annotation.Bean;
1516
import org.springframework.scheduling.annotation.EnableScheduling;
1617
import org.springframework.scheduling.quartz.CronTriggerFactoryBean;
@@ -21,6 +22,7 @@
2122
import org.springframework.web.reactive.function.client.WebClient;
2223

2324
@SpringBootApplication
25+
@EnableCaching
2426
@EnableScheduling
2527
public class SentryDemoApplication {
2628
public static void main(String[] args) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package io.sentry.samples.spring.boot.jakarta;
2+
3+
import java.util.Map;
4+
import java.util.concurrent.ConcurrentHashMap;
5+
import org.springframework.cache.annotation.CacheEvict;
6+
import org.springframework.cache.annotation.CachePut;
7+
import org.springframework.cache.annotation.Cacheable;
8+
import org.springframework.stereotype.Service;
9+
10+
@Service
11+
public class TodoService {
12+
private final Map<Long, Todo> store = new ConcurrentHashMap<>();
13+
14+
@Cacheable(value = "todos", key = "#id")
15+
public Todo get(Long id) {
16+
return store.get(id);
17+
}
18+
19+
@CachePut(value = "todos", key = "#todo.id")
20+
public Todo save(Todo todo) {
21+
store.put(todo.getId(), todo);
22+
return todo;
23+
}
24+
25+
@CacheEvict(value = "todos", key = "#id")
26+
public void delete(Long id) {
27+
store.remove(id);
28+
}
29+
}

sentry-samples/sentry-samples-spring-boot-jakarta-opentelemetry-noagent/src/main/resources/application.properties

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,11 @@ spring.graphql.graphiql.enabled=true
3535
spring.graphql.websocket.path=/graphql
3636
spring.quartz.job-store-type=memory
3737

38+
# Cache tracing
39+
sentry.enable-cache-tracing=true
40+
spring.cache.cache-names=todos
41+
spring.cache.caffeine.spec=maximumSize=500,expireAfterAccess=600s
42+
3843
# OTEL configuration
3944
otel.propagators=tracecontext,baggage,sentry
4045
otel.logs.exporter=none
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package io.sentry.systemtest
2+
3+
import io.sentry.systemtest.util.TestHelper
4+
import kotlin.test.Test
5+
import kotlin.test.assertEquals
6+
import org.junit.Before
7+
8+
class CacheSystemTest {
9+
lateinit var testHelper: TestHelper
10+
11+
@Before
12+
fun setup() {
13+
testHelper = TestHelper("http://localhost:8080")
14+
testHelper.reset()
15+
}
16+
17+
@Test
18+
fun `cache put and get produce spans`() {
19+
val restClient = testHelper.restClient
20+
21+
// Save a todo (triggers @CachePut -> cache.put span)
22+
val todo = Todo(1L, "test-todo", false)
23+
restClient.saveCachedTodo(todo)
24+
assertEquals(200, restClient.lastKnownStatusCode)
25+
26+
testHelper.ensureTransactionReceived { transaction, _ ->
27+
testHelper.doesTransactionContainSpanWithOp(transaction, "cache.put")
28+
}
29+
30+
testHelper.reset()
31+
32+
// Get the todo (triggers @Cacheable -> cache.get span, should be a hit)
33+
restClient.getCachedTodo(1L)
34+
assertEquals(200, restClient.lastKnownStatusCode)
35+
36+
testHelper.ensureTransactionReceived { transaction, _ ->
37+
testHelper.doesTransactionContainSpanWithOp(transaction, "cache.get")
38+
}
39+
}
40+
41+
@Test
42+
fun `cache evict produces span`() {
43+
val restClient = testHelper.restClient
44+
45+
restClient.deleteCachedTodo(1L)
46+
47+
testHelper.ensureTransactionReceived { transaction, _ ->
48+
testHelper.doesTransactionContainSpanWithOp(transaction, "cache.remove")
49+
}
50+
}
51+
}

sentry-samples/sentry-samples-spring-boot-jakarta-opentelemetry/build.gradle.kts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,10 @@ dependencies {
5656
implementation(libs.otel)
5757
implementation(projects.sentryAsyncProfiler)
5858

59+
// cache tracing
60+
implementation(libs.springboot3.starter.cache)
61+
implementation(libs.caffeine)
62+
5963
// database query tracing
6064
implementation(projects.sentryJdbc)
6165
runtimeOnly(libs.hsqldb)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package io.sentry.samples.spring.boot.jakarta;
2+
3+
import org.springframework.web.bind.annotation.DeleteMapping;
4+
import org.springframework.web.bind.annotation.GetMapping;
5+
import org.springframework.web.bind.annotation.PathVariable;
6+
import org.springframework.web.bind.annotation.PostMapping;
7+
import org.springframework.web.bind.annotation.RequestBody;
8+
import org.springframework.web.bind.annotation.RequestMapping;
9+
import org.springframework.web.bind.annotation.RestController;
10+
11+
@RestController
12+
@RequestMapping("/cache/")
13+
public class CacheController {
14+
private final TodoService todoService;
15+
16+
public CacheController(TodoService todoService) {
17+
this.todoService = todoService;
18+
}
19+
20+
@GetMapping("{id}")
21+
Todo get(@PathVariable Long id) {
22+
return todoService.get(id);
23+
}
24+
25+
@PostMapping
26+
Todo save(@RequestBody Todo todo) {
27+
return todoService.save(todo);
28+
}
29+
30+
@DeleteMapping("{id}")
31+
void delete(@PathVariable Long id) {
32+
todoService.delete(id);
33+
}
34+
}

sentry-samples/sentry-samples-spring-boot-jakarta-opentelemetry/src/main/java/io/sentry/samples/spring/boot/jakarta/SentryDemoApplication.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import org.springframework.boot.SpringApplication;
1212
import org.springframework.boot.autoconfigure.SpringBootApplication;
1313
import org.springframework.boot.web.client.RestTemplateBuilder;
14+
import org.springframework.cache.annotation.EnableCaching;
1415
import org.springframework.context.annotation.Bean;
1516
import org.springframework.scheduling.annotation.EnableScheduling;
1617
import org.springframework.scheduling.quartz.CronTriggerFactoryBean;
@@ -21,6 +22,7 @@
2122
import org.springframework.web.reactive.function.client.WebClient;
2223

2324
@SpringBootApplication
25+
@EnableCaching
2426
@EnableScheduling
2527
public class SentryDemoApplication {
2628
public static void main(String[] args) {

0 commit comments

Comments
 (0)