Skip to content

Commit

Permalink
feat(sveltekit): Add performance monitoring for server load
Browse files Browse the repository at this point in the history
  • Loading branch information
AbhiPrasad committed Mar 20, 2023
1 parent 4434d60 commit 4a4f9e9
Showing 1 changed file with 80 additions and 14 deletions.
94 changes: 80 additions & 14 deletions packages/sveltekit/src/server/load.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
import { captureException } from '@sentry/node';
import { addExceptionMechanism, isThenable, objectify } from '@sentry/utils';
/* eslint-disable @sentry-internal/sdk/no-optional-chaining */
import type { Span } from '@sentry/core';
import { captureException, getCurrentHub } from '@sentry/node';
import {
addExceptionMechanism,
baggageHeaderToDynamicSamplingContext,
extractTraceparentData,
isThenable,
objectify,
} from '@sentry/utils';
import type { HttpError, ServerLoad } from '@sveltejs/kit';
import * as domain from 'domain';

function isHttpError(err: unknown): err is HttpError {
return typeof err === 'object' && err !== null && 'status' in err && 'body' in err;
Expand Down Expand Up @@ -36,6 +45,10 @@ function sendErrorToSentry(e: unknown): unknown {
return objectifiedErr;
}

function setSpan(span: Span | undefined): void {
getCurrentHub().getScope()?.setSpan(span);
}

/**
* Wrap load function with Sentry
*
Expand All @@ -44,21 +57,74 @@ function sendErrorToSentry(e: unknown): unknown {
export function wrapLoadWithSentry(origLoad: ServerLoad): ServerLoad {
return new Proxy(origLoad, {
apply: (wrappingTarget, thisArg, args: Parameters<ServerLoad>) => {
let maybePromiseResult;
return domain.create().bind(() => {
let maybePromiseResult;

const [event] = args;
const hub = getCurrentHub();
const scope = hub.getScope();

const parentSpan = scope?.getSpan();

let activeSpan: Span | undefined = undefined;

function finishActiveSpan(): void {
activeSpan?.finish();
setSpan(parentSpan);
}

if (parentSpan) {
activeSpan = parentSpan.startChild({
op: 'function.sveltekit.load',
description: event.route.id || 'load',
status: 'ok',
});
} else {
const sentryTraceHeader = event.request.headers.get('sentry-trace');
const baggageHeader = event.request.headers.get('baggage');
const traceparentData = sentryTraceHeader ? extractTraceparentData(sentryTraceHeader) : undefined;
const dynamicSamplingContext = baggageHeaderToDynamicSamplingContext(baggageHeader);

activeSpan = hub.startTransaction({
op: 'function.sveltekit.load',
name: event.route.id || 'load',
status: 'ok',
...traceparentData,
metadata: {
source: 'route',
dynamicSamplingContext: traceparentData && !dynamicSamplingContext ? {} : dynamicSamplingContext,
},
});
}

setSpan(activeSpan);

try {
maybePromiseResult = wrappingTarget.apply(thisArg, args);
} catch (e) {
throw sendErrorToSentry(e);
}
try {
maybePromiseResult = wrappingTarget.apply(thisArg, args);
} catch (e) {
activeSpan?.setStatus('internal_error');
const sentryError = sendErrorToSentry(e);
finishActiveSpan();
throw sentryError;
}

if (isThenable(maybePromiseResult)) {
Promise.resolve(maybePromiseResult).then(null, e => {
sendErrorToSentry(e);
});
}
if (isThenable(maybePromiseResult)) {
Promise.resolve(maybePromiseResult).then(
() => {
finishActiveSpan();
},
e => {
activeSpan?.setStatus('internal_error');
sendErrorToSentry(e);
finishActiveSpan();
},
);
} else {
finishActiveSpan();
}

return maybePromiseResult;
return maybePromiseResult;
})();
},
});
}

0 comments on commit 4a4f9e9

Please sign in to comment.