Skip to content

Commit d3062cb

Browse files
Add Sentry env vars and refactor Sentry init (#2584)
Co-authored-by: Ariel Weinberger <Weinberger.Ariel@gmail.com>
1 parent 029007d commit d3062cb

File tree

8 files changed

+95
-18
lines changed

8 files changed

+95
-18
lines changed

Dockerfile

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,16 @@ ARG PUBLIC_CONSOLE_MOCK_AI_SUGGESTIONS
3131
ARG PUBLIC_APPWRITE_ENDPOINT
3232
ARG PUBLIC_GROWTH_ENDPOINT
3333
ARG PUBLIC_STRIPE_KEY
34+
ARG PUBLIC_SENTRY_DSN
35+
ARG PUBLIC_SENTRY_INCLUDE_PII
36+
ARG PUBLIC_SENTRY_ENVIRONMENT
37+
ARG PUBLIC_SENTRY_TRACES_SAMPLE_RATE
38+
ARG PUBLIC_SENTRY_REPLAY_SAMPLE_RATE
39+
ARG PUBLIC_SENTRY_DEBUG
3440
ARG SENTRY_AUTH_TOKEN
3541
ARG SENTRY_RELEASE
3642

43+
3744
ENV PUBLIC_APPWRITE_ENDPOINT=$PUBLIC_APPWRITE_ENDPOINT
3845
ENV PUBLIC_GROWTH_ENDPOINT=$PUBLIC_GROWTH_ENDPOINT
3946
ENV PUBLIC_CONSOLE_MODE=$PUBLIC_CONSOLE_MODE
@@ -44,6 +51,12 @@ ENV PUBLIC_APPWRITE_MULTI_REGION=$PUBLIC_APPWRITE_MULTI_REGION
4451
ENV PUBLIC_CONSOLE_EMAIL_VERIFICATION=$PUBLIC_CONSOLE_EMAIL_VERIFICATION
4552
ENV PUBLIC_CONSOLE_MOCK_AI_SUGGESTIONS=$PUBLIC_CONSOLE_MOCK_AI_SUGGESTIONS
4653
ENV PUBLIC_STRIPE_KEY=$PUBLIC_STRIPE_KEY
54+
ENV PUBLIC_SENTRY_DSN=$PUBLIC_SENTRY_DSN
55+
ENV PUBLIC_SENTRY_INCLUDE_PII=$PUBLIC_SENTRY_INCLUDE_PII
56+
ENV PUBLIC_SENTRY_ENVIRONMENT=$PUBLIC_SENTRY_ENVIRONMENT
57+
ENV PUBLIC_SENTRY_TRACES_SAMPLE_RATE=$PUBLIC_SENTRY_TRACES_SAMPLE_RATE
58+
ENV PUBLIC_SENTRY_REPLAY_SAMPLE_RATE=$PUBLIC_SENTRY_REPLAY_SAMPLE_RATE
59+
ENV PUBLIC_SENTRY_DEBUG=$PUBLIC_SENTRY_DEBUG
4760
ENV SENTRY_AUTH_TOKEN=$SENTRY_AUTH_TOKEN
4861
ENV SENTRY_RELEASE=$SENTRY_RELEASE
4962
ENV PUBLIC_IMAGINE_CDN_URL=$PUBLIC_IMAGINE_CDN_URL

src/hooks.client.ts

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,15 @@
1-
import * as Sentry from '@sentry/sveltekit';
2-
import { isCloud, isProd } from '$lib/system';
31
import { AppwriteException } from '@appwrite.io/console';
42
import type { HandleClientError } from '@sveltejs/kit';
3+
import { setupSentry } from '$lib/sentry';
54

6-
Sentry.init({
7-
enabled: isCloud && isProd,
8-
dsn: 'https://c7ce178bdedd486480317b72f282fd39@o1063647.ingest.us.sentry.io/4504158071422976',
9-
tracesSampleRate: 1,
10-
replaysSessionSampleRate: 0,
11-
replaysOnErrorSampleRate: 0
5+
setupSentry({
6+
withSessionReplay: true
127
});
138

149
export const handleError: HandleClientError = ({ error, message, status }) => {
1510
console.error(error);
1611

17-
let type;
12+
let type: string;
1813
if (error instanceof AppwriteException) {
1914
status = error.code === 0 ? undefined : error.code;
2015
message = error.message;

src/hooks.server.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,9 @@
11
import { sequence } from '@sveltejs/kit/hooks';
22
import { handleErrorWithSentry, sentryHandle } from '@sentry/sveltekit';
3-
import * as Sentry from '@sentry/sveltekit';
4-
import { isCloud, isProd } from '$lib/system';
3+
import { setupSentry } from '$lib/sentry';
54

6-
Sentry.init({
7-
enabled: isCloud && isProd,
8-
dsn: 'https://c7ce178bdedd486480317b72f282fd39@o1063647.ingest.us.sentry.io/4504158071422976',
9-
tracesSampleRate: 1.0
5+
setupSentry({
6+
withSessionReplay: false
107
});
118

129
export const handle = sequence(sentryHandle());

src/lib/sentry.ts

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import { env } from '$env/dynamic/public';
2+
import * as Sentry from '@sentry/sveltekit';
3+
import { isCloud } from './system';
4+
5+
const timestamp = Date.now();
6+
7+
export function getSessionId(userId: string) {
8+
return `${userId}-${timestamp}`;
9+
}
10+
11+
export function identify(userId: string) {
12+
if (isCloud) {
13+
Sentry.setContext('Imagine Request Context', {
14+
session_id: getSessionId(userId)
15+
});
16+
Sentry.setUser({
17+
id: userId
18+
});
19+
}
20+
}
21+
22+
export function setupSentry({ withSessionReplay }: { withSessionReplay: boolean }) {
23+
const dsn = env.PUBLIC_SENTRY_DSN;
24+
const environment = env.PUBLIC_SENTRY_ENVIRONMENT;
25+
26+
if (!dsn) {
27+
return;
28+
}
29+
30+
if (dsn && !environment) {
31+
throw new Error(
32+
"PUBLIC_SENTRY_ENVIRONMENT is required when PUBLIC_SENTRY_DSN is set. For local development, set it to your name, e.g. 'torsten'."
33+
);
34+
}
35+
36+
const variables = {
37+
enabled: true,
38+
includePII: env.PUBLIC_SENTRY_INCLUDE_PII === 'true',
39+
tracesSampleRate: parseFloat(env.PUBLIC_SENTRY_TRACES_SAMPLE_RATE),
40+
replaysSessionSampleRate: parseFloat(env.PUBLIC_SENTRY_REPLAY_SAMPLE_RATE),
41+
debug: env.PUBLIC_SENTRY_DEBUG === 'true'
42+
};
43+
44+
const integrations = [];
45+
if (withSessionReplay) {
46+
integrations.push(
47+
Sentry.replayIntegration({
48+
maskAllText: variables.includePII ? false : true,
49+
maskAllInputs: variables.includePII ? false : true
50+
})
51+
);
52+
}
53+
54+
Sentry.init({
55+
enabled: variables.enabled,
56+
dsn,
57+
tracesSampleRate: variables.tracesSampleRate,
58+
replaysSessionSampleRate: variables.replaysSessionSampleRate,
59+
replaysOnErrorSampleRate: 1,
60+
integrations,
61+
debug: variables.debug,
62+
sendDefaultPii: true
63+
});
64+
}

src/lib/studio/studio-widget.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { goto } from '$app/navigation';
55
import { resolve } from '$app/paths';
66
import { ensureMonacoStyles } from './monaco-style-manager';
77
import DEV_CSS_URL from '@imagine.dev/web-components/imagine-web-components.css?url';
8+
import { getSessionId } from '$lib/sentry';
89

910
const COMPONENT_SELECTOR = 'imagine-web-components-wrapper[data-appwrite-studio]';
1011
const STYLE_ATTRIBUTE = 'data-appwrite-studio-style';
@@ -273,6 +274,7 @@ export function hideStudio() {
273274
export async function initImagine(
274275
region: string,
275276
projectId: string,
277+
userId: string,
276278
callbacks?: {
277279
onProjectNameChange: () => void;
278280
onAddDomain: () => void | Promise<void>;
@@ -291,6 +293,7 @@ export async function initImagine(
291293
},
292294
{
293295
initialTheme: get(app).themeInUse,
296+
consoleSessionId: getSessionId(userId),
294297
callbacks
295298
}
296299
);

src/lib/studio/studio.svelte

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,12 @@
1818
1919
const {
2020
region,
21-
projectId
21+
projectId,
22+
userId
2223
}: {
2324
region: string;
2425
projectId: string;
26+
userId: string;
2527
} = $props();
2628
2729
const siteId = `project-${projectId}`;
@@ -31,7 +33,7 @@
3133
onMount(() => {
3234
ensureStudioComponent();
3335
34-
initImagine(region, projectId, {
36+
initImagine(region, projectId, userId, {
3537
onProjectNameChange: () => {
3638
invalidate(Dependencies.PROJECT);
3739
},

src/routes/(console)/+layout.svelte

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -333,7 +333,7 @@
333333
});
334334
</script>
335335

336-
<Studio region={page.params.region} projectId={page.params.project} />
336+
<Studio region={page.params.region} projectId={page.params.project} userId={data.account.$id} />
337337
<CommandCenter />
338338
<Shell
339339
showSideNavigation={page.url.pathname !== '/' &&

src/routes/+layout.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import type { Account } from '$lib/stores/user';
1111
import { type AppwriteException, Query } from '@appwrite.io/console';
1212
import { isCloud, VARS } from '$lib/system';
1313
import { checkPricingRefAndRedirect } from '$lib/helpers/pricingRedirect';
14+
import { identify } from '$lib/sentry';
1415
import { resolvedProfile } from '$lib/profiles/index.svelte';
1516

1617
export const ssr = false;
@@ -24,6 +25,8 @@ export const load: LayoutLoad = async ({ depends, url, route }) => {
2425
.then((response) => [response, null])
2526
.catch((error) => [null, error])) as [Account, AppwriteException];
2627

28+
if (account) identify(account.$id);
29+
2730
if (url.searchParams.has('forceRedirect')) {
2831
redirectTo.set(url.searchParams.get('forceRedirect') || null);
2932
url.searchParams.delete('forceRedirect');

0 commit comments

Comments
 (0)