Skip to content

Commit 5d8a445

Browse files
adinauerclaude
andcommitted
feat(spring): Add db.operation.name attribute to cache spans
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 5a729ca commit 5d8a445

File tree

8 files changed

+102
-46
lines changed

8 files changed

+102
-46
lines changed

sentry-jcache/src/main/java/io/sentry/jcache/SentryJCacheWrapper.java

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
public final class SentryJCacheWrapper<K, V> implements Cache<K, V> {
3434

3535
private static final String TRACE_ORIGIN = "auto.cache.jcache";
36+
private static final String OPERATION_ATTRIBUTE = "db.operation.name";
3637

3738
private final @NotNull Cache<K, V> delegate;
3839
private final @NotNull IScopes scopes;
@@ -50,7 +51,7 @@ public SentryJCacheWrapper(final @NotNull Cache<K, V> delegate, final @NotNull I
5051

5152
@Override
5253
public V get(final K key) {
53-
final ISpan span = startSpan("cache.get", key);
54+
final ISpan span = startSpan("cache.get", key, "get");
5455
if (span == null) {
5556
return delegate.get(key);
5657
}
@@ -70,7 +71,7 @@ public V get(final K key) {
7071

7172
@Override
7273
public Map<K, V> getAll(final Set<? extends K> keys) {
73-
final ISpan span = startSpanForKeys("cache.get", keys);
74+
final ISpan span = startSpanForKeys("cache.get", keys, "getAll");
7475
if (span == null) {
7576
return delegate.getAll(keys);
7677
}
@@ -97,7 +98,7 @@ public boolean containsKey(final K key) {
9798

9899
@Override
99100
public void put(final K key, final V value) {
100-
final ISpan span = startSpan("cache.put", key);
101+
final ISpan span = startSpan("cache.put", key, "put");
101102
if (span == null) {
102103
delegate.put(key, value);
103104
return;
@@ -116,7 +117,7 @@ public void put(final K key, final V value) {
116117

117118
@Override
118119
public V getAndPut(final K key, final V value) {
119-
final ISpan span = startSpan("cache.put", key);
120+
final ISpan span = startSpan("cache.put", key, "getAndPut");
120121
if (span == null) {
121122
return delegate.getAndPut(key, value);
122123
}
@@ -135,7 +136,7 @@ public V getAndPut(final K key, final V value) {
135136

136137
@Override
137138
public void putAll(final Map<? extends K, ? extends V> map) {
138-
final ISpan span = startSpanForKeys("cache.put", map.keySet());
139+
final ISpan span = startSpanForKeys("cache.put", map.keySet(), "putAll");
139140
if (span == null) {
140141
delegate.putAll(map);
141142
return;
@@ -181,7 +182,7 @@ public V getAndReplace(final K key, final V value) {
181182

182183
@Override
183184
public boolean remove(final K key) {
184-
final ISpan span = startSpan("cache.remove", key);
185+
final ISpan span = startSpan("cache.remove", key, "remove");
185186
if (span == null) {
186187
return delegate.remove(key);
187188
}
@@ -200,7 +201,7 @@ public boolean remove(final K key) {
200201

201202
@Override
202203
public boolean remove(final K key, final V oldValue) {
203-
final ISpan span = startSpan("cache.remove", key);
204+
final ISpan span = startSpan("cache.remove", key, "remove");
204205
if (span == null) {
205206
return delegate.remove(key, oldValue);
206207
}
@@ -219,7 +220,7 @@ public boolean remove(final K key, final V oldValue) {
219220

220221
@Override
221222
public V getAndRemove(final K key) {
222-
final ISpan span = startSpan("cache.remove", key);
223+
final ISpan span = startSpan("cache.remove", key, "getAndRemove");
223224
if (span == null) {
224225
return delegate.getAndRemove(key);
225226
}
@@ -238,7 +239,7 @@ public V getAndRemove(final K key) {
238239

239240
@Override
240241
public void removeAll(final Set<? extends K> keys) {
241-
final ISpan span = startSpanForKeys("cache.remove", keys);
242+
final ISpan span = startSpanForKeys("cache.remove", keys, "removeAll");
242243
if (span == null) {
243244
delegate.removeAll(keys);
244245
return;
@@ -257,7 +258,7 @@ public void removeAll(final Set<? extends K> keys) {
257258

258259
@Override
259260
public void removeAll() {
260-
final ISpan span = startSpan("cache.flush", null);
261+
final ISpan span = startSpan("cache.flush", null, "removeAll");
261262
if (span == null) {
262263
delegate.removeAll();
263264
return;
@@ -278,7 +279,7 @@ public void removeAll() {
278279

279280
@Override
280281
public void clear() {
281-
final ISpan span = startSpan("cache.flush", null);
282+
final ISpan span = startSpan("cache.flush", null, "clear");
282283
if (span == null) {
283284
delegate.clear();
284285
return;
@@ -306,7 +307,7 @@ public void close() {
306307
public <T> T invoke(
307308
final K key, final EntryProcessor<K, V, T> entryProcessor, final Object... arguments)
308309
throws EntryProcessorException {
309-
final ISpan span = startSpan("cache.get", key);
310+
final ISpan span = startSpan("cache.get", key, "invoke");
310311
if (span == null) {
311312
return delegate.invoke(key, entryProcessor, arguments);
312313
}
@@ -328,7 +329,7 @@ public <T> Map<K, EntryProcessorResult<T>> invokeAll(
328329
final Set<? extends K> keys,
329330
final EntryProcessor<K, V, T> entryProcessor,
330331
final Object... arguments) {
331-
final ISpan span = startSpanForKeys("cache.get", keys);
332+
final ISpan span = startSpanForKeys("cache.get", keys, "invokeAll");
332333
if (span == null) {
333334
return delegate.invokeAll(keys, entryProcessor, arguments);
334335
}
@@ -400,7 +401,10 @@ public Iterator<Entry<K, V>> iterator() {
400401

401402
// -- span helpers --
402403

403-
private @Nullable ISpan startSpan(final @NotNull String operation, final @Nullable Object key) {
404+
private @Nullable ISpan startSpan(
405+
final @NotNull String operation,
406+
final @Nullable Object key,
407+
final @NotNull String operationName) {
404408
if (!scopes.getOptions().isEnableCacheTracing()) {
405409
return null;
406410
}
@@ -420,11 +424,14 @@ public Iterator<Entry<K, V>> iterator() {
420424
if (keyString != null) {
421425
span.setData(SpanDataConvention.CACHE_KEY_KEY, Arrays.asList(keyString));
422426
}
427+
span.setData(OPERATION_ATTRIBUTE, operationName);
423428
return span;
424429
}
425430

426431
private @Nullable ISpan startSpanForKeys(
427-
final @NotNull String operation, final @NotNull Set<?> keys) {
432+
final @NotNull String operation,
433+
final @NotNull Set<?> keys,
434+
final @NotNull String operationName) {
428435
if (!scopes.getOptions().isEnableCacheTracing()) {
429436
return null;
430437
}
@@ -443,6 +450,7 @@ public Iterator<Entry<K, V>> iterator() {
443450
span.setData(
444451
SpanDataConvention.CACHE_KEY_KEY,
445452
keys.stream().map(String::valueOf).collect(Collectors.toList()));
453+
span.setData(OPERATION_ATTRIBUTE, operationName);
446454
return span;
447455
}
448456
}

sentry-jcache/src/test/kotlin/io/sentry/jcache/SentryJCacheWrapperTest.kt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ class SentryJCacheWrapperTest {
6464
assertEquals(true, span.getData(SpanDataConvention.CACHE_HIT_KEY))
6565
assertEquals(listOf("myKey"), span.getData(SpanDataConvention.CACHE_KEY_KEY))
6666
assertEquals("auto.cache.jcache", span.spanContext.origin)
67+
assertEquals("get", span.getData("db.operation.name"))
6768
}
6869

6970
@Test
@@ -98,6 +99,7 @@ class SentryJCacheWrapperTest {
9899
assertEquals(true, span.getData(SpanDataConvention.CACHE_HIT_KEY))
99100
val cacheKeys = span.getData(SpanDataConvention.CACHE_KEY_KEY) as List<*>
100101
assertTrue(cacheKeys.containsAll(listOf("k1", "k2")))
102+
assertEquals("getAll", span.getData("db.operation.name"))
101103
}
102104

103105
@Test
@@ -127,6 +129,7 @@ class SentryJCacheWrapperTest {
127129
assertEquals("cache.put", span.operation)
128130
assertEquals(SpanStatus.OK, span.status)
129131
assertEquals(listOf("myKey"), span.getData(SpanDataConvention.CACHE_KEY_KEY))
132+
assertEquals("put", span.getData("db.operation.name"))
130133
}
131134

132135
// -- getAndPut --
@@ -142,6 +145,7 @@ class SentryJCacheWrapperTest {
142145
assertEquals("oldValue", result)
143146
assertEquals(1, tx.spans.size)
144147
assertEquals("cache.put", tx.spans.first().operation)
148+
assertEquals("getAndPut", tx.spans.first().getData("db.operation.name"))
145149
}
146150

147151
// -- putAll --
@@ -161,6 +165,7 @@ class SentryJCacheWrapperTest {
161165
assertEquals("testCache", span.description)
162166
val cacheKeys = span.getData(SpanDataConvention.CACHE_KEY_KEY) as List<*>
163167
assertTrue(cacheKeys.containsAll(listOf("k1", "k2")))
168+
assertEquals("putAll", span.getData("db.operation.name"))
164169
}
165170

166171
// -- putIfAbsent --
@@ -236,6 +241,7 @@ class SentryJCacheWrapperTest {
236241
val span = tx.spans.first()
237242
assertEquals("cache.remove", span.operation)
238243
assertEquals(SpanStatus.OK, span.status)
244+
assertEquals("remove", span.getData("db.operation.name"))
239245
}
240246

241247
// -- remove(K, V) --
@@ -251,6 +257,7 @@ class SentryJCacheWrapperTest {
251257
assertTrue(result)
252258
assertEquals(1, tx.spans.size)
253259
assertEquals("cache.remove", tx.spans.first().operation)
260+
assertEquals("remove", tx.spans.first().getData("db.operation.name"))
254261
}
255262

256263
// -- getAndRemove --
@@ -266,6 +273,7 @@ class SentryJCacheWrapperTest {
266273
assertEquals("value", result)
267274
assertEquals(1, tx.spans.size)
268275
assertEquals("cache.remove", tx.spans.first().operation)
276+
assertEquals("getAndRemove", tx.spans.first().getData("db.operation.name"))
269277
}
270278

271279
// -- removeAll(Set) --
@@ -283,6 +291,7 @@ class SentryJCacheWrapperTest {
283291
val span = tx.spans.first()
284292
assertEquals("cache.remove", span.operation)
285293
assertEquals("testCache", span.description)
294+
assertEquals("removeAll", span.getData("db.operation.name"))
286295
}
287296

288297
// -- removeAll() --
@@ -297,6 +306,7 @@ class SentryJCacheWrapperTest {
297306
verify(delegate).removeAll()
298307
assertEquals(1, tx.spans.size)
299308
assertEquals("cache.flush", tx.spans.first().operation)
309+
assertEquals("removeAll", tx.spans.first().getData("db.operation.name"))
300310
}
301311

302312
// -- clear --
@@ -314,6 +324,7 @@ class SentryJCacheWrapperTest {
314324
assertEquals("cache.flush", span.operation)
315325
assertEquals(SpanStatus.OK, span.status)
316326
assertNull(span.getData(SpanDataConvention.CACHE_KEY_KEY))
327+
assertEquals("clear", span.getData("db.operation.name"))
317328
}
318329

319330
// -- invoke --
@@ -330,6 +341,7 @@ class SentryJCacheWrapperTest {
330341
assertEquals("result", result)
331342
assertEquals(1, tx.spans.size)
332343
assertEquals("cache.get", tx.spans.first().operation)
344+
assertEquals("invoke", tx.spans.first().getData("db.operation.name"))
333345
}
334346

335347
// -- invokeAll --
@@ -348,6 +360,7 @@ class SentryJCacheWrapperTest {
348360
assertEquals(resultMap, result)
349361
assertEquals(1, tx.spans.size)
350362
assertEquals("cache.get", tx.spans.first().operation)
363+
assertEquals("invokeAll", tx.spans.first().getData("db.operation.name"))
351364
}
352365

353366
// -- passthrough operations --

sentry-spring-7/src/main/java/io/sentry/spring7/cache/SentryCacheWrapper.java

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
public final class SentryCacheWrapper implements Cache {
2121

2222
private static final String TRACE_ORIGIN = "auto.cache.spring";
23+
private static final String OPERATION_ATTRIBUTE = "db.operation.name";
2324

2425
private final @NotNull Cache delegate;
2526
private final @NotNull IScopes scopes;
@@ -41,7 +42,7 @@ public SentryCacheWrapper(final @NotNull Cache delegate, final @NotNull IScopes
4142

4243
@Override
4344
public @Nullable ValueWrapper get(final @NotNull Object key) {
44-
final ISpan span = startSpan("cache.get", key);
45+
final ISpan span = startSpan("cache.get", key, "get");
4546
if (span == null) {
4647
return delegate.get(key);
4748
}
@@ -61,7 +62,7 @@ public SentryCacheWrapper(final @NotNull Cache delegate, final @NotNull IScopes
6162

6263
@Override
6364
public @Nullable <T> T get(final @NotNull Object key, final @Nullable Class<T> type) {
64-
final ISpan span = startSpan("cache.get", key);
65+
final ISpan span = startSpan("cache.get", key, "get");
6566
if (span == null) {
6667
return delegate.get(key, type);
6768
}
@@ -81,7 +82,7 @@ public SentryCacheWrapper(final @NotNull Cache delegate, final @NotNull IScopes
8182

8283
@Override
8384
public @Nullable <T> T get(final @NotNull Object key, final @NotNull Callable<T> valueLoader) {
84-
final ISpan span = startSpan("cache.get", key);
85+
final ISpan span = startSpan("cache.get", key, "get");
8586
if (span == null) {
8687
return delegate.get(key, valueLoader);
8788
}
@@ -108,7 +109,7 @@ public SentryCacheWrapper(final @NotNull Cache delegate, final @NotNull IScopes
108109

109110
@Override
110111
public @Nullable CompletableFuture<?> retrieve(final @NotNull Object key) {
111-
final ISpan span = startSpan("cache.get", key);
112+
final ISpan span = startSpan("cache.get", key, "retrieve");
112113
if (span == null) {
113114
return delegate.retrieve(key);
114115
}
@@ -143,7 +144,7 @@ public SentryCacheWrapper(final @NotNull Cache delegate, final @NotNull IScopes
143144
@Override
144145
public <T> CompletableFuture<T> retrieve(
145146
final @NotNull Object key, final @NotNull Supplier<CompletableFuture<T>> valueLoader) {
146-
final ISpan span = startSpan("cache.get", key);
147+
final ISpan span = startSpan("cache.get", key, "retrieve");
147148
if (span == null) {
148149
return delegate.retrieve(key, valueLoader);
149150
}
@@ -178,7 +179,7 @@ public <T> CompletableFuture<T> retrieve(
178179

179180
@Override
180181
public void put(final @NotNull Object key, final @Nullable Object value) {
181-
final ISpan span = startSpan("cache.put", key);
182+
final ISpan span = startSpan("cache.put", key, "put");
182183
if (span == null) {
183184
delegate.put(key, value);
184185
return;
@@ -207,7 +208,7 @@ public void put(final @NotNull Object key, final @Nullable Object value) {
207208

208209
@Override
209210
public void evict(final @NotNull Object key) {
210-
final ISpan span = startSpan("cache.remove", key);
211+
final ISpan span = startSpan("cache.remove", key, "evict");
211212
if (span == null) {
212213
delegate.evict(key);
213214
return;
@@ -226,7 +227,7 @@ public void evict(final @NotNull Object key) {
226227

227228
@Override
228229
public boolean evictIfPresent(final @NotNull Object key) {
229-
final ISpan span = startSpan("cache.remove", key);
230+
final ISpan span = startSpan("cache.remove", key, "evictIfPresent");
230231
if (span == null) {
231232
return delegate.evictIfPresent(key);
232233
}
@@ -245,7 +246,7 @@ public boolean evictIfPresent(final @NotNull Object key) {
245246

246247
@Override
247248
public void clear() {
248-
final ISpan span = startSpan("cache.flush", null);
249+
final ISpan span = startSpan("cache.flush", null, "clear");
249250
if (span == null) {
250251
delegate.clear();
251252
return;
@@ -264,7 +265,7 @@ public void clear() {
264265

265266
@Override
266267
public boolean invalidate() {
267-
final ISpan span = startSpan("cache.flush", null);
268+
final ISpan span = startSpan("cache.flush", null, "invalidate");
268269
if (span == null) {
269270
return delegate.invalidate();
270271
}
@@ -281,7 +282,10 @@ public boolean invalidate() {
281282
}
282283
}
283284

284-
private @Nullable ISpan startSpan(final @NotNull String operation, final @Nullable Object key) {
285+
private @Nullable ISpan startSpan(
286+
final @NotNull String operation,
287+
final @Nullable Object key,
288+
final @NotNull String operationName) {
285289
if (!scopes.getOptions().isEnableCacheTracing()) {
286290
return null;
287291
}
@@ -301,6 +305,7 @@ public boolean invalidate() {
301305
if (keyString != null) {
302306
span.setData(SpanDataConvention.CACHE_KEY_KEY, Arrays.asList(keyString));
303307
}
308+
span.setData(OPERATION_ATTRIBUTE, operationName);
304309
return span;
305310
}
306311
}

0 commit comments

Comments
 (0)