From 8a3d1e24e43c627c64cbebf9e381303c47e9586b Mon Sep 17 00:00:00 2001 From: Martin Sonnberger Date: Mon, 27 Jul 2026 15:42:55 +0200 Subject: [PATCH 1/5] feat(nuxt, nitro)!: Use convention cache ops for storage spans Collapse the per-method ops onto `cache.get` / `cache.put` / `cache.remove`. The exact unstorage method is already preserved in `db.operation.name`. Ref: JS-3105 Co-Authored-By: Claude Opus 5 (1M context) --- .../nitro-3/tests/cache.test.ts | 24 ++++++------ .../nitro-3/tests/storage-aliases.test.ts | 24 ++++++------ .../nitro-3/tests/storage.test.ts | 38 ++++++++++--------- .../nuxt-3/tests/cache.test.ts | 24 ++++++------ .../nuxt-3/tests/storage-aliases.test.ts | 24 ++++++------ .../nuxt-3/tests/storage.test.ts | 38 ++++++++++--------- .../nuxt-4/tests/cache.test.ts | 24 ++++++------ .../nuxt-4/tests/storage-aliases.test.ts | 24 ++++++------ .../nuxt-4/tests/storage.test.ts | 38 ++++++++++--------- .../nuxt-5/tests/cache.test.ts | 24 ++++++------ .../nuxt-5/tests/storage-aliases.test.ts | 24 ++++++------ .../nuxt-5/tests/storage.test.ts | 38 ++++++++++--------- packages/nitro/package.json | 1 + .../src/runtime/hooks/captureStorageEvents.ts | 29 +++++++++++--- packages/nuxt/package.json | 1 + .../src/runtime/utils/instrumentStorage.ts | 32 ++++++++++++---- 16 files changed, 226 insertions(+), 181 deletions(-) diff --git a/dev-packages/e2e-tests/test-applications/nitro-3/tests/cache.test.ts b/dev-packages/e2e-tests/test-applications/nitro-3/tests/cache.test.ts index feda6b3ea3fe..53b7c0118d37 100644 --- a/dev-packages/e2e-tests/test-applications/nitro-3/tests/cache.test.ts +++ b/dev-packages/e2e-tests/test-applications/nitro-3/tests/cache.test.ts @@ -18,8 +18,10 @@ test.describe('Cache Instrumentation', () => { const transaction = await transactionPromise; - const findSpansByOp = (op: string) => { - return transaction.spans?.filter(span => span.data?.[SEMANTIC_ATTRIBUTE_SENTRY_OP] === op) || []; + // Several unstorage methods share one convention op (e.g. hasItem/getItem/getKeys are all + // `cache.get`), so spans are located by `db.operation.name`, which stays unique per method. + const findSpansByMethod = (method: string) => { + return transaction.spans?.filter(span => span.data?.['db.operation.name'] === method) || []; }; const allCacheSpans = transaction.spans?.filter( @@ -28,7 +30,7 @@ test.describe('Cache Instrumentation', () => { expect(allCacheSpans?.length).toBeGreaterThan(0); // getItem spans for cachedFunction - should have both cache miss and cache hit - const getItemSpans = findSpansByOp('cache.get_item'); + const getItemSpans = findSpansByMethod('getItem'); expect(getItemSpans.length).toBeGreaterThan(0); // Find cache miss (first call to getCachedUser('123')) @@ -40,7 +42,7 @@ test.describe('Cache Instrumentation', () => { ); expect(cacheMissSpan).toBeDefined(); expect(cacheMissSpan?.data).toMatchObject({ - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.get_item', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.get', [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.cache.nitro', [SEMANTIC_ATTRIBUTE_CACHE_HIT]: false, 'db.operation.name': 'getItem', @@ -55,14 +57,14 @@ test.describe('Cache Instrumentation', () => { ); expect(cacheHitSpan).toBeDefined(); expect(cacheHitSpan?.data).toMatchObject({ - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.get_item', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.get', [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.cache.nitro', [SEMANTIC_ATTRIBUTE_CACHE_HIT]: true, 'db.operation.name': 'getItem', }); // setItem spans for cachedFunction - when cache miss occurs, value is set - const setItemSpans = findSpansByOp('cache.set_item'); + const setItemSpans = findSpansByMethod('setItem'); expect(setItemSpans.length).toBeGreaterThan(0); const cacheSetSpan = setItemSpans.find( @@ -72,7 +74,7 @@ test.describe('Cache Instrumentation', () => { ); expect(cacheSetSpan).toBeDefined(); expect(cacheSetSpan?.data).toMatchObject({ - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.set_item', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.put', [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.cache.nitro', 'db.operation.name': 'setItem', }); @@ -120,12 +122,8 @@ test.describe('Cache Instrumentation', () => { ); expect(allCacheSpans?.length).toBeGreaterThan(0); - const allGetItemSpans = allCacheSpans?.filter( - span => span.data?.[SEMANTIC_ATTRIBUTE_SENTRY_OP] === 'cache.get_item', - ); - const allSetItemSpans = allCacheSpans?.filter( - span => span.data?.[SEMANTIC_ATTRIBUTE_SENTRY_OP] === 'cache.set_item', - ); + const allGetItemSpans = allCacheSpans?.filter(span => span.data?.[SEMANTIC_ATTRIBUTE_SENTRY_OP] === 'cache.get'); + const allSetItemSpans = allCacheSpans?.filter(span => span.data?.[SEMANTIC_ATTRIBUTE_SENTRY_OP] === 'cache.put'); expect(allGetItemSpans?.length).toBeGreaterThan(0); expect(allSetItemSpans?.length).toBeGreaterThan(0); diff --git a/dev-packages/e2e-tests/test-applications/nitro-3/tests/storage-aliases.test.ts b/dev-packages/e2e-tests/test-applications/nitro-3/tests/storage-aliases.test.ts index 173e6c0b82d5..746bf1c1294f 100644 --- a/dev-packages/e2e-tests/test-applications/nitro-3/tests/storage-aliases.test.ts +++ b/dev-packages/e2e-tests/test-applications/nitro-3/tests/storage-aliases.test.ts @@ -18,17 +18,19 @@ test.describe('Storage Instrumentation - Aliases', () => { const transaction = await transactionPromise; // Helper to find spans by operation - const findSpansByOp = (op: string) => { - return transaction.spans?.filter(span => span.data?.[SEMANTIC_ATTRIBUTE_SENTRY_OP] === op) || []; + // Several unstorage methods share one convention op (e.g. hasItem/getItem/getKeys are all + // `cache.get`), so spans are located by `db.operation.name`, which stays unique per method. + const findSpansByMethod = (method: string) => { + return transaction.spans?.filter(span => span.data?.['db.operation.name'] === method) || []; }; // Test set (alias for setItem) - const setSpans = findSpansByOp('cache.set_item'); + const setSpans = findSpansByMethod('setItem'); expect(setSpans.length).toBeGreaterThanOrEqual(1); const setSpan = setSpans.find(span => span.data?.[SEMANTIC_ATTRIBUTE_CACHE_KEY] === prefixKey('alias:user')); expect(setSpan).toBeDefined(); expect(setSpan?.data).toMatchObject({ - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.set_item', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.put', [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.cache.nitro', [SEMANTIC_ATTRIBUTE_CACHE_KEY]: prefixKey('alias:user'), 'db.operation.name': 'setItem', @@ -37,12 +39,12 @@ test.describe('Storage Instrumentation - Aliases', () => { expect(setSpan?.description).toBe(prefixKey('alias:user')); // Test get (alias for getItem) - const getSpans = findSpansByOp('cache.get_item'); + const getSpans = findSpansByMethod('getItem'); expect(getSpans.length).toBeGreaterThanOrEqual(1); const getSpan = getSpans.find(span => span.data?.[SEMANTIC_ATTRIBUTE_CACHE_KEY] === prefixKey('alias:user')); expect(getSpan).toBeDefined(); expect(getSpan?.data).toMatchObject({ - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.get_item', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.get', [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.cache.nitro', [SEMANTIC_ATTRIBUTE_CACHE_KEY]: prefixKey('alias:user'), [SEMANTIC_ATTRIBUTE_CACHE_HIT]: true, @@ -52,12 +54,12 @@ test.describe('Storage Instrumentation - Aliases', () => { expect(getSpan?.description).toBe(prefixKey('alias:user')); // Test has (alias for hasItem) - const hasSpans = findSpansByOp('cache.has_item'); + const hasSpans = findSpansByMethod('hasItem'); expect(hasSpans.length).toBeGreaterThanOrEqual(1); const hasSpan = hasSpans.find(span => span.data?.[SEMANTIC_ATTRIBUTE_CACHE_KEY] === prefixKey('alias:user')); expect(hasSpan).toBeDefined(); expect(hasSpan?.data).toMatchObject({ - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.has_item', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.get', [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.cache.nitro', [SEMANTIC_ATTRIBUTE_CACHE_KEY]: prefixKey('alias:user'), [SEMANTIC_ATTRIBUTE_CACHE_HIT]: true, @@ -66,13 +68,13 @@ test.describe('Storage Instrumentation - Aliases', () => { }); // Test del and remove (both aliases for removeItem) - const removeSpans = findSpansByOp('cache.remove_item'); + const removeSpans = findSpansByMethod('removeItem'); expect(removeSpans.length).toBeGreaterThanOrEqual(2); const delSpan = removeSpans.find(span => span.data?.[SEMANTIC_ATTRIBUTE_CACHE_KEY] === prefixKey('alias:temp1')); expect(delSpan).toBeDefined(); expect(delSpan?.data).toMatchObject({ - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.remove_item', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.remove', [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.cache.nitro', [SEMANTIC_ATTRIBUTE_CACHE_KEY]: prefixKey('alias:temp1'), 'db.operation.name': 'removeItem', @@ -83,7 +85,7 @@ test.describe('Storage Instrumentation - Aliases', () => { const removeSpan = removeSpans.find(span => span.data?.[SEMANTIC_ATTRIBUTE_CACHE_KEY] === prefixKey('alias:temp2')); expect(removeSpan).toBeDefined(); expect(removeSpan?.data).toMatchObject({ - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.remove_item', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.remove', [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.cache.nitro', [SEMANTIC_ATTRIBUTE_CACHE_KEY]: prefixKey('alias:temp2'), 'db.operation.name': 'removeItem', diff --git a/dev-packages/e2e-tests/test-applications/nitro-3/tests/storage.test.ts b/dev-packages/e2e-tests/test-applications/nitro-3/tests/storage.test.ts index e4a959219c10..b7f01d8e87ce 100644 --- a/dev-packages/e2e-tests/test-applications/nitro-3/tests/storage.test.ts +++ b/dev-packages/e2e-tests/test-applications/nitro-3/tests/storage.test.ts @@ -18,17 +18,19 @@ test.describe('Storage Instrumentation', () => { const transaction = await transactionPromise; // Helper to find spans by operation - const findSpansByOp = (op: string) => { - return transaction.spans?.filter(span => span.data?.[SEMANTIC_ATTRIBUTE_SENTRY_OP] === op) || []; + // Several unstorage methods share one convention op (e.g. hasItem/getItem/getKeys are all + // `cache.get`), so spans are located by `db.operation.name`, which stays unique per method. + const findSpansByMethod = (method: string) => { + return transaction.spans?.filter(span => span.data?.['db.operation.name'] === method) || []; }; // Test setItem spans - const setItemSpans = findSpansByOp('cache.set_item'); + const setItemSpans = findSpansByMethod('setItem'); expect(setItemSpans.length).toBeGreaterThanOrEqual(1); const setItemSpan = setItemSpans.find(span => span.data?.[SEMANTIC_ATTRIBUTE_CACHE_KEY] === prefixKey('user:123')); expect(setItemSpan).toBeDefined(); expect(setItemSpan?.data).toMatchObject({ - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.set_item', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.put', [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.cache.nitro', [SEMANTIC_ATTRIBUTE_CACHE_KEY]: prefixKey('user:123'), 'db.operation.name': 'setItem', @@ -37,14 +39,14 @@ test.describe('Storage Instrumentation', () => { expect(setItemSpan?.description).toBe(prefixKey('user:123')); // Test setItemRaw spans - const setItemRawSpans = findSpansByOp('cache.set_item_raw'); + const setItemRawSpans = findSpansByMethod('setItemRaw'); expect(setItemRawSpans.length).toBeGreaterThanOrEqual(1); const setItemRawSpan = setItemRawSpans.find( span => span.data?.[SEMANTIC_ATTRIBUTE_CACHE_KEY] === prefixKey('raw:data'), ); expect(setItemRawSpan).toBeDefined(); expect(setItemRawSpan?.data).toMatchObject({ - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.set_item_raw', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.put', [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.cache.nitro', [SEMANTIC_ATTRIBUTE_CACHE_KEY]: prefixKey('raw:data'), 'db.operation.name': 'setItemRaw', @@ -52,12 +54,12 @@ test.describe('Storage Instrumentation', () => { }); // Test hasItem spans - should have cache hit attribute - const hasItemSpans = findSpansByOp('cache.has_item'); + const hasItemSpans = findSpansByMethod('hasItem'); expect(hasItemSpans.length).toBeGreaterThanOrEqual(1); const hasItemSpan = hasItemSpans.find(span => span.data?.[SEMANTIC_ATTRIBUTE_CACHE_KEY] === prefixKey('user:123')); expect(hasItemSpan).toBeDefined(); expect(hasItemSpan?.data).toMatchObject({ - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.has_item', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.get', [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.cache.nitro', [SEMANTIC_ATTRIBUTE_CACHE_KEY]: prefixKey('user:123'), [SEMANTIC_ATTRIBUTE_CACHE_HIT]: true, @@ -66,12 +68,12 @@ test.describe('Storage Instrumentation', () => { }); // Test getItem spans - should have cache hit attribute - const getItemSpans = findSpansByOp('cache.get_item'); + const getItemSpans = findSpansByMethod('getItem'); expect(getItemSpans.length).toBeGreaterThanOrEqual(1); const getItemSpan = getItemSpans.find(span => span.data?.[SEMANTIC_ATTRIBUTE_CACHE_KEY] === prefixKey('user:123')); expect(getItemSpan).toBeDefined(); expect(getItemSpan?.data).toMatchObject({ - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.get_item', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.get', [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.cache.nitro', [SEMANTIC_ATTRIBUTE_CACHE_KEY]: prefixKey('user:123'), [SEMANTIC_ATTRIBUTE_CACHE_HIT]: true, @@ -81,14 +83,14 @@ test.describe('Storage Instrumentation', () => { expect(getItemSpan?.description).toBe(prefixKey('user:123')); // Test getItemRaw spans - should have cache hit attribute - const getItemRawSpans = findSpansByOp('cache.get_item_raw'); + const getItemRawSpans = findSpansByMethod('getItemRaw'); expect(getItemRawSpans.length).toBeGreaterThanOrEqual(1); const getItemRawSpan = getItemRawSpans.find( span => span.data?.[SEMANTIC_ATTRIBUTE_CACHE_KEY] === prefixKey('raw:data'), ); expect(getItemRawSpan).toBeDefined(); expect(getItemRawSpan?.data).toMatchObject({ - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.get_item_raw', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.get', [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.cache.nitro', [SEMANTIC_ATTRIBUTE_CACHE_KEY]: prefixKey('raw:data'), [SEMANTIC_ATTRIBUTE_CACHE_HIT]: true, @@ -97,24 +99,24 @@ test.describe('Storage Instrumentation', () => { }); // Test getKeys spans - const getKeysSpans = findSpansByOp('cache.get_keys'); + const getKeysSpans = findSpansByMethod('getKeys'); expect(getKeysSpans.length).toBeGreaterThanOrEqual(1); expect(getKeysSpans[0]?.data).toMatchObject({ - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.get_keys', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.get', [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.cache.nitro', 'db.operation.name': 'getKeys', 'db.system.name': expect.any(String), }); // Test removeItem spans - const removeItemSpans = findSpansByOp('cache.remove_item'); + const removeItemSpans = findSpansByMethod('removeItem'); expect(removeItemSpans.length).toBeGreaterThanOrEqual(1); const removeItemSpan = removeItemSpans.find( span => span.data?.[SEMANTIC_ATTRIBUTE_CACHE_KEY] === prefixKey('batch:1'), ); expect(removeItemSpan).toBeDefined(); expect(removeItemSpan?.data).toMatchObject({ - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.remove_item', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.remove', [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.cache.nitro', [SEMANTIC_ATTRIBUTE_CACHE_KEY]: prefixKey('batch:1'), 'db.operation.name': 'removeItem', @@ -122,10 +124,10 @@ test.describe('Storage Instrumentation', () => { }); // Test clear spans - const clearSpans = findSpansByOp('cache.clear'); + const clearSpans = findSpansByMethod('clear'); expect(clearSpans.length).toBeGreaterThanOrEqual(1); expect(clearSpans[0]?.data).toMatchObject({ - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.clear', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.remove', [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.cache.nitro', 'db.operation.name': 'clear', 'db.system.name': expect.any(String), diff --git a/dev-packages/e2e-tests/test-applications/nuxt-3/tests/cache.test.ts b/dev-packages/e2e-tests/test-applications/nuxt-3/tests/cache.test.ts index a1697136ef01..af34ac5d306c 100644 --- a/dev-packages/e2e-tests/test-applications/nuxt-3/tests/cache.test.ts +++ b/dev-packages/e2e-tests/test-applications/nuxt-3/tests/cache.test.ts @@ -19,8 +19,10 @@ test.describe('Cache Instrumentation', () => { const transaction = await transactionPromise; // Helper to find spans by operation - const findSpansByOp = (op: string) => { - return transaction.spans?.filter(span => span.data?.[SEMANTIC_ATTRIBUTE_SENTRY_OP] === op) || []; + // Several unstorage methods share one convention op (e.g. hasItem/getItem/getKeys are all + // `cache.get`), so spans are located by `db.operation.name`, which stays unique per method. + const findSpansByMethod = (method: string) => { + return transaction.spans?.filter(span => span.data?.['db.operation.name'] === method) || []; }; // Test that we have cache operations from cachedFunction and cachedEventHandler @@ -30,7 +32,7 @@ test.describe('Cache Instrumentation', () => { expect(allCacheSpans?.length).toBeGreaterThan(0); // Test getItem spans for cachedFunction - should have both cache miss and cache hit - const getItemSpans = findSpansByOp('cache.get_item'); + const getItemSpans = findSpansByMethod('getItem'); expect(getItemSpans.length).toBeGreaterThan(0); // Find cache miss (first call to getCachedUser('123')) @@ -42,7 +44,7 @@ test.describe('Cache Instrumentation', () => { ); if (cacheMissSpan) { expect(cacheMissSpan.data).toMatchObject({ - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.get_item', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.get', [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.cache.nuxt', [SEMANTIC_ATTRIBUTE_CACHE_HIT]: false, 'db.operation.name': 'getItem', @@ -59,7 +61,7 @@ test.describe('Cache Instrumentation', () => { ); if (cacheHitSpan) { expect(cacheHitSpan.data).toMatchObject({ - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.get_item', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.get', [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.cache.nuxt', [SEMANTIC_ATTRIBUTE_CACHE_HIT]: true, 'db.operation.name': 'getItem', @@ -68,7 +70,7 @@ test.describe('Cache Instrumentation', () => { } // Test setItem spans for cachedFunction - when cache miss occurs, value is set - const setItemSpans = findSpansByOp('cache.set_item'); + const setItemSpans = findSpansByMethod('setItem'); expect(setItemSpans.length).toBeGreaterThan(0); const cacheSetSpan = setItemSpans.find( @@ -78,7 +80,7 @@ test.describe('Cache Instrumentation', () => { ); if (cacheSetSpan) { expect(cacheSetSpan.data).toMatchObject({ - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.set_item', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.put', [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.cache.nuxt', 'db.operation.name': 'setItem', 'db.collection.name': expect.stringMatching(/^(cache)?$/), @@ -133,14 +135,10 @@ test.describe('Cache Instrumentation', () => { expect(allCacheSpans?.length).toBeGreaterThan(0); // Get all getItem operations - const allGetItemSpans = allCacheSpans?.filter( - span => span.data?.[SEMANTIC_ATTRIBUTE_SENTRY_OP] === 'cache.get_item', - ); + const allGetItemSpans = allCacheSpans?.filter(span => span.data?.[SEMANTIC_ATTRIBUTE_SENTRY_OP] === 'cache.get'); // Get all setItem operations - const allSetItemSpans = allCacheSpans?.filter( - span => span.data?.[SEMANTIC_ATTRIBUTE_SENTRY_OP] === 'cache.set_item', - ); + const allSetItemSpans = allCacheSpans?.filter(span => span.data?.[SEMANTIC_ATTRIBUTE_SENTRY_OP] === 'cache.put'); // We should have both get and set operations expect(allGetItemSpans?.length).toBeGreaterThan(0); diff --git a/dev-packages/e2e-tests/test-applications/nuxt-3/tests/storage-aliases.test.ts b/dev-packages/e2e-tests/test-applications/nuxt-3/tests/storage-aliases.test.ts index a721df04b40c..2e6241e811f5 100644 --- a/dev-packages/e2e-tests/test-applications/nuxt-3/tests/storage-aliases.test.ts +++ b/dev-packages/e2e-tests/test-applications/nuxt-3/tests/storage-aliases.test.ts @@ -18,17 +18,19 @@ test.describe('Storage Instrumentation - Aliases', () => { const transaction = await transactionPromise; // Helper to find spans by operation - const findSpansByOp = (op: string) => { - return transaction.spans?.filter(span => span.data?.[SEMANTIC_ATTRIBUTE_SENTRY_OP] === op) || []; + // Several unstorage methods share one convention op (e.g. hasItem/getItem/getKeys are all + // `cache.get`), so spans are located by `db.operation.name`, which stays unique per method. + const findSpansByMethod = (method: string) => { + return transaction.spans?.filter(span => span.data?.['db.operation.name'] === method) || []; }; // Test set (alias for setItem) - const setSpans = findSpansByOp('cache.set_item'); + const setSpans = findSpansByMethod('setItem'); expect(setSpans.length).toBeGreaterThanOrEqual(1); const setSpan = setSpans.find(span => span.data?.[SEMANTIC_ATTRIBUTE_CACHE_KEY] === prefixKey('alias:user')); expect(setSpan).toBeDefined(); expect(setSpan?.data).toMatchObject({ - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.set_item', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.put', [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.cache.nuxt', [SEMANTIC_ATTRIBUTE_CACHE_KEY]: prefixKey('alias:user'), 'db.operation.name': 'setItem', @@ -38,12 +40,12 @@ test.describe('Storage Instrumentation - Aliases', () => { expect(setSpan?.description).toBe(prefixKey('alias:user')); // Test get (alias for getItem) - const getSpans = findSpansByOp('cache.get_item'); + const getSpans = findSpansByMethod('getItem'); expect(getSpans.length).toBeGreaterThanOrEqual(1); const getSpan = getSpans.find(span => span.data?.[SEMANTIC_ATTRIBUTE_CACHE_KEY] === prefixKey('alias:user')); expect(getSpan).toBeDefined(); expect(getSpan?.data).toMatchObject({ - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.get_item', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.get', [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.cache.nuxt', [SEMANTIC_ATTRIBUTE_CACHE_KEY]: prefixKey('alias:user'), [SEMANTIC_ATTRIBUTE_CACHE_HIT]: true, @@ -54,12 +56,12 @@ test.describe('Storage Instrumentation - Aliases', () => { expect(getSpan?.description).toBe(prefixKey('alias:user')); // Test has (alias for hasItem) - const hasSpans = findSpansByOp('cache.has_item'); + const hasSpans = findSpansByMethod('hasItem'); expect(hasSpans.length).toBeGreaterThanOrEqual(1); const hasSpan = hasSpans.find(span => span.data?.[SEMANTIC_ATTRIBUTE_CACHE_KEY] === prefixKey('alias:user')); expect(hasSpan).toBeDefined(); expect(hasSpan?.data).toMatchObject({ - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.has_item', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.get', [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.cache.nuxt', [SEMANTIC_ATTRIBUTE_CACHE_KEY]: prefixKey('alias:user'), [SEMANTIC_ATTRIBUTE_CACHE_HIT]: true, @@ -69,13 +71,13 @@ test.describe('Storage Instrumentation - Aliases', () => { }); // Test del and remove (both aliases for removeItem) - const removeSpans = findSpansByOp('cache.remove_item'); + const removeSpans = findSpansByMethod('removeItem'); expect(removeSpans.length).toBeGreaterThanOrEqual(2); // Should have both del and remove calls const delSpan = removeSpans.find(span => span.data?.[SEMANTIC_ATTRIBUTE_CACHE_KEY] === prefixKey('alias:temp1')); expect(delSpan).toBeDefined(); expect(delSpan?.data).toMatchObject({ - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.remove_item', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.remove', [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.cache.nuxt', [SEMANTIC_ATTRIBUTE_CACHE_KEY]: prefixKey('alias:temp1'), 'db.operation.name': 'removeItem', @@ -87,7 +89,7 @@ test.describe('Storage Instrumentation - Aliases', () => { const removeSpan = removeSpans.find(span => span.data?.[SEMANTIC_ATTRIBUTE_CACHE_KEY] === prefixKey('alias:temp2')); expect(removeSpan).toBeDefined(); expect(removeSpan?.data).toMatchObject({ - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.remove_item', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.remove', [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.cache.nuxt', [SEMANTIC_ATTRIBUTE_CACHE_KEY]: prefixKey('alias:temp2'), 'db.operation.name': 'removeItem', diff --git a/dev-packages/e2e-tests/test-applications/nuxt-3/tests/storage.test.ts b/dev-packages/e2e-tests/test-applications/nuxt-3/tests/storage.test.ts index 2c451be51135..aaaed1b315a9 100644 --- a/dev-packages/e2e-tests/test-applications/nuxt-3/tests/storage.test.ts +++ b/dev-packages/e2e-tests/test-applications/nuxt-3/tests/storage.test.ts @@ -18,17 +18,19 @@ test.describe('Storage Instrumentation', () => { const transaction = await transactionPromise; // Helper to find spans by operation - const findSpansByOp = (op: string) => { - return transaction.spans?.filter(span => span.data?.[SEMANTIC_ATTRIBUTE_SENTRY_OP] === op) || []; + // Several unstorage methods share one convention op (e.g. hasItem/getItem/getKeys are all + // `cache.get`), so spans are located by `db.operation.name`, which stays unique per method. + const findSpansByMethod = (method: string) => { + return transaction.spans?.filter(span => span.data?.['db.operation.name'] === method) || []; }; // Test setItem spans - const setItemSpans = findSpansByOp('cache.set_item'); + const setItemSpans = findSpansByMethod('setItem'); expect(setItemSpans.length).toBeGreaterThanOrEqual(1); const setItemSpan = setItemSpans.find(span => span.data?.[SEMANTIC_ATTRIBUTE_CACHE_KEY] === prefixKey('user:123')); expect(setItemSpan).toBeDefined(); expect(setItemSpan?.data).toMatchObject({ - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.set_item', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.put', [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.cache.nuxt', [SEMANTIC_ATTRIBUTE_CACHE_KEY]: prefixKey('user:123'), 'db.operation.name': 'setItem', @@ -39,7 +41,7 @@ test.describe('Storage Instrumentation', () => { expect(setItemSpan?.description).toBe(prefixKey('user:123')); // Test setItemRaw spans - const setItemRawSpans = findSpansByOp('cache.set_item_raw'); + const setItemRawSpans = findSpansByMethod('setItemRaw'); expect(setItemRawSpans.length).toBeGreaterThanOrEqual(1); const setItemRawSpan = setItemRawSpans.find( @@ -48,7 +50,7 @@ test.describe('Storage Instrumentation', () => { expect(setItemRawSpan).toBeDefined(); expect(setItemRawSpan?.data).toMatchObject({ - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.set_item_raw', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.put', [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.cache.nuxt', [SEMANTIC_ATTRIBUTE_CACHE_KEY]: prefixKey('raw:data'), 'db.operation.name': 'setItemRaw', @@ -57,12 +59,12 @@ test.describe('Storage Instrumentation', () => { }); // Test hasItem spans - should have cache hit attribute - const hasItemSpans = findSpansByOp('cache.has_item'); + const hasItemSpans = findSpansByMethod('hasItem'); expect(hasItemSpans.length).toBeGreaterThanOrEqual(1); const hasItemSpan = hasItemSpans.find(span => span.data?.[SEMANTIC_ATTRIBUTE_CACHE_KEY] === prefixKey('user:123')); expect(hasItemSpan).toBeDefined(); expect(hasItemSpan?.data).toMatchObject({ - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.has_item', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.get', [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.cache.nuxt', [SEMANTIC_ATTRIBUTE_CACHE_KEY]: prefixKey('user:123'), [SEMANTIC_ATTRIBUTE_CACHE_HIT]: true, @@ -72,12 +74,12 @@ test.describe('Storage Instrumentation', () => { }); // Test getItem spans - should have cache hit attribute - const getItemSpans = findSpansByOp('cache.get_item'); + const getItemSpans = findSpansByMethod('getItem'); expect(getItemSpans.length).toBeGreaterThanOrEqual(1); const getItemSpan = getItemSpans.find(span => span.data?.[SEMANTIC_ATTRIBUTE_CACHE_KEY] === prefixKey('user:123')); expect(getItemSpan).toBeDefined(); expect(getItemSpan?.data).toMatchObject({ - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.get_item', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.get', [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.cache.nuxt', [SEMANTIC_ATTRIBUTE_CACHE_KEY]: prefixKey('user:123'), [SEMANTIC_ATTRIBUTE_CACHE_HIT]: true, @@ -88,14 +90,14 @@ test.describe('Storage Instrumentation', () => { expect(getItemSpan?.description).toBe(prefixKey('user:123')); // Test getItemRaw spans - should have cache hit attribute - const getItemRawSpans = findSpansByOp('cache.get_item_raw'); + const getItemRawSpans = findSpansByMethod('getItemRaw'); expect(getItemRawSpans.length).toBeGreaterThanOrEqual(1); const getItemRawSpan = getItemRawSpans.find( span => span.data?.[SEMANTIC_ATTRIBUTE_CACHE_KEY] === prefixKey('raw:data'), ); expect(getItemRawSpan).toBeDefined(); expect(getItemRawSpan?.data).toMatchObject({ - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.get_item_raw', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.get', [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.cache.nuxt', [SEMANTIC_ATTRIBUTE_CACHE_KEY]: prefixKey('raw:data'), [SEMANTIC_ATTRIBUTE_CACHE_HIT]: true, @@ -105,10 +107,10 @@ test.describe('Storage Instrumentation', () => { }); // Test getKeys spans - const getKeysSpans = findSpansByOp('cache.get_keys'); + const getKeysSpans = findSpansByMethod('getKeys'); expect(getKeysSpans.length).toBeGreaterThanOrEqual(1); expect(getKeysSpans[0]?.data).toMatchObject({ - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.get_keys', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.get', [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.cache.nuxt', 'db.operation.name': 'getKeys', 'db.collection.name': 'test-storage', @@ -116,14 +118,14 @@ test.describe('Storage Instrumentation', () => { }); // Test removeItem spans - const removeItemSpans = findSpansByOp('cache.remove_item'); + const removeItemSpans = findSpansByMethod('removeItem'); expect(removeItemSpans.length).toBeGreaterThanOrEqual(1); const removeItemSpan = removeItemSpans.find( span => span.data?.[SEMANTIC_ATTRIBUTE_CACHE_KEY] === prefixKey('batch:1'), ); expect(removeItemSpan).toBeDefined(); expect(removeItemSpan?.data).toMatchObject({ - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.remove_item', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.remove', [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.cache.nuxt', [SEMANTIC_ATTRIBUTE_CACHE_KEY]: prefixKey('batch:1'), 'db.operation.name': 'removeItem', @@ -132,10 +134,10 @@ test.describe('Storage Instrumentation', () => { }); // Test clear spans - const clearSpans = findSpansByOp('cache.clear'); + const clearSpans = findSpansByMethod('clear'); expect(clearSpans.length).toBeGreaterThanOrEqual(1); expect(clearSpans[0]?.data).toMatchObject({ - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.clear', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.remove', [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.cache.nuxt', 'db.operation.name': 'clear', 'db.collection.name': 'test-storage', diff --git a/dev-packages/e2e-tests/test-applications/nuxt-4/tests/cache.test.ts b/dev-packages/e2e-tests/test-applications/nuxt-4/tests/cache.test.ts index 1295de002145..5572a57b6f9c 100644 --- a/dev-packages/e2e-tests/test-applications/nuxt-4/tests/cache.test.ts +++ b/dev-packages/e2e-tests/test-applications/nuxt-4/tests/cache.test.ts @@ -19,8 +19,10 @@ test.describe('Cache Instrumentation', () => { const transaction = await transactionPromise; // Helper to find spans by operation - const findSpansByOp = (op: string) => { - return transaction.spans?.filter(span => span.data?.[SEMANTIC_ATTRIBUTE_SENTRY_OP] === op) || []; + // Several unstorage methods share one convention op (e.g. hasItem/getItem/getKeys are all + // `cache.get`), so spans are located by `db.operation.name`, which stays unique per method. + const findSpansByMethod = (method: string) => { + return transaction.spans?.filter(span => span.data?.['db.operation.name'] === method) || []; }; // Test that we have cache operations from cachedFunction and cachedEventHandler @@ -30,7 +32,7 @@ test.describe('Cache Instrumentation', () => { expect(allCacheSpans?.length).toBeGreaterThan(0); // Test getItem spans for cachedFunction - should have both cache miss and cache hit - const getItemSpans = findSpansByOp('cache.get_item'); + const getItemSpans = findSpansByMethod('getItem'); expect(getItemSpans.length).toBeGreaterThan(0); // Find cache miss (first call to getCachedUser('123')) @@ -42,7 +44,7 @@ test.describe('Cache Instrumentation', () => { ); if (cacheMissSpan) { expect(cacheMissSpan.data).toMatchObject({ - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.get_item', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.get', [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.cache.nuxt', [SEMANTIC_ATTRIBUTE_CACHE_HIT]: false, 'db.operation.name': 'getItem', @@ -59,7 +61,7 @@ test.describe('Cache Instrumentation', () => { ); if (cacheHitSpan) { expect(cacheHitSpan.data).toMatchObject({ - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.get_item', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.get', [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.cache.nuxt', [SEMANTIC_ATTRIBUTE_CACHE_HIT]: true, 'db.operation.name': 'getItem', @@ -68,7 +70,7 @@ test.describe('Cache Instrumentation', () => { } // Test setItem spans for cachedFunction - when cache miss occurs, value is set - const setItemSpans = findSpansByOp('cache.set_item'); + const setItemSpans = findSpansByMethod('setItem'); expect(setItemSpans.length).toBeGreaterThan(0); const cacheSetSpan = setItemSpans.find( @@ -78,7 +80,7 @@ test.describe('Cache Instrumentation', () => { ); if (cacheSetSpan) { expect(cacheSetSpan.data).toMatchObject({ - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.set_item', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.put', [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.cache.nuxt', 'db.operation.name': 'setItem', 'db.collection.name': expect.stringMatching(/^(cache)?$/), @@ -133,14 +135,10 @@ test.describe('Cache Instrumentation', () => { expect(allCacheSpans?.length).toBeGreaterThan(0); // Get all getItem operations - const allGetItemSpans = allCacheSpans?.filter( - span => span.data?.[SEMANTIC_ATTRIBUTE_SENTRY_OP] === 'cache.get_item', - ); + const allGetItemSpans = allCacheSpans?.filter(span => span.data?.[SEMANTIC_ATTRIBUTE_SENTRY_OP] === 'cache.get'); // Get all setItem operations - const allSetItemSpans = allCacheSpans?.filter( - span => span.data?.[SEMANTIC_ATTRIBUTE_SENTRY_OP] === 'cache.set_item', - ); + const allSetItemSpans = allCacheSpans?.filter(span => span.data?.[SEMANTIC_ATTRIBUTE_SENTRY_OP] === 'cache.put'); // We should have both get and set operations expect(allGetItemSpans?.length).toBeGreaterThan(0); diff --git a/dev-packages/e2e-tests/test-applications/nuxt-4/tests/storage-aliases.test.ts b/dev-packages/e2e-tests/test-applications/nuxt-4/tests/storage-aliases.test.ts index 1e2fc1eb16b1..6d28f1d3cedb 100644 --- a/dev-packages/e2e-tests/test-applications/nuxt-4/tests/storage-aliases.test.ts +++ b/dev-packages/e2e-tests/test-applications/nuxt-4/tests/storage-aliases.test.ts @@ -18,17 +18,19 @@ test.describe('Storage Instrumentation - Aliases', () => { const transaction = await transactionPromise; // Helper to find spans by operation - const findSpansByOp = (op: string) => { - return transaction.spans?.filter(span => span.data?.[SEMANTIC_ATTRIBUTE_SENTRY_OP] === op) || []; + // Several unstorage methods share one convention op (e.g. hasItem/getItem/getKeys are all + // `cache.get`), so spans are located by `db.operation.name`, which stays unique per method. + const findSpansByMethod = (method: string) => { + return transaction.spans?.filter(span => span.data?.['db.operation.name'] === method) || []; }; // Test set (alias for setItem) - const setSpans = findSpansByOp('cache.set_item'); + const setSpans = findSpansByMethod('setItem'); expect(setSpans.length).toBeGreaterThanOrEqual(1); const setSpan = setSpans.find(span => span.data?.[SEMANTIC_ATTRIBUTE_CACHE_KEY] === prefixKey('alias:user')); expect(setSpan).toBeDefined(); expect(setSpan?.data).toMatchObject({ - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.set_item', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.put', [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.cache.nuxt', [SEMANTIC_ATTRIBUTE_CACHE_KEY]: prefixKey('alias:user'), 'db.operation.name': 'setItem', @@ -38,12 +40,12 @@ test.describe('Storage Instrumentation - Aliases', () => { expect(setSpan?.description).toBe(prefixKey('alias:user')); // Test get (alias for getItem) - const getSpans = findSpansByOp('cache.get_item'); + const getSpans = findSpansByMethod('getItem'); expect(getSpans.length).toBeGreaterThanOrEqual(1); const getSpan = getSpans.find(span => span.data?.[SEMANTIC_ATTRIBUTE_CACHE_KEY] === prefixKey('alias:user')); expect(getSpan).toBeDefined(); expect(getSpan?.data).toMatchObject({ - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.get_item', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.get', [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.cache.nuxt', [SEMANTIC_ATTRIBUTE_CACHE_KEY]: prefixKey('alias:user'), [SEMANTIC_ATTRIBUTE_CACHE_HIT]: true, @@ -54,12 +56,12 @@ test.describe('Storage Instrumentation - Aliases', () => { expect(getSpan?.description).toBe(prefixKey('alias:user')); // Test has (alias for hasItem) - const hasSpans = findSpansByOp('cache.has_item'); + const hasSpans = findSpansByMethod('hasItem'); expect(hasSpans.length).toBeGreaterThanOrEqual(1); const hasSpan = hasSpans.find(span => span.data?.[SEMANTIC_ATTRIBUTE_CACHE_KEY] === prefixKey('alias:user')); expect(hasSpan).toBeDefined(); expect(hasSpan?.data).toMatchObject({ - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.has_item', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.get', [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.cache.nuxt', [SEMANTIC_ATTRIBUTE_CACHE_KEY]: prefixKey('alias:user'), [SEMANTIC_ATTRIBUTE_CACHE_HIT]: true, @@ -69,13 +71,13 @@ test.describe('Storage Instrumentation - Aliases', () => { }); // Test del and remove (both aliases for removeItem) - const removeSpans = findSpansByOp('cache.remove_item'); + const removeSpans = findSpansByMethod('removeItem'); expect(removeSpans.length).toBeGreaterThanOrEqual(2); // Should have both del and remove calls const delSpan = removeSpans.find(span => span.data?.[SEMANTIC_ATTRIBUTE_CACHE_KEY] === prefixKey('alias:temp1')); expect(delSpan).toBeDefined(); expect(delSpan?.data).toMatchObject({ - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.remove_item', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.remove', [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.cache.nuxt', [SEMANTIC_ATTRIBUTE_CACHE_KEY]: prefixKey('alias:temp1'), 'db.operation.name': 'removeItem', @@ -87,7 +89,7 @@ test.describe('Storage Instrumentation - Aliases', () => { const removeSpan = removeSpans.find(span => span.data?.[SEMANTIC_ATTRIBUTE_CACHE_KEY] === prefixKey('alias:temp2')); expect(removeSpan).toBeDefined(); expect(removeSpan?.data).toMatchObject({ - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.remove_item', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.remove', [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.cache.nuxt', [SEMANTIC_ATTRIBUTE_CACHE_KEY]: prefixKey('alias:temp2'), 'db.operation.name': 'removeItem', diff --git a/dev-packages/e2e-tests/test-applications/nuxt-4/tests/storage.test.ts b/dev-packages/e2e-tests/test-applications/nuxt-4/tests/storage.test.ts index c171c9b6956f..9543b703f26c 100644 --- a/dev-packages/e2e-tests/test-applications/nuxt-4/tests/storage.test.ts +++ b/dev-packages/e2e-tests/test-applications/nuxt-4/tests/storage.test.ts @@ -18,17 +18,19 @@ test.describe('Storage Instrumentation', () => { const transaction = await transactionPromise; // Helper to find spans by operation - const findSpansByOp = (op: string) => { - return transaction.spans?.filter(span => span.data?.[SEMANTIC_ATTRIBUTE_SENTRY_OP] === op) || []; + // Several unstorage methods share one convention op (e.g. hasItem/getItem/getKeys are all + // `cache.get`), so spans are located by `db.operation.name`, which stays unique per method. + const findSpansByMethod = (method: string) => { + return transaction.spans?.filter(span => span.data?.['db.operation.name'] === method) || []; }; // Test setItem spans - const setItemSpans = findSpansByOp('cache.set_item'); + const setItemSpans = findSpansByMethod('setItem'); expect(setItemSpans.length).toBeGreaterThanOrEqual(1); const setItemSpan = setItemSpans.find(span => span.data?.[SEMANTIC_ATTRIBUTE_CACHE_KEY] === prefixKey('user:123')); expect(setItemSpan).toBeDefined(); expect(setItemSpan?.data).toMatchObject({ - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.set_item', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.put', [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.cache.nuxt', [SEMANTIC_ATTRIBUTE_CACHE_KEY]: prefixKey('user:123'), 'db.operation.name': 'setItem', @@ -38,14 +40,14 @@ test.describe('Storage Instrumentation', () => { expect(setItemSpan?.description).toBe(prefixKey('user:123')); // Test setItemRaw spans - const setItemRawSpans = findSpansByOp('cache.set_item_raw'); + const setItemRawSpans = findSpansByMethod('setItemRaw'); expect(setItemRawSpans.length).toBeGreaterThanOrEqual(1); const setItemRawSpan = setItemRawSpans.find( span => span.data?.[SEMANTIC_ATTRIBUTE_CACHE_KEY] === prefixKey('raw:data'), ); expect(setItemRawSpan).toBeDefined(); expect(setItemRawSpan?.data).toMatchObject({ - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.set_item_raw', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.put', [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.cache.nuxt', [SEMANTIC_ATTRIBUTE_CACHE_KEY]: prefixKey('raw:data'), 'db.operation.name': 'setItemRaw', @@ -54,12 +56,12 @@ test.describe('Storage Instrumentation', () => { }); // Test hasItem spans - should have cache hit attribute - const hasItemSpans = findSpansByOp('cache.has_item'); + const hasItemSpans = findSpansByMethod('hasItem'); expect(hasItemSpans.length).toBeGreaterThanOrEqual(1); const hasItemSpan = hasItemSpans.find(span => span.data?.[SEMANTIC_ATTRIBUTE_CACHE_KEY] === prefixKey('user:123')); expect(hasItemSpan).toBeDefined(); expect(hasItemSpan?.data).toMatchObject({ - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.has_item', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.get', [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.cache.nuxt', [SEMANTIC_ATTRIBUTE_CACHE_KEY]: prefixKey('user:123'), [SEMANTIC_ATTRIBUTE_CACHE_HIT]: true, @@ -69,12 +71,12 @@ test.describe('Storage Instrumentation', () => { }); // Test getItem spans - should have cache hit attribute - const getItemSpans = findSpansByOp('cache.get_item'); + const getItemSpans = findSpansByMethod('getItem'); expect(getItemSpans.length).toBeGreaterThanOrEqual(1); const getItemSpan = getItemSpans.find(span => span.data?.[SEMANTIC_ATTRIBUTE_CACHE_KEY] === prefixKey('user:123')); expect(getItemSpan).toBeDefined(); expect(getItemSpan?.data).toMatchObject({ - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.get_item', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.get', [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.cache.nuxt', [SEMANTIC_ATTRIBUTE_CACHE_KEY]: prefixKey('user:123'), [SEMANTIC_ATTRIBUTE_CACHE_HIT]: true, @@ -85,14 +87,14 @@ test.describe('Storage Instrumentation', () => { expect(getItemSpan?.description).toBe(prefixKey('user:123')); // Test getItemRaw spans - should have cache hit attribute - const getItemRawSpans = findSpansByOp('cache.get_item_raw'); + const getItemRawSpans = findSpansByMethod('getItemRaw'); expect(getItemRawSpans.length).toBeGreaterThanOrEqual(1); const getItemRawSpan = getItemRawSpans.find( span => span.data?.[SEMANTIC_ATTRIBUTE_CACHE_KEY] === prefixKey('raw:data'), ); expect(getItemRawSpan).toBeDefined(); expect(getItemRawSpan?.data).toMatchObject({ - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.get_item_raw', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.get', [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.cache.nuxt', [SEMANTIC_ATTRIBUTE_CACHE_KEY]: prefixKey('raw:data'), [SEMANTIC_ATTRIBUTE_CACHE_HIT]: true, @@ -102,10 +104,10 @@ test.describe('Storage Instrumentation', () => { }); // Test getKeys spans - const getKeysSpans = findSpansByOp('cache.get_keys'); + const getKeysSpans = findSpansByMethod('getKeys'); expect(getKeysSpans.length).toBeGreaterThanOrEqual(1); expect(getKeysSpans[0]?.data).toMatchObject({ - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.get_keys', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.get', [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.cache.nuxt', 'db.operation.name': 'getKeys', 'db.collection.name': 'test-storage', @@ -113,14 +115,14 @@ test.describe('Storage Instrumentation', () => { }); // Test removeItem spans - const removeItemSpans = findSpansByOp('cache.remove_item'); + const removeItemSpans = findSpansByMethod('removeItem'); expect(removeItemSpans.length).toBeGreaterThanOrEqual(1); const removeItemSpan = removeItemSpans.find( span => span.data?.[SEMANTIC_ATTRIBUTE_CACHE_KEY] === prefixKey('batch:1'), ); expect(removeItemSpan).toBeDefined(); expect(removeItemSpan?.data).toMatchObject({ - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.remove_item', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.remove', [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.cache.nuxt', [SEMANTIC_ATTRIBUTE_CACHE_KEY]: prefixKey('batch:1'), 'db.operation.name': 'removeItem', @@ -129,10 +131,10 @@ test.describe('Storage Instrumentation', () => { }); // Test clear spans - const clearSpans = findSpansByOp('cache.clear'); + const clearSpans = findSpansByMethod('clear'); expect(clearSpans.length).toBeGreaterThanOrEqual(1); expect(clearSpans[0]?.data).toMatchObject({ - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.clear', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.remove', [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.cache.nuxt', 'db.operation.name': 'clear', 'db.collection.name': 'test-storage', diff --git a/dev-packages/e2e-tests/test-applications/nuxt-5/tests/cache.test.ts b/dev-packages/e2e-tests/test-applications/nuxt-5/tests/cache.test.ts index 7a660b88d714..845d80c36983 100644 --- a/dev-packages/e2e-tests/test-applications/nuxt-5/tests/cache.test.ts +++ b/dev-packages/e2e-tests/test-applications/nuxt-5/tests/cache.test.ts @@ -19,8 +19,10 @@ test.describe('Cache Instrumentation', () => { const transaction = await transactionPromise; // Helper to find spans by operation - const findSpansByOp = (op: string) => { - return transaction.spans?.filter(span => span.data?.[SEMANTIC_ATTRIBUTE_SENTRY_OP] === op) || []; + // Several unstorage methods share one convention op (e.g. hasItem/getItem/getKeys are all + // `cache.get`), so spans are located by `db.operation.name`, which stays unique per method. + const findSpansByMethod = (method: string) => { + return transaction.spans?.filter(span => span.data?.['db.operation.name'] === method) || []; }; // Test that we have cache operations from cachedFunction and cachedEventHandler @@ -30,7 +32,7 @@ test.describe('Cache Instrumentation', () => { expect(allCacheSpans?.length).toBeGreaterThan(0); // Test getItem spans for cachedFunction - should have both cache miss and cache hit - const getItemSpans = findSpansByOp('cache.get_item'); + const getItemSpans = findSpansByMethod('getItem'); expect(getItemSpans.length).toBeGreaterThan(0); // Find cache miss (first call to getCachedUser('123')) @@ -42,7 +44,7 @@ test.describe('Cache Instrumentation', () => { ); if (cacheMissSpan) { expect(cacheMissSpan.data).toMatchObject({ - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.get_item', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.get', [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.cache.nuxt', [SEMANTIC_ATTRIBUTE_CACHE_HIT]: false, 'db.operation.name': 'getItem', @@ -59,7 +61,7 @@ test.describe('Cache Instrumentation', () => { ); if (cacheHitSpan) { expect(cacheHitSpan.data).toMatchObject({ - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.get_item', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.get', [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.cache.nuxt', [SEMANTIC_ATTRIBUTE_CACHE_HIT]: true, 'db.operation.name': 'getItem', @@ -68,7 +70,7 @@ test.describe('Cache Instrumentation', () => { } // Test setItem spans for cachedFunction - when cache miss occurs, value is set - const setItemSpans = findSpansByOp('cache.set_item'); + const setItemSpans = findSpansByMethod('setItem'); expect(setItemSpans.length).toBeGreaterThan(0); const cacheSetSpan = setItemSpans.find( @@ -78,7 +80,7 @@ test.describe('Cache Instrumentation', () => { ); if (cacheSetSpan) { expect(cacheSetSpan.data).toMatchObject({ - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.set_item', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.put', [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.cache.nuxt', 'db.operation.name': 'setItem', 'db.collection.name': expect.stringMatching(/^(cache)?$/), @@ -133,14 +135,10 @@ test.describe('Cache Instrumentation', () => { expect(allCacheSpans?.length).toBeGreaterThan(0); // Get all getItem operations - const allGetItemSpans = allCacheSpans?.filter( - span => span.data?.[SEMANTIC_ATTRIBUTE_SENTRY_OP] === 'cache.get_item', - ); + const allGetItemSpans = allCacheSpans?.filter(span => span.data?.[SEMANTIC_ATTRIBUTE_SENTRY_OP] === 'cache.get'); // Get all setItem operations - const allSetItemSpans = allCacheSpans?.filter( - span => span.data?.[SEMANTIC_ATTRIBUTE_SENTRY_OP] === 'cache.set_item', - ); + const allSetItemSpans = allCacheSpans?.filter(span => span.data?.[SEMANTIC_ATTRIBUTE_SENTRY_OP] === 'cache.put'); // We should have both get and set operations expect(allGetItemSpans?.length).toBeGreaterThan(0); diff --git a/dev-packages/e2e-tests/test-applications/nuxt-5/tests/storage-aliases.test.ts b/dev-packages/e2e-tests/test-applications/nuxt-5/tests/storage-aliases.test.ts index c6ff331a2780..440bcf32621e 100644 --- a/dev-packages/e2e-tests/test-applications/nuxt-5/tests/storage-aliases.test.ts +++ b/dev-packages/e2e-tests/test-applications/nuxt-5/tests/storage-aliases.test.ts @@ -18,17 +18,19 @@ test.describe('Storage Instrumentation - Aliases', () => { const transaction = await transactionPromise; // Helper to find spans by operation - const findSpansByOp = (op: string) => { - return transaction.spans?.filter(span => span.data?.[SEMANTIC_ATTRIBUTE_SENTRY_OP] === op) || []; + // Several unstorage methods share one convention op (e.g. hasItem/getItem/getKeys are all + // `cache.get`), so spans are located by `db.operation.name`, which stays unique per method. + const findSpansByMethod = (method: string) => { + return transaction.spans?.filter(span => span.data?.['db.operation.name'] === method) || []; }; // Test set (alias for setItem) - const setSpans = findSpansByOp('cache.set_item'); + const setSpans = findSpansByMethod('setItem'); expect(setSpans.length).toBeGreaterThanOrEqual(1); const setSpan = setSpans.find(span => span.data?.[SEMANTIC_ATTRIBUTE_CACHE_KEY] === prefixKey('alias:user')); expect(setSpan).toBeDefined(); expect(setSpan?.data).toMatchObject({ - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.set_item', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.put', [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.cache.nuxt', [SEMANTIC_ATTRIBUTE_CACHE_KEY]: prefixKey('alias:user'), 'db.operation.name': 'setItem', @@ -38,12 +40,12 @@ test.describe('Storage Instrumentation - Aliases', () => { expect(setSpan?.description).toBe(prefixKey('alias:user')); // Test get (alias for getItem) - const getSpans = findSpansByOp('cache.get_item'); + const getSpans = findSpansByMethod('getItem'); expect(getSpans.length).toBeGreaterThanOrEqual(1); const getSpan = getSpans.find(span => span.data?.[SEMANTIC_ATTRIBUTE_CACHE_KEY] === prefixKey('alias:user')); expect(getSpan).toBeDefined(); expect(getSpan?.data).toMatchObject({ - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.get_item', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.get', [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.cache.nuxt', [SEMANTIC_ATTRIBUTE_CACHE_KEY]: prefixKey('alias:user'), [SEMANTIC_ATTRIBUTE_CACHE_HIT]: true, @@ -54,12 +56,12 @@ test.describe('Storage Instrumentation - Aliases', () => { expect(getSpan?.description).toBe(prefixKey('alias:user')); // Test has (alias for hasItem) - const hasSpans = findSpansByOp('cache.has_item'); + const hasSpans = findSpansByMethod('hasItem'); expect(hasSpans.length).toBeGreaterThanOrEqual(1); const hasSpan = hasSpans.find(span => span.data?.[SEMANTIC_ATTRIBUTE_CACHE_KEY] === prefixKey('alias:user')); expect(hasSpan).toBeDefined(); expect(hasSpan?.data).toMatchObject({ - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.has_item', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.get', [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.cache.nuxt', [SEMANTIC_ATTRIBUTE_CACHE_KEY]: prefixKey('alias:user'), [SEMANTIC_ATTRIBUTE_CACHE_HIT]: true, @@ -69,13 +71,13 @@ test.describe('Storage Instrumentation - Aliases', () => { }); // Test del and remove (both aliases for removeItem) - const removeSpans = findSpansByOp('cache.remove_item'); + const removeSpans = findSpansByMethod('removeItem'); expect(removeSpans.length).toBeGreaterThanOrEqual(2); // Should have both del and remove calls const delSpan = removeSpans.find(span => span.data?.[SEMANTIC_ATTRIBUTE_CACHE_KEY] === prefixKey('alias:temp1')); expect(delSpan).toBeDefined(); expect(delSpan?.data).toMatchObject({ - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.remove_item', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.remove', [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.cache.nuxt', [SEMANTIC_ATTRIBUTE_CACHE_KEY]: prefixKey('alias:temp1'), 'db.operation.name': 'removeItem', @@ -87,7 +89,7 @@ test.describe('Storage Instrumentation - Aliases', () => { const removeSpan = removeSpans.find(span => span.data?.[SEMANTIC_ATTRIBUTE_CACHE_KEY] === prefixKey('alias:temp2')); expect(removeSpan).toBeDefined(); expect(removeSpan?.data).toMatchObject({ - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.remove_item', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.remove', [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.cache.nuxt', [SEMANTIC_ATTRIBUTE_CACHE_KEY]: prefixKey('alias:temp2'), 'db.operation.name': 'removeItem', diff --git a/dev-packages/e2e-tests/test-applications/nuxt-5/tests/storage.test.ts b/dev-packages/e2e-tests/test-applications/nuxt-5/tests/storage.test.ts index b0d9af9142da..9655c8f8be47 100644 --- a/dev-packages/e2e-tests/test-applications/nuxt-5/tests/storage.test.ts +++ b/dev-packages/e2e-tests/test-applications/nuxt-5/tests/storage.test.ts @@ -18,17 +18,19 @@ test.describe('Storage Instrumentation', () => { const transaction = await transactionPromise; // Helper to find spans by operation - const findSpansByOp = (op: string) => { - return transaction.spans?.filter(span => span.data?.[SEMANTIC_ATTRIBUTE_SENTRY_OP] === op) || []; + // Several unstorage methods share one convention op (e.g. hasItem/getItem/getKeys are all + // `cache.get`), so spans are located by `db.operation.name`, which stays unique per method. + const findSpansByMethod = (method: string) => { + return transaction.spans?.filter(span => span.data?.['db.operation.name'] === method) || []; }; // Test setItem spans - const setItemSpans = findSpansByOp('cache.set_item'); + const setItemSpans = findSpansByMethod('setItem'); expect(setItemSpans.length).toBeGreaterThanOrEqual(1); const setItemSpan = setItemSpans.find(span => span.data?.[SEMANTIC_ATTRIBUTE_CACHE_KEY] === prefixKey('user:123')); expect(setItemSpan).toBeDefined(); expect(setItemSpan?.data).toMatchObject({ - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.set_item', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.put', [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.cache.nuxt', [SEMANTIC_ATTRIBUTE_CACHE_KEY]: prefixKey('user:123'), 'db.operation.name': 'setItem', @@ -38,14 +40,14 @@ test.describe('Storage Instrumentation', () => { expect(setItemSpan?.description).toBe(prefixKey('user:123')); // Test setItemRaw spans - const setItemRawSpans = findSpansByOp('cache.set_item_raw'); + const setItemRawSpans = findSpansByMethod('setItemRaw'); expect(setItemRawSpans.length).toBeGreaterThanOrEqual(1); const setItemRawSpan = setItemRawSpans.find( span => span.data?.[SEMANTIC_ATTRIBUTE_CACHE_KEY] === prefixKey('raw:data'), ); expect(setItemRawSpan).toBeDefined(); expect(setItemRawSpan?.data).toMatchObject({ - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.set_item_raw', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.put', [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.cache.nuxt', [SEMANTIC_ATTRIBUTE_CACHE_KEY]: prefixKey('raw:data'), 'db.operation.name': 'setItemRaw', @@ -54,12 +56,12 @@ test.describe('Storage Instrumentation', () => { }); // Test hasItem spans - should have cache hit attribute - const hasItemSpans = findSpansByOp('cache.has_item'); + const hasItemSpans = findSpansByMethod('hasItem'); expect(hasItemSpans.length).toBeGreaterThanOrEqual(1); const hasItemSpan = hasItemSpans.find(span => span.data?.[SEMANTIC_ATTRIBUTE_CACHE_KEY] === prefixKey('user:123')); expect(hasItemSpan).toBeDefined(); expect(hasItemSpan?.data).toMatchObject({ - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.has_item', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.get', [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.cache.nuxt', [SEMANTIC_ATTRIBUTE_CACHE_KEY]: prefixKey('user:123'), [SEMANTIC_ATTRIBUTE_CACHE_HIT]: true, @@ -69,12 +71,12 @@ test.describe('Storage Instrumentation', () => { }); // Test getItem spans - should have cache hit attribute - const getItemSpans = findSpansByOp('cache.get_item'); + const getItemSpans = findSpansByMethod('getItem'); expect(getItemSpans.length).toBeGreaterThanOrEqual(1); const getItemSpan = getItemSpans.find(span => span.data?.[SEMANTIC_ATTRIBUTE_CACHE_KEY] === prefixKey('user:123')); expect(getItemSpan).toBeDefined(); expect(getItemSpan?.data).toMatchObject({ - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.get_item', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.get', [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.cache.nuxt', [SEMANTIC_ATTRIBUTE_CACHE_KEY]: prefixKey('user:123'), [SEMANTIC_ATTRIBUTE_CACHE_HIT]: true, @@ -85,14 +87,14 @@ test.describe('Storage Instrumentation', () => { expect(getItemSpan?.description).toBe(prefixKey('user:123')); // Test getItemRaw spans - should have cache hit attribute - const getItemRawSpans = findSpansByOp('cache.get_item_raw'); + const getItemRawSpans = findSpansByMethod('getItemRaw'); expect(getItemRawSpans.length).toBeGreaterThanOrEqual(1); const getItemRawSpan = getItemRawSpans.find( span => span.data?.[SEMANTIC_ATTRIBUTE_CACHE_KEY] === prefixKey('raw:data'), ); expect(getItemRawSpan).toBeDefined(); expect(getItemRawSpan?.data).toMatchObject({ - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.get_item_raw', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.get', [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.cache.nuxt', [SEMANTIC_ATTRIBUTE_CACHE_KEY]: prefixKey('raw:data'), [SEMANTIC_ATTRIBUTE_CACHE_HIT]: true, @@ -102,10 +104,10 @@ test.describe('Storage Instrumentation', () => { }); // Test getKeys spans - const getKeysSpans = findSpansByOp('cache.get_keys'); + const getKeysSpans = findSpansByMethod('getKeys'); expect(getKeysSpans.length).toBeGreaterThanOrEqual(1); expect(getKeysSpans[0]?.data).toMatchObject({ - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.get_keys', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.get', [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.cache.nuxt', 'db.operation.name': 'getKeys', 'db.collection.name': 'test-storage', @@ -113,14 +115,14 @@ test.describe('Storage Instrumentation', () => { }); // Test removeItem spans - const removeItemSpans = findSpansByOp('cache.remove_item'); + const removeItemSpans = findSpansByMethod('removeItem'); expect(removeItemSpans.length).toBeGreaterThanOrEqual(1); const removeItemSpan = removeItemSpans.find( span => span.data?.[SEMANTIC_ATTRIBUTE_CACHE_KEY] === prefixKey('batch:1'), ); expect(removeItemSpan).toBeDefined(); expect(removeItemSpan?.data).toMatchObject({ - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.remove_item', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.remove', [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.cache.nuxt', [SEMANTIC_ATTRIBUTE_CACHE_KEY]: prefixKey('batch:1'), 'db.operation.name': 'removeItem', @@ -129,10 +131,10 @@ test.describe('Storage Instrumentation', () => { }); // Test clear spans - const clearSpans = findSpansByOp('cache.clear'); + const clearSpans = findSpansByMethod('clear'); expect(clearSpans.length).toBeGreaterThanOrEqual(1); expect(clearSpans[0]?.data).toMatchObject({ - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.clear', + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'cache.remove', [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.cache.nuxt', 'db.operation.name': 'clear', 'db.collection.name': 'test-storage', diff --git a/packages/nitro/package.json b/packages/nitro/package.json index cc17edbd6b86..48c495001f26 100644 --- a/packages/nitro/package.json +++ b/packages/nitro/package.json @@ -36,6 +36,7 @@ }, "dependencies": { "@sentry/bundler-plugins": "^10.67.0", + "@sentry/conventions": "^0.16.0", "@sentry/core": "10.67.0", "@sentry/node": "10.67.0", "@sentry/server-utils": "10.67.0" diff --git a/packages/nitro/src/runtime/hooks/captureStorageEvents.ts b/packages/nitro/src/runtime/hooks/captureStorageEvents.ts index dc5e7396a934..54ccf7dd5509 100644 --- a/packages/nitro/src/runtime/hooks/captureStorageEvents.ts +++ b/packages/nitro/src/runtime/hooks/captureStorageEvents.ts @@ -1,4 +1,9 @@ import * as dc from 'node:diagnostics_channel'; +import { + DATABASE_CACHE_GET_SPAN_OP, + DATABASE_CACHE_PUT_SPAN_OP, + DATABASE_CACHE_REMOVE_SPAN_OP, +} from '@sentry/conventions/op'; import { flushIfServerless, GLOBAL_OBJ, @@ -34,6 +39,24 @@ type TracedOperation = (typeof TRACED_OPERATIONS)[number]; const CACHE_HIT_OPERATIONS = new Set(['hasItem', 'getItem', 'getItemRaw']); +/** + * Maps each unstorage operation to a convention cache op. Reads (including existence and key + * listing) are `cache.get`, writes are `cache.put`, and deletions are `cache.remove`. + * The precise operation stays available on `db.operation.name`. + */ +const OPERATION_SPAN_OPS = { + hasItem: DATABASE_CACHE_GET_SPAN_OP, + getItem: DATABASE_CACHE_GET_SPAN_OP, + getItemRaw: DATABASE_CACHE_GET_SPAN_OP, + getItems: DATABASE_CACHE_GET_SPAN_OP, + getKeys: DATABASE_CACHE_GET_SPAN_OP, + setItem: DATABASE_CACHE_PUT_SPAN_OP, + setItemRaw: DATABASE_CACHE_PUT_SPAN_OP, + setItems: DATABASE_CACHE_PUT_SPAN_OP, + removeItem: DATABASE_CACHE_REMOVE_SPAN_OP, + clear: DATABASE_CACHE_REMOVE_SPAN_OP, +} as const satisfies Record; + const CACHED_FN_HANDLERS_RE = /^nitro:(functions|handlers):/i; /** @@ -68,7 +91,7 @@ function setupStorageTracingChannel(operation: TracedOperation): void { return startInactiveSpan({ name: cacheKeys.join(', ') || operation, attributes: { - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: `cache.${normalizeMethodName(operation)}`, + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: OPERATION_SPAN_OPS[operation], [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: ORIGIN, [SEMANTIC_ATTRIBUTE_CACHE_KEY]: cacheKeys.length > 1 ? cacheKeys : cacheKeys[0], 'db.operation.name': operation, @@ -95,10 +118,6 @@ function setupStorageTracingChannel(operation: TracedOperation): void { ); } -function normalizeMethodName(methodName: string): string { - return methodName.replace(/[A-Z]/g, letter => `_${letter.toLowerCase()}`); -} - interface CacheEntry { value?: T; expires?: number; diff --git a/packages/nuxt/package.json b/packages/nuxt/package.json index 1ef9e69ef68b..7e59613e6546 100644 --- a/packages/nuxt/package.json +++ b/packages/nuxt/package.json @@ -56,6 +56,7 @@ "@nuxt/kit": "^3.13.2", "@sentry/browser": "10.67.0", "@sentry/cloudflare": "10.67.0", + "@sentry/conventions": "^0.16.0", "@sentry/core": "10.67.0", "@sentry/node": "10.67.0", "@sentry/bundler-plugins": "10.67.0", diff --git a/packages/nuxt/src/runtime/utils/instrumentStorage.ts b/packages/nuxt/src/runtime/utils/instrumentStorage.ts index 3e23a5087f4c..9ceca81ed7df 100644 --- a/packages/nuxt/src/runtime/utils/instrumentStorage.ts +++ b/packages/nuxt/src/runtime/utils/instrumentStorage.ts @@ -1,3 +1,8 @@ +import { + DATABASE_CACHE_GET_SPAN_OP, + DATABASE_CACHE_PUT_SPAN_OP, + DATABASE_CACHE_REMOVE_SPAN_OP, +} from '@sentry/conventions/op'; import { isObjectLike, captureException, @@ -55,6 +60,24 @@ type DriverMethod = keyof Driver; */ const CACHE_HIT_METHODS = new Set(['hasItem', 'getItem', 'getItemRaw']); +/** + * Maps each unstorage method to a convention cache op. Reads (including existence and key + * listing) are `cache.get`, writes are `cache.put`, and deletions are `cache.remove`. + * The precise method stays available on `db.operation.name`. + */ +const METHOD_SPAN_OPS = { + hasItem: DATABASE_CACHE_GET_SPAN_OP, + getItem: DATABASE_CACHE_GET_SPAN_OP, + getItemRaw: DATABASE_CACHE_GET_SPAN_OP, + getItems: DATABASE_CACHE_GET_SPAN_OP, + getKeys: DATABASE_CACHE_GET_SPAN_OP, + setItem: DATABASE_CACHE_PUT_SPAN_OP, + setItemRaw: DATABASE_CACHE_PUT_SPAN_OP, + setItems: DATABASE_CACHE_PUT_SPAN_OP, + removeItem: DATABASE_CACHE_REMOVE_SPAN_OP, + clear: DATABASE_CACHE_REMOVE_SPAN_OP, +} as const satisfies Partial>; + /** * Creates the Nitro storage plugin setup by instrumenting all relevant storage drivers. * @@ -203,13 +226,6 @@ function wrapStorageMount(storage: Storage): Storage['mount'] { return mountWithInstrumentation; } -/** - * Normalizes the method name to snake_case to be used in span names or op. - */ -function normalizeMethodName(methodName: string): string { - return methodName.replace(/[A-Z]/g, letter => `_${letter.toLowerCase()}`); -} - /** * Creates the span start options for the storage method. */ @@ -222,7 +238,7 @@ function createSpanStartOptions( const keys = getCacheKeys(args?.[0], mountBase); const attributes: SpanAttributes = { - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: `cache.${normalizeMethodName(methodName)}`, + [SEMANTIC_ATTRIBUTE_SENTRY_OP]: METHOD_SPAN_OPS[methodName as keyof typeof METHOD_SPAN_OPS], [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.cache.nuxt', [SEMANTIC_ATTRIBUTE_CACHE_KEY]: keys.length > 1 ? keys : keys[0], 'db.operation.name': methodName, From 07fa5dec3b734ca13f06747ddb219d8416b74d97 Mon Sep 17 00:00:00 2001 From: Martin Sonnberger Date: Wed, 29 Jul 2026 10:29:01 +0200 Subject: [PATCH 2/5] use sentry.op --- packages/nitro/src/runtime/hooks/captureStorageEvents.ts | 4 ++-- packages/nuxt/src/runtime/utils/instrumentStorage.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/nitro/src/runtime/hooks/captureStorageEvents.ts b/packages/nitro/src/runtime/hooks/captureStorageEvents.ts index 54ccf7dd5509..dafd1add83a9 100644 --- a/packages/nitro/src/runtime/hooks/captureStorageEvents.ts +++ b/packages/nitro/src/runtime/hooks/captureStorageEvents.ts @@ -1,4 +1,5 @@ import * as dc from 'node:diagnostics_channel'; +import { SENTRY_OP } from '@sentry/conventions/attributes'; import { DATABASE_CACHE_GET_SPAN_OP, DATABASE_CACHE_PUT_SPAN_OP, @@ -9,7 +10,6 @@ import { GLOBAL_OBJ, SEMANTIC_ATTRIBUTE_CACHE_HIT, SEMANTIC_ATTRIBUTE_CACHE_KEY, - SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, startInactiveSpan, } from '@sentry/core'; @@ -91,7 +91,7 @@ function setupStorageTracingChannel(operation: TracedOperation): void { return startInactiveSpan({ name: cacheKeys.join(', ') || operation, attributes: { - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: OPERATION_SPAN_OPS[operation], + [SENTRY_OP]: OPERATION_SPAN_OPS[operation], [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: ORIGIN, [SEMANTIC_ATTRIBUTE_CACHE_KEY]: cacheKeys.length > 1 ? cacheKeys : cacheKeys[0], 'db.operation.name': operation, diff --git a/packages/nuxt/src/runtime/utils/instrumentStorage.ts b/packages/nuxt/src/runtime/utils/instrumentStorage.ts index 9ceca81ed7df..b04b2c1b73b2 100644 --- a/packages/nuxt/src/runtime/utils/instrumentStorage.ts +++ b/packages/nuxt/src/runtime/utils/instrumentStorage.ts @@ -1,3 +1,4 @@ +import { SENTRY_OP } from '@sentry/conventions/attributes'; import { DATABASE_CACHE_GET_SPAN_OP, DATABASE_CACHE_PUT_SPAN_OP, @@ -10,7 +11,6 @@ import { flushIfServerless, SEMANTIC_ATTRIBUTE_CACHE_HIT, SEMANTIC_ATTRIBUTE_CACHE_KEY, - SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SPAN_STATUS_ERROR, SPAN_STATUS_OK, @@ -238,7 +238,7 @@ function createSpanStartOptions( const keys = getCacheKeys(args?.[0], mountBase); const attributes: SpanAttributes = { - [SEMANTIC_ATTRIBUTE_SENTRY_OP]: METHOD_SPAN_OPS[methodName as keyof typeof METHOD_SPAN_OPS], + [SENTRY_OP]: METHOD_SPAN_OPS[methodName as keyof typeof METHOD_SPAN_OPS], [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.cache.nuxt', [SEMANTIC_ATTRIBUTE_CACHE_KEY]: keys.length > 1 ? keys : keys[0], 'db.operation.name': methodName, From 7d0f2acfb52c8078d074caca974797382eb5442b Mon Sep 17 00:00:00 2001 From: Martin Sonnberger Date: Wed, 29 Jul 2026 11:17:30 +0200 Subject: [PATCH 3/5] fix `hasItem` hit logic in nuxt --- packages/nuxt/src/runtime/utils/instrumentStorage.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/nuxt/src/runtime/utils/instrumentStorage.ts b/packages/nuxt/src/runtime/utils/instrumentStorage.ts index b04b2c1b73b2..47b96b5f88f3 100644 --- a/packages/nuxt/src/runtime/utils/instrumentStorage.ts +++ b/packages/nuxt/src/runtime/utils/instrumentStorage.ts @@ -181,7 +181,8 @@ function createMethodWrapper( span.setStatus({ code: SPAN_STATUS_OK }); if (CACHE_HIT_METHODS.has(methodName)) { - span.setAttribute(SEMANTIC_ATTRIBUTE_CACHE_HIT, isCacheHit(args[0], result)); + const hit = methodName === 'hasItem' ? Boolean(result) : isCacheHit(args[0], result); + span.setAttribute(SEMANTIC_ATTRIBUTE_CACHE_HIT, hit); } return result; From 28cf6325922cf75680da5aaa81bf9775a65ed95e Mon Sep 17 00:00:00 2001 From: Martin Sonnberger Date: Wed, 29 Jul 2026 11:37:58 +0200 Subject: [PATCH 4/5] compute cache hit for `getItems` --- .../src/runtime/hooks/captureStorageEvents.ts | 23 ++++++++++++++++--- .../src/runtime/utils/instrumentStorage.ts | 22 +++++++++++++++--- 2 files changed, 39 insertions(+), 6 deletions(-) diff --git a/packages/nitro/src/runtime/hooks/captureStorageEvents.ts b/packages/nitro/src/runtime/hooks/captureStorageEvents.ts index dafd1add83a9..7bcbdac098f9 100644 --- a/packages/nitro/src/runtime/hooks/captureStorageEvents.ts +++ b/packages/nitro/src/runtime/hooks/captureStorageEvents.ts @@ -8,6 +8,7 @@ import { import { flushIfServerless, GLOBAL_OBJ, + isObjectLike, SEMANTIC_ATTRIBUTE_CACHE_HIT, SEMANTIC_ATTRIBUTE_CACHE_KEY, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, @@ -37,7 +38,7 @@ const TRACED_OPERATIONS = [ type TracedOperation = (typeof TRACED_OPERATIONS)[number]; -const CACHE_HIT_OPERATIONS = new Set(['hasItem', 'getItem', 'getItemRaw']); +const CACHE_HIT_OPERATIONS = new Set(['hasItem', 'getItem', 'getItemRaw', 'getItems']); /** * Maps each unstorage operation to a convention cache op. Reads (including existence and key @@ -107,8 +108,7 @@ function setupStorageTracingChannel(operation: TracedOperation): void { if (!('error' in data)) { const result = (data as { result?: unknown }).result; if (CACHE_HIT_OPERATIONS.has(operation)) { - const hit = operation === 'hasItem' ? Boolean(result) : isCacheHit(data.keys?.[0], result); - span.setAttribute(SEMANTIC_ATTRIBUTE_CACHE_HIT, hit); + span.setAttribute(SEMANTIC_ATTRIBUTE_CACHE_HIT, resolveCacheHit(operation, data.keys?.[0], result)); } } @@ -118,6 +118,23 @@ function setupStorageTracingChannel(operation: TracedOperation): void { ); } +/** + * Resolves the `cache.hit` value for a read operation. `hasItem` returns a boolean directly, + * `getItems` returns a `{ key, value }[]` where a hit means at least one entry has a value, + * and single-key reads fall back to the value-based `isCacheHit` check. + */ +function resolveCacheHit(operation: TracedOperation, key: unknown, result: unknown): boolean { + if (operation === 'hasItem') { + return Boolean(result); + } + + if (operation === 'getItems') { + return Array.isArray(result) && result.some(item => isObjectLike(item) && item.value != null); + } + + return isCacheHit(key, result); +} + interface CacheEntry { value?: T; expires?: number; diff --git a/packages/nuxt/src/runtime/utils/instrumentStorage.ts b/packages/nuxt/src/runtime/utils/instrumentStorage.ts index 47b96b5f88f3..ea55c1f502c9 100644 --- a/packages/nuxt/src/runtime/utils/instrumentStorage.ts +++ b/packages/nuxt/src/runtime/utils/instrumentStorage.ts @@ -58,7 +58,7 @@ type DriverMethod = keyof Driver; /** * Methods that should have an attribute to indicate a cache hit. */ -const CACHE_HIT_METHODS = new Set(['hasItem', 'getItem', 'getItemRaw']); +const CACHE_HIT_METHODS = new Set(['hasItem', 'getItem', 'getItemRaw', 'getItems']); /** * Maps each unstorage method to a convention cache op. Reads (including existence and key @@ -181,8 +181,7 @@ function createMethodWrapper( span.setStatus({ code: SPAN_STATUS_OK }); if (CACHE_HIT_METHODS.has(methodName)) { - const hit = methodName === 'hasItem' ? Boolean(result) : isCacheHit(args[0], result); - span.setAttribute(SEMANTIC_ATTRIBUTE_CACHE_HIT, hit); + span.setAttribute(SEMANTIC_ATTRIBUTE_CACHE_HIT, resolveCacheHit(methodName, args[0], result)); } return result; @@ -283,6 +282,23 @@ function normalizeKey(key: unknown, prefix: string): string { const CACHED_FN_HANDLERS_RE = /^nitro:(functions|handlers):/i; +/** + * Resolves the `cache.hit` value for a read method. `hasItem` returns a boolean directly, + * `getItems` returns a `{ key, value }[]` where a hit means at least one entry has a value, + * and single-key reads fall back to the value-based `isCacheHit` check. + */ +function resolveCacheHit(methodName: DriverMethod, key: unknown, result: unknown): boolean { + if (methodName === 'hasItem') { + return Boolean(result); + } + + if (methodName === 'getItems') { + return Array.isArray(result) && result.some(item => isObjectLike(item) && item.value != null); + } + + return isCacheHit(key, result); +} + /** * Since Nitro's cache may not utilize the driver's TTL, it is possible that the value is present in the cache but won't be used by Nitro. * The maxAge and expires values are serialized by Nitro in the cache entry. This means the value presence does not necessarily mean a cache hit. From 87a305ea14c63056d33c0e78336837d03426c8b7 Mon Sep 17 00:00:00 2001 From: Martin Sonnberger Date: Thu, 30 Jul 2026 10:40:28 +0200 Subject: [PATCH 5/5] remove comment --- .../e2e-tests/test-applications/nitro-3/tests/cache.test.ts | 2 -- .../test-applications/nitro-3/tests/storage-aliases.test.ts | 2 -- .../e2e-tests/test-applications/nitro-3/tests/storage.test.ts | 2 -- .../e2e-tests/test-applications/nuxt-3/tests/cache.test.ts | 2 -- .../test-applications/nuxt-3/tests/storage-aliases.test.ts | 2 -- .../e2e-tests/test-applications/nuxt-3/tests/storage.test.ts | 2 -- .../e2e-tests/test-applications/nuxt-4/tests/cache.test.ts | 2 -- .../test-applications/nuxt-4/tests/storage-aliases.test.ts | 2 -- .../e2e-tests/test-applications/nuxt-4/tests/storage.test.ts | 2 -- .../e2e-tests/test-applications/nuxt-5/tests/cache.test.ts | 2 -- .../test-applications/nuxt-5/tests/storage-aliases.test.ts | 2 -- .../e2e-tests/test-applications/nuxt-5/tests/storage.test.ts | 2 -- 12 files changed, 24 deletions(-) diff --git a/dev-packages/e2e-tests/test-applications/nitro-3/tests/cache.test.ts b/dev-packages/e2e-tests/test-applications/nitro-3/tests/cache.test.ts index 53b7c0118d37..336e74c8e030 100644 --- a/dev-packages/e2e-tests/test-applications/nitro-3/tests/cache.test.ts +++ b/dev-packages/e2e-tests/test-applications/nitro-3/tests/cache.test.ts @@ -18,8 +18,6 @@ test.describe('Cache Instrumentation', () => { const transaction = await transactionPromise; - // Several unstorage methods share one convention op (e.g. hasItem/getItem/getKeys are all - // `cache.get`), so spans are located by `db.operation.name`, which stays unique per method. const findSpansByMethod = (method: string) => { return transaction.spans?.filter(span => span.data?.['db.operation.name'] === method) || []; }; diff --git a/dev-packages/e2e-tests/test-applications/nitro-3/tests/storage-aliases.test.ts b/dev-packages/e2e-tests/test-applications/nitro-3/tests/storage-aliases.test.ts index 746bf1c1294f..2109810bc9be 100644 --- a/dev-packages/e2e-tests/test-applications/nitro-3/tests/storage-aliases.test.ts +++ b/dev-packages/e2e-tests/test-applications/nitro-3/tests/storage-aliases.test.ts @@ -18,8 +18,6 @@ test.describe('Storage Instrumentation - Aliases', () => { const transaction = await transactionPromise; // Helper to find spans by operation - // Several unstorage methods share one convention op (e.g. hasItem/getItem/getKeys are all - // `cache.get`), so spans are located by `db.operation.name`, which stays unique per method. const findSpansByMethod = (method: string) => { return transaction.spans?.filter(span => span.data?.['db.operation.name'] === method) || []; }; diff --git a/dev-packages/e2e-tests/test-applications/nitro-3/tests/storage.test.ts b/dev-packages/e2e-tests/test-applications/nitro-3/tests/storage.test.ts index b7f01d8e87ce..21d3ccc9c343 100644 --- a/dev-packages/e2e-tests/test-applications/nitro-3/tests/storage.test.ts +++ b/dev-packages/e2e-tests/test-applications/nitro-3/tests/storage.test.ts @@ -18,8 +18,6 @@ test.describe('Storage Instrumentation', () => { const transaction = await transactionPromise; // Helper to find spans by operation - // Several unstorage methods share one convention op (e.g. hasItem/getItem/getKeys are all - // `cache.get`), so spans are located by `db.operation.name`, which stays unique per method. const findSpansByMethod = (method: string) => { return transaction.spans?.filter(span => span.data?.['db.operation.name'] === method) || []; }; diff --git a/dev-packages/e2e-tests/test-applications/nuxt-3/tests/cache.test.ts b/dev-packages/e2e-tests/test-applications/nuxt-3/tests/cache.test.ts index af34ac5d306c..135ce9a71e42 100644 --- a/dev-packages/e2e-tests/test-applications/nuxt-3/tests/cache.test.ts +++ b/dev-packages/e2e-tests/test-applications/nuxt-3/tests/cache.test.ts @@ -19,8 +19,6 @@ test.describe('Cache Instrumentation', () => { const transaction = await transactionPromise; // Helper to find spans by operation - // Several unstorage methods share one convention op (e.g. hasItem/getItem/getKeys are all - // `cache.get`), so spans are located by `db.operation.name`, which stays unique per method. const findSpansByMethod = (method: string) => { return transaction.spans?.filter(span => span.data?.['db.operation.name'] === method) || []; }; diff --git a/dev-packages/e2e-tests/test-applications/nuxt-3/tests/storage-aliases.test.ts b/dev-packages/e2e-tests/test-applications/nuxt-3/tests/storage-aliases.test.ts index 2e6241e811f5..41ae29fd3560 100644 --- a/dev-packages/e2e-tests/test-applications/nuxt-3/tests/storage-aliases.test.ts +++ b/dev-packages/e2e-tests/test-applications/nuxt-3/tests/storage-aliases.test.ts @@ -18,8 +18,6 @@ test.describe('Storage Instrumentation - Aliases', () => { const transaction = await transactionPromise; // Helper to find spans by operation - // Several unstorage methods share one convention op (e.g. hasItem/getItem/getKeys are all - // `cache.get`), so spans are located by `db.operation.name`, which stays unique per method. const findSpansByMethod = (method: string) => { return transaction.spans?.filter(span => span.data?.['db.operation.name'] === method) || []; }; diff --git a/dev-packages/e2e-tests/test-applications/nuxt-3/tests/storage.test.ts b/dev-packages/e2e-tests/test-applications/nuxt-3/tests/storage.test.ts index aaaed1b315a9..07cee795e50f 100644 --- a/dev-packages/e2e-tests/test-applications/nuxt-3/tests/storage.test.ts +++ b/dev-packages/e2e-tests/test-applications/nuxt-3/tests/storage.test.ts @@ -18,8 +18,6 @@ test.describe('Storage Instrumentation', () => { const transaction = await transactionPromise; // Helper to find spans by operation - // Several unstorage methods share one convention op (e.g. hasItem/getItem/getKeys are all - // `cache.get`), so spans are located by `db.operation.name`, which stays unique per method. const findSpansByMethod = (method: string) => { return transaction.spans?.filter(span => span.data?.['db.operation.name'] === method) || []; }; diff --git a/dev-packages/e2e-tests/test-applications/nuxt-4/tests/cache.test.ts b/dev-packages/e2e-tests/test-applications/nuxt-4/tests/cache.test.ts index 5572a57b6f9c..47a0799c736c 100644 --- a/dev-packages/e2e-tests/test-applications/nuxt-4/tests/cache.test.ts +++ b/dev-packages/e2e-tests/test-applications/nuxt-4/tests/cache.test.ts @@ -19,8 +19,6 @@ test.describe('Cache Instrumentation', () => { const transaction = await transactionPromise; // Helper to find spans by operation - // Several unstorage methods share one convention op (e.g. hasItem/getItem/getKeys are all - // `cache.get`), so spans are located by `db.operation.name`, which stays unique per method. const findSpansByMethod = (method: string) => { return transaction.spans?.filter(span => span.data?.['db.operation.name'] === method) || []; }; diff --git a/dev-packages/e2e-tests/test-applications/nuxt-4/tests/storage-aliases.test.ts b/dev-packages/e2e-tests/test-applications/nuxt-4/tests/storage-aliases.test.ts index 6d28f1d3cedb..31d4d0af5e48 100644 --- a/dev-packages/e2e-tests/test-applications/nuxt-4/tests/storage-aliases.test.ts +++ b/dev-packages/e2e-tests/test-applications/nuxt-4/tests/storage-aliases.test.ts @@ -18,8 +18,6 @@ test.describe('Storage Instrumentation - Aliases', () => { const transaction = await transactionPromise; // Helper to find spans by operation - // Several unstorage methods share one convention op (e.g. hasItem/getItem/getKeys are all - // `cache.get`), so spans are located by `db.operation.name`, which stays unique per method. const findSpansByMethod = (method: string) => { return transaction.spans?.filter(span => span.data?.['db.operation.name'] === method) || []; }; diff --git a/dev-packages/e2e-tests/test-applications/nuxt-4/tests/storage.test.ts b/dev-packages/e2e-tests/test-applications/nuxt-4/tests/storage.test.ts index 9543b703f26c..98b457ba0f34 100644 --- a/dev-packages/e2e-tests/test-applications/nuxt-4/tests/storage.test.ts +++ b/dev-packages/e2e-tests/test-applications/nuxt-4/tests/storage.test.ts @@ -18,8 +18,6 @@ test.describe('Storage Instrumentation', () => { const transaction = await transactionPromise; // Helper to find spans by operation - // Several unstorage methods share one convention op (e.g. hasItem/getItem/getKeys are all - // `cache.get`), so spans are located by `db.operation.name`, which stays unique per method. const findSpansByMethod = (method: string) => { return transaction.spans?.filter(span => span.data?.['db.operation.name'] === method) || []; }; diff --git a/dev-packages/e2e-tests/test-applications/nuxt-5/tests/cache.test.ts b/dev-packages/e2e-tests/test-applications/nuxt-5/tests/cache.test.ts index 845d80c36983..6a14162b7278 100644 --- a/dev-packages/e2e-tests/test-applications/nuxt-5/tests/cache.test.ts +++ b/dev-packages/e2e-tests/test-applications/nuxt-5/tests/cache.test.ts @@ -19,8 +19,6 @@ test.describe('Cache Instrumentation', () => { const transaction = await transactionPromise; // Helper to find spans by operation - // Several unstorage methods share one convention op (e.g. hasItem/getItem/getKeys are all - // `cache.get`), so spans are located by `db.operation.name`, which stays unique per method. const findSpansByMethod = (method: string) => { return transaction.spans?.filter(span => span.data?.['db.operation.name'] === method) || []; }; diff --git a/dev-packages/e2e-tests/test-applications/nuxt-5/tests/storage-aliases.test.ts b/dev-packages/e2e-tests/test-applications/nuxt-5/tests/storage-aliases.test.ts index 440bcf32621e..ad9e0803a580 100644 --- a/dev-packages/e2e-tests/test-applications/nuxt-5/tests/storage-aliases.test.ts +++ b/dev-packages/e2e-tests/test-applications/nuxt-5/tests/storage-aliases.test.ts @@ -18,8 +18,6 @@ test.describe('Storage Instrumentation - Aliases', () => { const transaction = await transactionPromise; // Helper to find spans by operation - // Several unstorage methods share one convention op (e.g. hasItem/getItem/getKeys are all - // `cache.get`), so spans are located by `db.operation.name`, which stays unique per method. const findSpansByMethod = (method: string) => { return transaction.spans?.filter(span => span.data?.['db.operation.name'] === method) || []; }; diff --git a/dev-packages/e2e-tests/test-applications/nuxt-5/tests/storage.test.ts b/dev-packages/e2e-tests/test-applications/nuxt-5/tests/storage.test.ts index 9655c8f8be47..ad7c3b8b2b89 100644 --- a/dev-packages/e2e-tests/test-applications/nuxt-5/tests/storage.test.ts +++ b/dev-packages/e2e-tests/test-applications/nuxt-5/tests/storage.test.ts @@ -18,8 +18,6 @@ test.describe('Storage Instrumentation', () => { const transaction = await transactionPromise; // Helper to find spans by operation - // Several unstorage methods share one convention op (e.g. hasItem/getItem/getKeys are all - // `cache.get`), so spans are located by `db.operation.name`, which stays unique per method. const findSpansByMethod = (method: string) => { return transaction.spans?.filter(span => span.data?.['db.operation.name'] === method) || []; };