Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

minor: support @sentry/sveltekit routing instrumentation #98

Merged
6 commits merged into from
Oct 22, 2023
Merged

Conversation

jill64
Copy link
Owner

@jill64 jill64 commented Oct 22, 2023

close #97

Summary by CodeRabbit

  • New Feature: Introduced a module for instrumenting routing in a SvelteKit application with Sentry. This will provide more detailed insights into page load and navigation events.
  • New Feature: Added a function to initialize the Sentry SDK for Svelte applications in the browser. This will enhance error tracking and application monitoring capabilities.
  • Improvement: Updated the build configuration to treat $app/stores as an external dependency, improving the overall build process.
  • Improvement: Enhanced the BrowserOptions object with new functions for adding client integrations and applying SDK metadata. This will provide more customization options and better tracking of SDK usage.
  • Improvement: Introduced a function to switch the global fetch function to a proxy, improving the handling of network requests.

Please note, there are a couple of TypeScript errors that need to be addressed in the new switchToFetchProxy function.

@jill64 jill64 linked an issue Oct 22, 2023 that may be closed by this pull request
@ghost ghost enabled auto-merge October 22, 2023 01:20
@coderabbitai
Copy link

coderabbitai bot commented Oct 22, 2023

Walkthrough

The changes primarily focus on enhancing the Sentry SDK integration for Svelte applications. They introduce new functions to handle client integrations, apply SDK metadata, and manage the fetch function. The routing instrumentation for SvelteKit applications is also improved.

Changes

File Summary
packages/lib/scripts/build.ts Added $app/stores to the list of external dependencies in the build configuration.
packages/lib/src/client/addClientIntegrations.ts Introduced addClientIntegrations function to handle tracing integration.
packages/lib/src/client/applySdkMetadata.ts Added applySdkMetadata function to set SDK metadata.
packages/lib/src/client/init.ts Replaced Sentry.init with sentryInit for initializing the Sentry SDK.
packages/lib/src/client/restoreFetch.ts Exported restoreFetch function to manage the fetch function.
packages/lib/src/client/.../sentryInit.ts Introduced sentryInit function to initialize the Sentry SDK with custom options and configurations.
packages/lib/src/client/switchToFetchProxy.ts Added switchToFetchProxy function to switch the global fetch function to a proxy function.

🐇
"In the land of code, changes are afoot,
Sentry SDK, given a new suit.
With a hop, skip, and a jump,
We've cleared a major bump.
Celebrate, for our code is astute!" 🎉


Tips

Chat with CodeRabbit Bot (@coderabbitai)

  • If you reply to a review comment from CodeRabbit, the bot will automatically respond.
  • To engage with CodeRabbit bot directly around the specific lines of code in the PR, mention @coderabbitai in your review comment
  • Note: Review comments are made on code diffs or files, not on the PR overview.
  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.

