feat(spring): [Cache Tracing 12] Add db.operation.name attribute to cache spans#5201
feat(spring): [Cache Tracing 12] Add db.operation.name attribute to cache spans#5201adinauer wants to merge 1 commit intofix/cache-tracing-noop-spanfrom
Conversation
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Semver Impact of This PR🟡 Minor (new features) 📋 Changelog PreviewThis is how your changes will appear in the changelog. This PR will not appear in the changelog. 🤖 This preview updates automatically when you update the PR. |
|
|
@sentry review |
|
cursor review |
Sentry Build Distribution
|
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix prepared a fix for the issue found in the latest run.
- ✅ Fixed: Duplicated constant belongs in shared SpanDataConvention interface
- Added
DB_OPERATION_NAME_KEYtoSpanDataConventionand updated all cache wrappers to use it instead of duplicated local constants.
- Added
Or push these changes by commenting:
@cursor push eebc04ec98
Preview (eebc04ec98)
diff --git a/sentry-jcache/src/main/java/io/sentry/jcache/SentryJCacheWrapper.java b/sentry-jcache/src/main/java/io/sentry/jcache/SentryJCacheWrapper.java
--- a/sentry-jcache/src/main/java/io/sentry/jcache/SentryJCacheWrapper.java
+++ b/sentry-jcache/src/main/java/io/sentry/jcache/SentryJCacheWrapper.java
@@ -33,7 +33,6 @@
public final class SentryJCacheWrapper<K, V> implements Cache<K, V> {
private static final String TRACE_ORIGIN = "auto.cache.jcache";
- private static final String OPERATION_ATTRIBUTE = "db.operation.name";
private final @NotNull Cache<K, V> delegate;
private final @NotNull IScopes scopes;
@@ -424,7 +423,7 @@
if (keyString != null) {
span.setData(SpanDataConvention.CACHE_KEY_KEY, Arrays.asList(keyString));
}
- span.setData(OPERATION_ATTRIBUTE, operationName);
+ span.setData(SpanDataConvention.DB_OPERATION_NAME_KEY, operationName);
return span;
}
@@ -450,7 +449,7 @@
span.setData(
SpanDataConvention.CACHE_KEY_KEY,
keys.stream().map(String::valueOf).collect(Collectors.toList()));
- span.setData(OPERATION_ATTRIBUTE, operationName);
+ span.setData(SpanDataConvention.DB_OPERATION_NAME_KEY, operationName);
return span;
}
}
diff --git a/sentry-spring-7/src/main/java/io/sentry/spring7/cache/SentryCacheWrapper.java b/sentry-spring-7/src/main/java/io/sentry/spring7/cache/SentryCacheWrapper.java
--- a/sentry-spring-7/src/main/java/io/sentry/spring7/cache/SentryCacheWrapper.java
+++ b/sentry-spring-7/src/main/java/io/sentry/spring7/cache/SentryCacheWrapper.java
@@ -20,7 +20,6 @@
public final class SentryCacheWrapper implements Cache {
private static final String TRACE_ORIGIN = "auto.cache.spring";
- private static final String OPERATION_ATTRIBUTE = "db.operation.name";
private final @NotNull Cache delegate;
private final @NotNull IScopes scopes;
@@ -305,7 +304,7 @@
if (keyString != null) {
span.setData(SpanDataConvention.CACHE_KEY_KEY, Arrays.asList(keyString));
}
- span.setData(OPERATION_ATTRIBUTE, operationName);
+ span.setData(SpanDataConvention.DB_OPERATION_NAME_KEY, operationName);
return span;
}
}
diff --git a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/cache/SentryCacheWrapper.java b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/cache/SentryCacheWrapper.java
--- a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/cache/SentryCacheWrapper.java
+++ b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/cache/SentryCacheWrapper.java
@@ -20,7 +20,6 @@
public final class SentryCacheWrapper implements Cache {
private static final String TRACE_ORIGIN = "auto.cache.spring";
- private static final String OPERATION_ATTRIBUTE = "db.operation.name";
private final @NotNull Cache delegate;
private final @NotNull IScopes scopes;
@@ -305,7 +304,7 @@
if (keyString != null) {
span.setData(SpanDataConvention.CACHE_KEY_KEY, Arrays.asList(keyString));
}
- span.setData(OPERATION_ATTRIBUTE, operationName);
+ span.setData(SpanDataConvention.DB_OPERATION_NAME_KEY, operationName);
return span;
}
}
diff --git a/sentry-spring/src/main/java/io/sentry/spring/cache/SentryCacheWrapper.java b/sentry-spring/src/main/java/io/sentry/spring/cache/SentryCacheWrapper.java
--- a/sentry-spring/src/main/java/io/sentry/spring/cache/SentryCacheWrapper.java
+++ b/sentry-spring/src/main/java/io/sentry/spring/cache/SentryCacheWrapper.java
@@ -18,7 +18,6 @@
public final class SentryCacheWrapper implements Cache {
private static final String TRACE_ORIGIN = "auto.cache.spring";
- private static final String OPERATION_ATTRIBUTE = "db.operation.name";
private final @NotNull Cache delegate;
private final @NotNull IScopes scopes;
@@ -233,7 +232,7 @@
if (keyString != null) {
span.setData(SpanDataConvention.CACHE_KEY_KEY, Arrays.asList(keyString));
}
- span.setData(OPERATION_ATTRIBUTE, operationName);
+ span.setData(SpanDataConvention.DB_OPERATION_NAME_KEY, operationName);
return span;
}
}
diff --git a/sentry/api/sentry.api b/sentry/api/sentry.api
--- a/sentry/api/sentry.api
+++ b/sentry/api/sentry.api
@@ -4348,6 +4348,7 @@
public static final field CONTRIBUTES_TTFD Ljava/lang/String;
public static final field CONTRIBUTES_TTID Ljava/lang/String;
public static final field DB_NAME_KEY Ljava/lang/String;
+ public static final field DB_OPERATION_NAME_KEY Ljava/lang/String;
public static final field DB_SYSTEM_KEY Ljava/lang/String;
public static final field FRAMES_DELAY Ljava/lang/String;
public static final field FRAMES_FROZEN Ljava/lang/String;
diff --git a/sentry/src/main/java/io/sentry/SpanDataConvention.java b/sentry/src/main/java/io/sentry/SpanDataConvention.java
--- a/sentry/src/main/java/io/sentry/SpanDataConvention.java
+++ b/sentry/src/main/java/io/sentry/SpanDataConvention.java
@@ -8,6 +8,7 @@
// https://develop.sentry.dev/sdk/performance/span-data-conventions/
String DB_SYSTEM_KEY = "db.system";
String DB_NAME_KEY = "db.name";
+ String DB_OPERATION_NAME_KEY = "db.operation.name";
String HTTP_QUERY_KEY = "http.query";
String HTTP_FRAGMENT_KEY = "http.fragment";
String HTTP_METHOD_KEY = "http.request.method";This Bugbot Autofix run was free. To enable autofix for future PRs, go to the Cursor dashboard.
| public final class SentryJCacheWrapper<K, V> implements Cache<K, V> { | ||
|
|
||
| private static final String TRACE_ORIGIN = "auto.cache.jcache"; | ||
| private static final String OPERATION_ATTRIBUTE = "db.operation.name"; |
There was a problem hiding this comment.
Duplicated constant belongs in shared SpanDataConvention interface
Low Severity
The OPERATION_ATTRIBUTE = "db.operation.name" constant is independently defined as a private static final in four separate wrapper classes. All four files already import and use SpanDataConvention for CACHE_HIT_KEY and CACHE_KEY_KEY. Adding a DB_OPERATION_NAME_KEY constant to SpanDataConvention would follow the established pattern, eliminate the duplication, and ensure a single source of truth for this attribute name.
Additional Locations (2)
There was a problem hiding this comment.
As db.operation.name does not match any keys listed in the sentry span data convention here: https://develop.sentry.dev/sdk/performance/span-data-conventions/. I think it is fine as is. @adinauer wdyt?
There was a problem hiding this comment.
We can move the constant but I first have to clarify internally what the attribute key should be.
Performance metrics 🚀
|
lbloder
left a comment
There was a problem hiding this comment.
One open cursor question. LGTM otherwise
| public final class SentryJCacheWrapper<K, V> implements Cache<K, V> { | ||
|
|
||
| private static final String TRACE_ORIGIN = "auto.cache.jcache"; | ||
| private static final String OPERATION_ATTRIBUTE = "db.operation.name"; |
There was a problem hiding this comment.
As db.operation.name does not match any keys listed in the sentry span data convention here: https://develop.sentry.dev/sdk/performance/span-data-conventions/. I think it is fine as is. @adinauer wdyt?



PR Stack (Cache Tracing)
📜 Description
Add a
db.operation.namespan data attribute to every instrumented cache operation. The value is the name of the cache method being invoked (e.g.get,put,evict,retrieve,getAll,removeAll), allowing Sentry to distinguish between operations that share the same span op (e.g.evictvsevictIfPresentboth usecache.remove).Each wrapper class defines its own
private static final String OPERATION_ATTRIBUTE = "db.operation.name"constant. The attribute is set centrally in thestartSpan()/startSpanForKeys()helper methods via an addedoperationNameparameter.Modules changed:
sentry-spring— 8 call sitessentry-spring-7— 10 call sites (includesretrieve)sentry-spring-jakarta— 10 call sites (includesretrieve)sentry-jcache— 13 call sites💡 Motivation and Context
The
db.operation.nameattribute enables more granular cache operation visibility in the Sentry UI. Without it,evictandevictIfPresentare indistinguishable (bothcache.remove), andclearvsinvalidateare indistinguishable (bothcache.flush).💚 How did you test it?
Added
assertEquals("methodName", span.getData("db.operation.name"))assertions to all existing span tests across all 4 test files. All tests pass.📝 Checklist
sendDefaultPIIis enabled.🔮 Next steps
None — this is a self-contained enhancement.
#skip-changelog