Commit 028aa67
feat(spring): Cache Tracing (#5165)
* feat(spring): [Cache Tracing 1] Add SentryCacheWrapper and SentryCacheManagerWrapper
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* collection: Cache Tracing
* fix(cache): Fix span description, putIfAbsent, and Callable hit detection
- Use cache key as span description instead of cache name, matching
the spec and other SDKs (Python, JavaScript)
- Skip instrumentation for putIfAbsent since we cannot know if a write
actually occurred; override to bypass default get()+put() delegation
- Wrap valueLoader Callable in get(key, Callable) to detect cache
hit/miss instead of always reporting hit=true
- Update tests to match new behavior
Co-Authored-By: Claude <noreply@anthropic.com>
* feat(core): [Cache Tracing 2] Add enableCacheTracing option
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat(spring): [Cache Tracing 3] Add BeanPostProcessor and auto-configuration
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* changelog
* fix: Update changelog PR references
Co-Authored-By: Claude <noreply@anthropic.com>
* feat(samples): [Cache Tracing 4] Add cache tracing e2e sample
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* ref(samples): Replace ConcurrentMapCacheManager with Caffeine
Use Caffeine as the cache provider instead of a plain
ConcurrentMapCacheManager. Spring Boot auto-configures
CaffeineCacheManager when Caffeine is on the classpath,
so the explicit CacheManager bean is no longer needed.
Co-Authored-By: Claude <noreply@anthropic.com>
* fix dependencies; move to toml
* feat(jcache): Add SentryJCacheWrapper for JCache (JSR-107) cache tracing
* changelog
* fix(jcache): Make replace and getAndReplace passthrough (no span)
Like putIfAbsent, these are conditional writes that may be no-ops.
Emitting a cache.put span for them would be misleading.
* fix(jcache): Check for NoOp span after startChild
startChild can return a NoOp span (e.g. when span limit is reached).
Skip instrumentation in that case to avoid unnecessary work.
* fix(jcache): Use cache.flush for removeAll() without keys
removeAll() with no args removes all entries, which is semantically
equivalent to clear(). Use cache.flush instead of cache.remove.
The keyed removeAll(Set) remains cache.remove.
* feat(samples): Add JCache cache tracing demo to console sample
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* changelog
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* changelog
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(core): Use correct cache span op terminology in Javadoc
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* changelog
* fix(spring7): Avoid double-wrapping caches in SentryCacheManagerWrapper
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat(samples): Add cache tracing to all Spring Boot 4 samples
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(test): Add SENTRY_ENABLE_CACHE_TRACING env var to system test runner
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat(jcache): Add SentryJCacheWrapper ctor that uses ScopesAdapter
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat(spring7): Add retrieve() overrides to SentryCacheWrapper
Adds support for Spring 6.1+ async cache operations (CompletableFuture
and Mono/Flux). Without these overrides, @Cacheable on reactive return
types crashes with UnsupportedOperationException.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat(spring-jakarta): Add cache tracing for Spring Boot 3 / Spring 6
Port cache tracing classes from sentry-spring-7 to sentry-spring-jakarta,
covering Spring Boot 3 (Spring Framework 6.x) users. Includes
SentryCacheWrapper, SentryCacheManagerWrapper, SentryCacheBeanPostProcessor,
and auto-configuration in sentry-spring-boot-jakarta.
The retrieve() overrides for CompletableFuture/reactive cache operations
are included and safe on Spring 6.0 (where retrieve() doesn't exist on
the Cache interface) — they're simply dead code, never called by the
framework until Spring 6.1+.
Co-Authored-By: Claude <noreply@anthropic.com>
* 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>
* feat(spring): Add cache tracing for Spring Boot 2 / Spring 5
Port cache tracing instrumentation from sentry-spring-jakarta to
sentry-spring for Spring Boot 2 users. Adds SentryCacheWrapper,
SentryCacheManagerWrapper, and SentryCacheBeanPostProcessor in the
io.sentry.spring.cache package. Wires auto-configuration in
sentry-spring-boot via sentry.enable-cache-tracing=true property.
The retrieve() methods are omitted since Spring 5 does not have them
(they were added in Spring 6.1).
Co-Authored-By: Claude <noreply@anthropic.com>
* feat(samples): Add cache tracing to Spring Boot 2 sample
Add CacheController, TodoService with @Cacheable/@CachePut/@CacheEvict
annotations, and CacheSystemTest e2e tests to the sentry-samples-spring-boot
sample. Enables cache tracing with Caffeine as the cache provider.
Co-Authored-By: Claude <noreply@anthropic.com>
* changelog
* fix(spring): Skip cache span data when child span is NoOp
Add span.isNoOp() check after startChild() in all three Spring
SentryCacheWrapper variants, matching the existing pattern in
SentryJCacheWrapper. This avoids setting span data on noop spans
when sampling drops the span.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat(spring): Add db.operation.name attribute to cache spans
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat(spring): Instrument putIfAbsent, replace, and getAndReplace cache operations
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(spring): Use ValueWrapper to determine cache hit in typed get
The get(key, type) method incorrectly used result != null to detect
cache hits, failing to distinguish a miss from a cached null value.
Now uses delegate.get(key) to check the ValueWrapper first.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* docs(jcache): Fix docs link in README
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* ref(spring): Use method-specific span operations for cache spans
Instead of the 4 generic categories (cache.get, cache.put,
cache.remove, cache.flush), use the actual method name as the span
operation (e.g. cache.evict, cache.putIfAbsent, cache.retrieve).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* ref(spring): Derive span operation from operationName in startSpan
Remove redundant first parameter since it was always "cache." +
operationName. The prefix is now applied inside the helper method.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* ref(jcache): Merge startSpanForKeys into startSpan overload
Replace the separate startSpanForKeys helper with a startSpan(Set, String)
overload, unifying the two span creation methods under the same name.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Format code
* ref(cache): Move operation attribute to SpanDataConvention as CACHE_OPERATION_KEY
Replace local OPERATION_ATTRIBUTE constants in all cache wrappers with
a shared CACHE_OPERATION_KEY constant in SpanDataConvention. Also
changes the attribute key from "db.operation.name" to "cache.operation".
* feat(cache): Add cache.write boolean span attribute
Set cache.write on spans across all four cache wrapper implementations
to indicate whether an operation actually modified the cache. This
complements the existing cache.hit attribute for read operations.
Co-Authored-By: Claude <noreply@anthropic.com>
* fix(jcache): Use comma-joined keys as span description for bulk operations
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* ref(cache): Remove _KEY suffix from cache SpanDataConvention constants
Rename CACHE_HIT_KEY, CACHE_KEY_KEY, and CACHE_OPERATION_KEY to
CACHE_HIT, CACHE_KEY, and CACHE_OPERATION to match the newer naming
convention used by CACHE_WRITE, THREAD_ID, FRAMES_TOTAL, etc.
Co-Authored-By: Claude <noreply@anthropic.com>
* fix(spring): Fix get(key, type) double-call in SentryCacheWrapper
Use a single delegate.get(key, type) call instead of calling
delegate.get(key) for hit detection and delegate.get(key, type) for
the actual value. This eliminates doubled cache round trips (e.g. Redis
network calls) and a TOCTOU race where the entry could expire between
the two calls.
The trade-off is that cached null values are now indistinguishable from
cache misses, which is acceptable for observability purposes.
* fix(samples): Fix cache evict system test to match actual span op
* assert multiple keys in single assertions
* Format code
* update PR links in changelog
* fix(spring): [Cache Tracing 24] Track invalidate cache.write accurately
Set cache.write based on delegate.invalidate() result instead of always true.
This keeps span data aligned with Spring's invalidate semantics when no
entries were present.
Add tests in spring, spring-jakarta, and spring-7 wrappers to cover the
false return path and assert cache.write is false.
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Sentry Github Bot <bot+github-bot@sentry.io>1 parent 23b2680 commit 028aa67
File tree
100 files changed
+5447
-1
lines changed- buildSrc/src/main/java
- gradle
- sentry-jcache
- api
- src
- main/java/io/sentry/jcache
- test/kotlin/io/sentry/jcache
- sentry-samples
- sentry-samples-console
- src/main/java/io/sentry/samples/console
- sentry-samples-spring-boot-4-opentelemetry
- src
- main
- java/io/sentry/samples/spring/boot4
- resources
- test/kotlin/io/sentry/systemtest
- sentry-samples-spring-boot-4-otlp
- src
- main
- java/io/sentry/samples/spring/boot4/otlp
- resources
- test/kotlin/io/sentry/systemtest
- sentry-samples-spring-boot-4-webflux
- src
- main
- java/io/sentry/samples/spring/boot4
- resources
- test/kotlin/io/sentry/systemtest
- sentry-samples-spring-boot-4
- src
- main
- java/io/sentry/samples/spring/boot4
- resources
- test/kotlin/io/sentry/systemtest
- sentry-samples-spring-boot-jakarta-opentelemetry-noagent
- src
- main
- java/io/sentry/samples/spring/boot/jakarta
- resources
- test/kotlin/io/sentry/systemtest
- sentry-samples-spring-boot-jakarta-opentelemetry
- src
- main
- java/io/sentry/samples/spring/boot/jakarta
- resources
- test/kotlin/io/sentry/systemtest
- sentry-samples-spring-boot-jakarta
- src
- main
- java/io/sentry/samples/spring/boot/jakarta
- resources
- test/kotlin/io/sentry/systemtest
- sentry-samples-spring-boot-webflux-jakarta
- src
- main
- java/io/sentry/samples/spring/boot/jakarta
- resources
- test/kotlin/io/sentry/systemtest
- sentry-samples-spring-boot
- src
- main
- java/io/sentry/samples/spring/boot
- resources
- test/kotlin/io/sentry/systemtest
- sentry-spring-7
- api
- src
- main/java/io/sentry/spring7/cache
- test/kotlin/io/sentry/spring7/cache
- sentry-spring-boot-4/src
- main/java/io/sentry/spring/boot4
- test/kotlin/io/sentry/spring/boot4
- sentry-spring-boot-jakarta/src/main/java/io/sentry/spring/boot/jakarta
- sentry-spring-boot/src/main/java/io/sentry/spring/boot
- sentry-spring-jakarta
- api
- src
- main/java/io/sentry/spring/jakarta/cache
- test/kotlin/io/sentry/spring/jakarta/cache
- sentry-spring
- api
- src
- main/java/io/sentry/spring/cache
- test/kotlin/io/sentry/spring/cache
- sentry-system-test-support
- api
- src/main/kotlin/io/sentry/systemtest/util
- sentry
- api
- src
- main/java/io/sentry
- test/java/io/sentry
- test
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
100 files changed
+5447
-1
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
8 | 8 | | |
9 | 9 | | |
10 | 10 | | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
11 | 17 | | |
12 | 18 | | |
13 | 19 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
57 | 57 | | |
58 | 58 | | |
59 | 59 | | |
| 60 | + | |
60 | 61 | | |
61 | 62 | | |
62 | 63 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
77 | 77 | | |
78 | 78 | | |
79 | 79 | | |
| 80 | + | |
80 | 81 | | |
81 | 82 | | |
82 | 83 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
99 | 99 | | |
100 | 100 | | |
101 | 101 | | |
| 102 | + | |
| 103 | + | |
102 | 104 | | |
103 | 105 | | |
104 | 106 | | |
| |||
144 | 146 | | |
145 | 147 | | |
146 | 148 | | |
| 149 | + | |
147 | 150 | | |
148 | 151 | | |
149 | 152 | | |
| |||
166 | 169 | | |
167 | 170 | | |
168 | 171 | | |
| 172 | + | |
169 | 173 | | |
170 | 174 | | |
171 | 175 | | |
| |||
178 | 182 | | |
179 | 183 | | |
180 | 184 | | |
| 185 | + | |
181 | 186 | | |
182 | 187 | | |
183 | 188 | | |
| |||
193 | 198 | | |
194 | 199 | | |
195 | 200 | | |
| 201 | + | |
196 | 202 | | |
197 | 203 | | |
198 | 204 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
0 commit comments