CodeRabbit Commands (invoked as PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger a review. This is useful when automatic reviews are disabled for the repository.

Note: For conversation with the bot, please use the review comments on code diffs or files.

@cloudflare-workers-and-pages
Copy link

cloudflare-workers-and-pages bot commented Oct 22, 2023

Deploying with  Cloudflare Pages  Cloudflare Pages

Latest commit: 261b748
Status: ✅  Deploy successful!
Preview URL: https://a0489762.sentry-sveltekit-cloudflare.pages.dev
Branch Preview URL: https://issues-97.sentry-sveltekit-cloudflare.pages.dev

View logs

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review Status

Actionable comments generated: 4

Commits Files that changed from the base of the PR and between 6ab9e00 and 0df4485.
Files ignored due to filter (2)
  • package.json
  • pnpm-lock.yaml
Files selected for processing (8)
  • packages/lib/scripts/build.ts (1 hunks)
  • packages/lib/src/client/addClientIntegrations.ts (1 hunks)
  • packages/lib/src/client/applySdkMetadata.ts (1 hunks)
  • packages/lib/src/client/init.ts (2 hunks)
  • packages/lib/src/client/restoreFetch.ts (1 hunks)
  • packages/lib/src/client/router.ts (1 hunks)
  • packages/lib/src/client/sentryInit.ts (1 hunks)
  • packages/lib/src/client/switchToFetchProxy.ts (1 hunks)
Files skipped from review due to trivial changes (3)
  • packages/lib/scripts/build.ts
  • packages/lib/src/client/init.ts
  • packages/lib/src/client/router.ts
Additional comments (Suppressed): 1
packages/lib/src/client/restoreFetch.ts (1)
  • 1-11: The restoreFetch function is replacing the global fetch function with the original fetch function passed as an argument. This is a good practice to restore the original behavior after the Sentry SDK initialization. However, it's not clear why the fetch function is being stored in _sentryFetchProxy on line 7. If this is not used elsewhere, it might be unnecessary. Please verify.
-   globalWithSentryFetchProxy._sentryFetchProxy =
-     globalWithSentryFetchProxy.fetch
- 
    globalWithSentryFetchProxy.fetch = actualFetch

Comment on lines +1 to +24
import { hasTracingEnabled } from '@sentry/core'
import { BrowserOptions, BrowserTracing } from '@sentry/svelte'
import { addOrUpdateIntegration } from '@sentry/utils'
import { svelteKitRoutingInstrumentation } from './router.js'

export const addClientIntegrations = (options: BrowserOptions) => {
let integrations = options.integrations || []

if (hasTracingEnabled(options)) {
const defaultBrowserTracingIntegration = new BrowserTracing({
routingInstrumentation: svelteKitRoutingInstrumentation
})

integrations = addOrUpdateIntegration(
defaultBrowserTracingIntegration,
integrations,
{
'options.routingInstrumentation': svelteKitRoutingInstrumentation
}
)
}

options.integrations = integrations
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The function addClientIntegrations modifies the options object passed to it. This can lead to unexpected side effects if the caller is not aware of this behavior. Consider returning a new object with the updated integrations instead of modifying the input object. This would make the function pure and easier to reason about.

-   options.integrations = integrations
+   return { ...options, integrations };

Then, the caller can decide whether to replace the original options object or not.

Comment on lines +1 to +17
import { WINDOW } from '@sentry/svelte'

export function switchToFetchProxy() {
const globalWithSentryFetchProxy = WINDOW

const actualFetch = globalWithSentryFetchProxy.fetch

// @ts-expect-error TODO: fix this
if (globalWithSentryFetchProxy._sentryFetchProxy && actualFetch) {
globalWithSentryFetchProxy.fetch =
// @ts-expect-error TODO: fix this
globalWithSentryFetchProxy._sentryFetchProxy
return actualFetch
}

return undefined
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The function switchToFetchProxy switches the global fetch function to a Sentry proxy. However, it doesn't check if the _sentryFetchProxy is a function before assigning it to fetch. This could potentially break the application if _sentryFetchProxy is not a function. Consider adding a type check before the assignment.

- if (globalWithSentryFetchProxy._sentryFetchProxy && actualFetch) {
+ if (typeof globalWithSentryFetchProxy._sentryFetchProxy === 'function' && actualFetch) {

Also, the function returns undefined if the conditions are not met. This could lead to unexpected behavior in the calling code. Consider throwing an error or returning a default value instead.

Comment on lines +1 to +26
import { BrowserOptions, configureScope, init } from '@sentry/svelte'
import { addClientIntegrations } from './addClientIntegrations.js'
import { applySdkMetadata } from './applySdkMetadata.js'
import { restoreFetch } from './restoreFetch.js'
import { switchToFetchProxy } from './switchToFetchProxy.js'

export const sentryInit = (options: BrowserOptions) => {
applySdkMetadata(options, ['sveltekit', 'svelte'])

addClientIntegrations(options)

// 1. Switch window.fetch to our fetch proxy we injected earlier
const actualFetch = switchToFetchProxy()

// 2. Initialize the SDK which will instrument our proxy
init(options)

// 3. Restore the original fetch now that our proxy is instrumented
if (actualFetch) {
restoreFetch(actualFetch)
}

configureScope((scope) => {
scope.setTag('runtime', 'browser')
})
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The sentryInit function is well-structured and follows a clear sequence of steps for initializing Sentry with SvelteKit. However, there is a potential issue with the restoreFetch function. If switchToFetchProxy fails and returns null or undefined, restoreFetch will be called with an undefined argument. This could lead to unexpected behavior or errors. Consider adding error handling or a check to ensure actualFetch is a function before restoring it.

  // 3. Restore the original fetch now that our proxy is instrumented
  if (actualFetch && typeof actualFetch === 'function') {
    restoreFetch(actualFetch)
  }

Comment on lines +1 to +16
import { SDK_VERSION } from '@sentry/core'
import { BrowserOptions } from '@sentry/svelte'

const PACKAGE_NAME_PREFIX = 'npm:@sentry/'

export const applySdkMetadata = (options: BrowserOptions, names: string[]) => {
options._metadata = options._metadata || {}
options._metadata.sdk = options._metadata.sdk || {
name: 'sentry.javascript.sveltekit',
packages: names.map((name) => ({
name: `${PACKAGE_NAME_PREFIX}${name}`,
version: SDK_VERSION
})),
version: SDK_VERSION
}
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The function applySdkMetadata modifies the options object passed to it. This is a side effect that could lead to unexpected behavior if the caller is not aware of it. Consider returning a new object instead of modifying the existing one. This would make the function pure and easier to reason about.

- export const applySdkMetadata = (options: BrowserOptions, names: string[]) => {
-   options._metadata = options._metadata || {}
-   options._metadata.sdk = options._metadata.sdk || {
-     name: 'sentry.javascript.sveltekit',
-     packages: names.map((name) => ({
-       name: `${PACKAGE_NAME_PREFIX}${name}`,
-       version: SDK_VERSION
-     })),
-     version: SDK_VERSION
-   }
- }
+ export const applySdkMetadata = (options: BrowserOptions, names: string[]): BrowserOptions => {
+   const newOptions = { ...options };
+   newOptions._metadata = newOptions._metadata || {}
+   newOptions._metadata.sdk = newOptions._metadata.sdk || {
+     name: 'sentry.javascript.sveltekit',
+     packages: names.map((name) => ({
+       name: `${PACKAGE_NAME_PREFIX}${name}`,
+       version: SDK_VERSION
+     })),
+     version: SDK_VERSION
+   }
+   return newOptions;
+ }

@ghost ghost merged commit a65c2c9 into main Oct 22, 2023
6 checks passed
@ghost ghost deleted the issues-97 branch October 22, 2023 01:21
This pull request was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support SvelteKit routing instrumentation to BrowserTracing
1 participant