Skip to content

Commit c145c32

Browse files
committed
feat: clean up attributes and use semantic cache ops
1 parent 4e3692c commit c145c32

File tree

1 file changed

+34
-12
lines changed

1 file changed

+34
-12
lines changed

packages/nuxt/src/runtime/plugins/storage.server.ts

Lines changed: 34 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@ import {
33
captureException,
44
debug,
55
flushIfServerless,
6+
SEMANTIC_ATTRIBUTE_CACHE_HIT,
7+
SEMANTIC_ATTRIBUTE_CACHE_KEY,
68
SEMANTIC_ATTRIBUTE_SENTRY_OP,
79
SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,
8-
SEMANTIC_ATTRIBUTE_SENTRY_SOURCE,
910
SPAN_STATUS_ERROR,
1011
SPAN_STATUS_OK,
1112
startSpan,
@@ -20,6 +21,11 @@ type MaybeInstrumentedDriver = Driver & {
2021
__sentry_instrumented__?: boolean;
2122
};
2223

24+
/**
25+
* Methods that should have a attribute to indicate a cache hit.
26+
*/
27+
const KEYED_METHODS = new Set(['hasItem', 'getItem', 'getItemRaw', 'getItems']);
28+
2329
/**
2430
* Creates a Nitro plugin that instruments the storage driver.
2531
*/
@@ -74,7 +80,6 @@ function instrumentDriver(driver: MaybeInstrumentedDriver, mountBase: string): D
7480
'setItems',
7581
'removeItem',
7682
'getKeys',
77-
'getMeta',
7883
'clear',
7984
];
8085

@@ -86,7 +91,7 @@ function instrumentDriver(driver: MaybeInstrumentedDriver, mountBase: string): D
8691
}
8792

8893
// Replace with instrumented
89-
driver[methodName] = createMethodWrapper(original, methodName, driver.name ?? 'unknown', mountBase);
94+
driver[methodName] = createMethodWrapper(original, methodName, driver, mountBase);
9095
}
9196

9297
// Mark as instrumented
@@ -101,25 +106,31 @@ function instrumentDriver(driver: MaybeInstrumentedDriver, mountBase: string): D
101106
function createMethodWrapper(
102107
original: (...args: unknown[]) => unknown,
103108
methodName: string,
104-
driverName: string,
109+
driver: Driver,
105110
mountBase: string,
106111
): (...args: unknown[]) => unknown {
107112
return new Proxy(original, {
108113
async apply(target, thisArg, args) {
109-
const attributes = getSpanAttributes(methodName, driverName ?? 'unknown', mountBase);
114+
const attributes = getSpanAttributes(methodName, driver, mountBase, args);
110115

111-
debug.log(`[storage] Running method: "${methodName}" on driver: "${driverName}"`);
116+
debug.log(`[storage] Running method: "${methodName}" on driver: "${driver.name ?? 'unknown'}"`);
117+
118+
const spanName = KEYED_METHODS.has(methodName) ? String(args?.[0]) : `storage.${normalizeMethodName(methodName)}`;
112119

113120
return startSpan(
114121
{
115-
name: `storage.${methodName}`,
122+
name: spanName,
116123
attributes,
117124
},
118125
async span => {
119126
try {
120127
const result = await target.apply(thisArg, args);
121128
span.setStatus({ code: SPAN_STATUS_OK });
122129

130+
if (KEYED_METHODS.has(methodName)) {
131+
span.setAttribute(SEMANTIC_ATTRIBUTE_CACHE_HIT, true);
132+
}
133+
123134
return result;
124135
} catch (error) {
125136
span.setStatus({ code: SPAN_STATUS_ERROR, message: 'internal_error' });
@@ -161,15 +172,26 @@ function wrapStorageMount(storage: Storage): Storage['mount'] {
161172
/**
162173
* Gets the span attributes for the storage method.
163174
*/
164-
function getSpanAttributes(methodName: string, driverName: string, mountBase: string): SpanAttributes {
175+
function getSpanAttributes(methodName: string, driver: Driver, mountBase: string, args: unknown[]): SpanAttributes {
165176
const attributes: SpanAttributes = {
166-
[SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'app.storage.nuxt',
167-
[SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'custom',
168-
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.app.storage.nuxt',
177+
[SEMANTIC_ATTRIBUTE_SENTRY_OP]: `cache.${normalizeMethodName(methodName)}`,
178+
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.cache.nuxt',
169179
'nuxt.storage.op': methodName,
170-
'nuxt.storage.driver': driverName,
171180
'nuxt.storage.mount': mountBase,
181+
'nuxt.storage.driver': driver.name ?? 'unknown',
172182
};
173183

184+
// Add the key if it's a get/set/del call
185+
if (args?.[0] && typeof args[0] === 'string') {
186+
attributes[SEMANTIC_ATTRIBUTE_CACHE_KEY] = `${mountBase}${args[0]}`;
187+
}
188+
174189
return attributes;
175190
}
191+
192+
/**
193+
* Normalizes the method name to snake_case to be used in span names or op.
194+
*/
195+
function normalizeMethodName(methodName: string): string {
196+
return methodName.replace(/[A-Z]/g, letter => `_${letter.toLowerCase()}`);
197+
}

0 commit comments

Comments
 (0)