Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 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
2 changes: 2 additions & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ androidx-recyclerview = { module = "androidx.recyclerview:recyclerview", version
androidx-browser = { module = "androidx.browser:browser", version = "1.8.0" }
async-profiler = { module = "tools.profiler:async-profiler", version.ref = "asyncProfiler" }
async-profiler-jfr-converter = { module = "tools.profiler:jfr-converter", version.ref = "asyncProfiler" }
caffeine = { module = "com.github.ben-manes.caffeine:caffeine" }
coil-compose = { module = "io.coil-kt:coil-compose", version = "2.6.0" }
commons-compress = {module = "org.apache.commons:commons-compress", version = "1.25.0"}
context-propagation = { module = "io.micrometer:context-propagation", version = "1.1.0" }
Expand Down Expand Up @@ -193,6 +194,7 @@ springboot4-starter-restclient = { module = "org.springframework.boot:spring-boo
springboot4-starter-webclient = { module = "org.springframework.boot:spring-boot-starter-webclient", version.ref = "springboot4" }
springboot4-starter-jdbc = { module = "org.springframework.boot:spring-boot-starter-jdbc", version.ref = "springboot4" }
springboot4-starter-actuator = { module = "org.springframework.boot:spring-boot-starter-actuator", version.ref = "springboot4" }
springboot4-starter-cache = { module = "org.springframework.boot:spring-boot-starter-cache", version.ref = "springboot4" }
timber = { module = "com.jakewharton.timber:timber", version = "4.7.1" }

# Animalsniffer signature
Expand Down
4 changes: 4 additions & 0 deletions sentry-samples/sentry-samples-spring-boot-4/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ dependencies {
implementation(projects.sentryQuartz)
implementation(projects.sentryAsyncProfiler)

// cache tracing
implementation(libs.springboot4.starter.cache)
implementation(libs.caffeine)

// database query tracing
implementation(projects.sentryJdbc)
runtimeOnly(libs.hsqldb)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package io.sentry.samples.spring.boot4;

import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/cache/")
public class CacheController {
private final TodoService todoService;

public CacheController(TodoService todoService) {
this.todoService = todoService;
}

@GetMapping("{id}")
Todo get(@PathVariable Long id) {
return todoService.get(id);
}

@PostMapping
Todo save(@RequestBody Todo todo) {
return todoService.save(todo);
}

@DeleteMapping("{id}")
void delete(@PathVariable Long id) {
todoService.delete(id);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.restclient.RestTemplateBuilder;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.quartz.CronTriggerFactoryBean;
Expand All @@ -19,6 +20,7 @@
import org.springframework.web.reactive.function.client.WebClient;

@SpringBootApplication
@EnableCaching
@EnableScheduling
public class SentryDemoApplication {
public static void main(String[] args) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package io.sentry.samples.spring.boot4;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

@Service
public class TodoService {
private final Map<Long, Todo> store = new ConcurrentHashMap<>();

@Cacheable(value = "todos", key = "#id")
public Todo get(Long id) {
return store.get(id);
}

@CachePut(value = "todos", key = "#todo.id")
public Todo save(Todo todo) {
store.put(todo.getId(), todo);
return todo;
}

@CacheEvict(value = "todos", key = "#id")
public void delete(Long id) {
store.remove(id);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ sentry.logs.enabled=true
sentry.profile-session-sample-rate=1.0
sentry.profiling-traces-dir-path=tmp/sentry/profiling-traces
sentry.profile-lifecycle=TRACE
sentry.enable-cache-tracing=true
spring.cache.cache-names=todos
spring.cache.caffeine.spec=maximumSize=500,expireAfterAccess=600s

# Uncomment and set to true to enable aot compatibility
# This flag disables all AOP related features (i.e. @SentryTransaction, @SentrySpan)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package io.sentry.systemtest

import io.sentry.systemtest.util.TestHelper
import kotlin.test.Test
import kotlin.test.assertEquals
import org.junit.Before

class CacheSystemTest {
lateinit var testHelper: TestHelper

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

@Test
fun `cache put and get produce spans`() {
val restClient = testHelper.restClient

// Save a todo (triggers @CachePut -> cache.put span)
val todo = Todo(1L, "test-todo", false)
restClient.saveCachedTodo(todo)
assertEquals(200, restClient.lastKnownStatusCode)

testHelper.ensureTransactionReceived { transaction, _ ->
testHelper.doesTransactionContainSpanWithOp(transaction, "cache.put")
}

testHelper.reset()

// Get the todo (triggers @Cacheable -> cache.get span, should be a hit)
restClient.getCachedTodo(1L)
assertEquals(200, restClient.lastKnownStatusCode)

testHelper.ensureTransactionReceived { transaction, _ ->
testHelper.doesTransactionContainSpanWithOp(transaction, "cache.get")
}
}

@Test
fun `cache evict produces span`() {
val restClient = testHelper.restClient

restClient.deleteCachedTodo(1L)

testHelper.ensureTransactionReceived { transaction, _ ->
testHelper.doesTransactionContainSpanWithOp(transaction, "cache.remove")
}
}
}
3 changes: 3 additions & 0 deletions sentry-system-test-support/api/sentry-system-test-support.api
Original file line number Diff line number Diff line change
Expand Up @@ -548,7 +548,9 @@ public final class io/sentry/systemtest/util/RestTestClient : io/sentry/systemte
public static synthetic fun createPerson$default (Lio/sentry/systemtest/util/RestTestClient;Lio/sentry/systemtest/Person;Ljava/util/Map;ILjava/lang/Object;)Lio/sentry/systemtest/Person;
public final fun createPersonDistributedTracing (Lio/sentry/systemtest/Person;Ljava/util/Map;)Lio/sentry/systemtest/Person;
public static synthetic fun createPersonDistributedTracing$default (Lio/sentry/systemtest/util/RestTestClient;Lio/sentry/systemtest/Person;Ljava/util/Map;ILjava/lang/Object;)Lio/sentry/systemtest/Person;
public final fun deleteCachedTodo (J)V
public final fun errorWithFeatureFlag (Ljava/lang/String;)Ljava/lang/String;
public final fun getCachedTodo (J)Lio/sentry/systemtest/Todo;
public final fun getCountMetric ()Ljava/lang/String;
public final fun getDistributionMetric (J)Ljava/lang/String;
public final fun getGaugeMetric (J)Ljava/lang/String;
Expand All @@ -558,6 +560,7 @@ public final class io/sentry/systemtest/util/RestTestClient : io/sentry/systemte
public final fun getTodo (J)Lio/sentry/systemtest/Todo;
public final fun getTodoRestClient (J)Lio/sentry/systemtest/Todo;
public final fun getTodoWebclient (J)Lio/sentry/systemtest/Todo;
public final fun saveCachedTodo (Lio/sentry/systemtest/Todo;)Lio/sentry/systemtest/Todo;
}

public final class io/sentry/systemtest/util/SentryMockServerClient : io/sentry/systemtest/util/LoggingInsecureRestClient {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,24 @@ class RestTestClient(private val backendBaseUrl: String) : LoggingInsecureRestCl
return callTyped(request, true)
}

fun getCachedTodo(id: Long): Todo? {
val request = Request.Builder().url("$backendBaseUrl/cache/$id")

return callTyped(request, true)
}

fun saveCachedTodo(todo: Todo): Todo? {
val request = Request.Builder().url("$backendBaseUrl/cache/").post(toRequestBody(todo))

return callTyped(request, true)
}

fun deleteCachedTodo(id: Long) {
val request = Request.Builder().url("$backendBaseUrl/cache/$id").delete()

call(request, true)
}

fun checkFeatureFlag(flagKey: String): FeatureFlagResponse? {
val request = Request.Builder().url("$backendBaseUrl/feature-flag/check/$flagKey")

Expand Down
Loading