-
-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Expand file tree
/
Copy pathwithServerActionInstrumentation.ts
More file actions
64 lines (59 loc) · 2.23 KB
/
withServerActionInstrumentation.ts
File metadata and controls
64 lines (59 loc) · 2.23 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
import {
flushIfServerless,
handleCallbackErrors,
SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,
SPAN_STATUS_ERROR,
} from '@sentry/core';
import { captureException, getActiveSpan, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, spanToJSON, startSpan } from '@sentry/node';
import { isRedirect } from './utils';
/**
* Wraps a server action (functions that use the 'use server' directive)
* function body with Sentry Error and Performance instrumentation.
*/
export async function withServerActionInstrumentation<A extends (...args: unknown[]) => unknown>(
serverActionName: string,
callback: A,
): Promise<ReturnType<A>> {
const activeSpan = getActiveSpan();
if (activeSpan) {
const spanData = spanToJSON(activeSpan).data;
// In solid start, server function calls are made to `/_server` which doesn't tell us
// a lot. We rewrite the span's route to be that of the sever action name but only
// if the target is `/_server`, otherwise we'd overwrite pageloads on routes that use
// server actions (which are more meaningful, e.g. a request to `GET /users/5` is more
// meaningful than overwriting it with `GET doSomeFunctionCall`).
if (spanData && !spanData['http.route'] && spanData['http.target'] === '/_server') {
activeSpan.setAttribute('http.route', serverActionName);
activeSpan.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, 'component');
}
}
try {
return await startSpan(
{
op: 'function.server_action',
name: serverActionName,
attributes: {
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.function.solidstart',
[SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'component',
},
},
async span => {
// oxlint-disable-next-line typescript/await-thenable -- callback may be async at runtime
const result = await handleCallbackErrors(callback, error => {
if (!isRedirect(error)) {
span.setStatus({ code: SPAN_STATUS_ERROR, message: 'internal_error' });
captureException(error, {
mechanism: {
handled: false,
type: 'auto.function.solidstart',
},
});
}
});
return result;
},
);
} finally {
await flushIfServerless();
}
}