From 47c2fabbe43f8d84317b91e391a88f4312811abc Mon Sep 17 00:00:00 2001 From: Francesco Novy Date: Wed, 19 Jun 2024 14:18:17 +0200 Subject: [PATCH 1/5] docs: Add docs about creating a new SDK --- docs/creating-a-new-sdk.md | 104 +++++++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 docs/creating-a-new-sdk.md diff --git a/docs/creating-a-new-sdk.md b/docs/creating-a-new-sdk.md new file mode 100644 index 000000000000..16baba029bc5 --- /dev/null +++ b/docs/creating-a-new-sdk.md @@ -0,0 +1,104 @@ +# Creating a new SDK + +While each SDK (e.g. `@sentry/react` or `@sentry/nextjs`) is somewhat unique, we try to follow some general themes when +creating a new SDK. + +## Types of SDKs + +Broadly speaking, there are three types of SDKs: + +1. Browser SDKs (e.g. `@sentry/react` or `@sentry/angular`) +2. Server SDKs (e.g. `@sentry/bun` or `@sentry/node`) +3. Meta SDKs (e.g. `@sentry/nextjs` or `@sentry/sveltekit`) - which cover both Browser & Server + +Depending on what type of SDK you are creating, you'll have to include different things. + +## General Guidelines + +As a rule of thumb, we should follow these two ideas: + +a. Whenever possible, instrumentation should work without (or with as little as possible) user configuration. b. +Instrumentation should follow common patterns for a specific platform. No config is always preferred, but if config is +unavoidable, it should feel reasonable to users of the given framework. + +## 1. Browser SDKs + +A purely browser SDK generally should cover the following things: + +### 1a. Routing Instrumentation + +While we have a default `browserTracingIntegration`, this has no access to a router, and is thus only based on URLs. We +should strive to provide a custom `browserTracingIntegration` for SDKs that can leverage the router & routing +information. + +Ideally, this means that we can emit pageload & navigation spans with parametrized route names instead of full URLs. + +### 1b. Error Capturing + +We have global error handlers out of the box. However, in many frameworks there are ways for users to capture errors +too, which may lead to them not bubble up to our global handlers. Generally, the goal is that all errors are captured by +Sentry. + +Either we should use some hook (e.g. `app.on('error')`) to capture exceptions, or provide composables (e.g. an error +boundary component in React) that users can use in their app to ensure all errors are captured by Sentry. + +### 1c. OPTIONAL: Component Tracking + +Optionally, we may also track component renders and similar things. These are stretch goals, though, and do not need to +be part of an MVP. + +## 2. Server SDKs + +A purely server SDK generally should cover the following things: + +### 2a. `http.server` spans with route information + +Most SDKs that build on top of `@sentry/node` should automatically have basic `http.server` spans emitted by +`httpIntegration`. However, these spans do not contain any routing information (e.g. a `http.route` attribute). A server +SDK should make sure to add route information to these spans. + +If there are things that should be captured in spans that are not covered by `httpIntegration`, we may need to write our +own instrumentation to capture `http.server` spans. + +### 2b. Error Capturing + +We have global error handlers out of the box. However, in many frameworks there are ways for users to capture errors +too, which may lead to them not bubble up to our global handlers. Generally, the goal is that all errors are captured by +Sentry. + +Either we should use some hook (e.g. `app.on('error')`) to capture exceptions, or provide composables (e.g. +`setupFastifyErrorHandler(app)`) that user can call. + +### 2c. OPTIONAL: Middleware Tracking + +If possible, we may want to instrument middlewares, and create spans for them. + +### 2d. OPTIONAL: Additional features + +We may also want to instrument additional features, if applicable, including: + +- Crons +- Cache module + +## 3. Meta SDKs + +Meta SDKs should contain both the things pointed out in 1. and 2, _PLUS_: + +### 3a. Connected Traces + +Traces from SSR (server side) should be continued in the client side (browser). Usually this means that we have to +inject the trace data as `` tags into the rendered HTML pages. If possible, we should do that automatically. If +there is no way to do that automatically, we should provide a utility for users to do it themselves. + +### 3b. Instrumented Server Components / API Routes / etc. + +Depending on the framework, we should instrument all the pieces that exist in this framework. This includes capturing +errors & spans for things like: + +- Server Components +- API Routes +- Layouts +- etc. + +When possible, we should auto-capture this. If not possible, we should provide utilities for users to do this +themselves. From 0d74f56d7d2bbe044cecbff80c73162a900c07dc Mon Sep 17 00:00:00 2001 From: Francesco Novy Date: Wed, 19 Jun 2024 17:00:15 +0200 Subject: [PATCH 2/5] Apply suggestions from code review Co-authored-by: Luca Forstner --- docs/creating-a-new-sdk.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/creating-a-new-sdk.md b/docs/creating-a-new-sdk.md index 16baba029bc5..c13d04a49533 100644 --- a/docs/creating-a-new-sdk.md +++ b/docs/creating-a-new-sdk.md @@ -44,7 +44,7 @@ boundary component in React) that users can use in their app to ensure all error ### 1c. OPTIONAL: Component Tracking -Optionally, we may also track component renders and similar things. These are stretch goals, though, and do not need to +Optionally, we may also track the duration of component renders and similar things. These are stretch goals, though, and do not need to be part of an MVP. ## 2. Server SDKs @@ -53,7 +53,7 @@ A purely server SDK generally should cover the following things: ### 2a. `http.server` spans with route information -Most SDKs that build on top of `@sentry/node` should automatically have basic `http.server` spans emitted by +Most SDKs that build on top of `@sentry/node` should automatically have basic `http.server` spans emitted for incoming requests by the `httpIntegration`. However, these spans do not contain any routing information (e.g. a `http.route` attribute). A server SDK should make sure to add route information to these spans. From 5e26fc8e2844cfdc34e723fa23640ddbe7743083 Mon Sep 17 00:00:00 2001 From: Francesco Novy Date: Tue, 25 Jun 2024 13:58:55 +0200 Subject: [PATCH 3/5] adjustments --- docs/creating-a-new-sdk.md | 100 ++++++++++++++++++++++++++----------- 1 file changed, 71 insertions(+), 29 deletions(-) diff --git a/docs/creating-a-new-sdk.md b/docs/creating-a-new-sdk.md index c13d04a49533..79176baaa63a 100644 --- a/docs/creating-a-new-sdk.md +++ b/docs/creating-a-new-sdk.md @@ -17,23 +17,15 @@ Depending on what type of SDK you are creating, you'll have to include different As a rule of thumb, we should follow these two ideas: -a. Whenever possible, instrumentation should work without (or with as little as possible) user configuration. b. -Instrumentation should follow common patterns for a specific platform. No config is always preferred, but if config is -unavoidable, it should feel reasonable to users of the given framework. +1. Whenever possible, instrumentation should work without (or with as little as possible) user configuration. +2. Instrumentation should follow common patterns for a specific platform. No config is always preferred, but if config + is unavoidable, it should feel as native as possible to users of the given framework. ## 1. Browser SDKs A purely browser SDK generally should cover the following things: -### 1a. Routing Instrumentation - -While we have a default `browserTracingIntegration`, this has no access to a router, and is thus only based on URLs. We -should strive to provide a custom `browserTracingIntegration` for SDKs that can leverage the router & routing -information. - -Ideally, this means that we can emit pageload & navigation spans with parametrized route names instead of full URLs. - -### 1b. Error Capturing +### 1a. Error Monitoring We have global error handlers out of the box. However, in many frameworks there are ways for users to capture errors too, which may lead to them not bubble up to our global handlers. Generally, the goal is that all errors are captured by @@ -42,25 +34,36 @@ Sentry. Either we should use some hook (e.g. `app.on('error')`) to capture exceptions, or provide composables (e.g. an error boundary component in React) that users can use in their app to ensure all errors are captured by Sentry. -### 1c. OPTIONAL: Component Tracking +### 1b. Performance Monitoring -Optionally, we may also track the duration of component renders and similar things. These are stretch goals, though, and do not need to -be part of an MVP. +#### Routing Instrumentation -## 2. Server SDKs +At a minimum, each browser SDK should have **Routing Instrumentation**. -A purely server SDK generally should cover the following things: +While we have a default `browserTracingIntegration`, this has no access to a router, and is thus only based on URLs. We +should strive to provide a custom `browserTracingIntegration` for SDKs that can leverage the router & routing +information. -### 2a. `http.server` spans with route information +Ideally, this means that we can emit pageload & navigation spans with parametrized route names instead of full URLs. -Most SDKs that build on top of `@sentry/node` should automatically have basic `http.server` spans emitted for incoming requests by the -`httpIntegration`. However, these spans do not contain any routing information (e.g. a `http.route` attribute). A server -SDK should make sure to add route information to these spans. +Some of the following concepts may be relevant to your SDK: -If there are things that should be captured in spans that are not covered by `httpIntegration`, we may need to write our -own instrumentation to capture `http.server` spans. +- **Redirects**: If possible, we want to skip redirects. This means that if a user navigates to `/`, and this redirects + the user internally to `/dashboard`, we only want to capture a single `/` navigation/pageload. +- **Route Params**: Routes should be parametrized, which means that instead of `/users/123` we want to capture + `/users/:id` or simmilar. +- **Query Params**: Query params should generally be removed from the route. + +#### Component Tracking -### 2b. Error Capturing +Additionally, depending on the framework we may also have **Component Tracking**. We may track the duration of component +renders and similar things. These are stretch goals, though, and do not need to be part of an MVP. + +## 2. Server SDKs + +A purely server SDK generally should cover the following things: + +### 2a. Error Monitoring We have global error handlers out of the box. However, in many frameworks there are ways for users to capture errors too, which may lead to them not bubble up to our global handlers. Generally, the goal is that all errors are captured by @@ -69,16 +72,39 @@ Sentry. Either we should use some hook (e.g. `app.on('error')`) to capture exceptions, or provide composables (e.g. `setupFastifyErrorHandler(app)`) that user can call. -### 2c. OPTIONAL: Middleware Tracking +### 2b. Performance Monitoring + +#### Routing Instrumentation + +At a minimum, each Node SDK should have **Routing Instrumentation**. + +Most SDKs that build on top of `@sentry/node` should automatically have basic `http.server` spans emitted for incoming +requests by the `httpIntegration`. However, these spans do not contain any routing information (e.g. a `http.route` +attribute). A server SDK should make sure to add route information to these spans. + +If there are things that should be captured in spans that are not covered by `httpIntegration`, we may need to write our +own instrumentation to capture `http.server` spans. -If possible, we may want to instrument middlewares, and create spans for them. +Some of the following concepts may be relevant to your SDK: -### 2d. OPTIONAL: Additional features +- **Route Params**: Routes should be parametrized, which means that instead of `/users/123` we want to capture + `/users/:id` or simmilar. +- **Query Params**: Query params should generally be removed from the route. + +#### Middleware Tracking + +Additionally, Node SDKs may also **Middleware Tracking**. If possible, we may want to instrument middlewares, and create +spans for them. These are stretch goals, though, and do not need to be part of an MVP. + +### 2c. OPTIONAL: Additional features We may also want to instrument additional features, if applicable, including: -- Crons -- Cache module +- Automatic cron instrumentation +- [Cache module](https://docs.sentry.io/product/insights/caches/) - See + [Instrument Caches](https://docs.sentry.io/platforms/javascript/guides/connect/tracing/instrumentation/custom-instrumentation/caches-module/) +- [Queue module](https://docs.sentry.io/product/insights/queue-monitoring/) - See + [Instrument Queues](https://docs.sentry.io/platforms/javascript/guides/connect/tracing/instrumentation/custom-instrumentation/queues-module/) ## 3. Meta SDKs @@ -102,3 +128,19 @@ errors & spans for things like: When possible, we should auto-capture this. If not possible, we should provide utilities for users to do this themselves. + +### 3c. Bundler Integration / Source Maps + +When possible, Meta SDKs should integrate with the used bundler. For example, SvelteKit uses Vite, so we should +automatically set up `@sentry/vite-plugin` for the user. At a minimum, we want to enable source maps upload for the meta +SDK, but this may also include automated release creation and other bundler features. + +We _should not_ expose the bundler plugin config directly, because this means that we cannot bump the underlying bundler +plugin version in a major way (because the bundler plugin config becomes public API of the meta SDK). Instead, we should +provide an abstraction layer of options that we expose on top of that. + +### 3d. Alternate JS Runtimes + +We generally want to support Node runtimes for the server. However, sometimes there may be alternate runtimes that may +be supported, e.g. Cloudflare Workers or Vercel Edge Functions. We generally do not need to support these in an MVP, but +may decide to support them later. From 6aa5fb139cea93fd3961bdca793a25568161b91e Mon Sep 17 00:00:00 2001 From: Francesco Novy Date: Tue, 25 Jun 2024 16:19:23 +0200 Subject: [PATCH 4/5] Apply suggestions from code review Co-authored-by: Andrei <168741329+andreiborza@users.noreply.github.com> --- docs/creating-a-new-sdk.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/creating-a-new-sdk.md b/docs/creating-a-new-sdk.md index 79176baaa63a..27625fc72622 100644 --- a/docs/creating-a-new-sdk.md +++ b/docs/creating-a-new-sdk.md @@ -66,7 +66,7 @@ A purely server SDK generally should cover the following things: ### 2a. Error Monitoring We have global error handlers out of the box. However, in many frameworks there are ways for users to capture errors -too, which may lead to them not bubble up to our global handlers. Generally, the goal is that all errors are captured by +too, which may lead to them not bubbling up to our global handlers. Generally, the goal is that all errors are captured by Sentry. Either we should use some hook (e.g. `app.on('error')`) to capture exceptions, or provide composables (e.g. @@ -93,7 +93,7 @@ Some of the following concepts may be relevant to your SDK: #### Middleware Tracking -Additionally, Node SDKs may also **Middleware Tracking**. If possible, we may want to instrument middlewares, and create +Additionally, Node SDKs may also do **Middleware Tracking**. If possible, we may want to instrument middlewares, and create spans for them. These are stretch goals, though, and do not need to be part of an MVP. ### 2c. OPTIONAL: Additional features From f7c4bd720c550e23b081c08fc7e820af5c1e5e6c Mon Sep 17 00:00:00 2001 From: Francesco Novy Date: Thu, 27 Jun 2024 09:34:53 +0200 Subject: [PATCH 5/5] fix prettier --- docs/creating-a-new-sdk.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/creating-a-new-sdk.md b/docs/creating-a-new-sdk.md index 27625fc72622..f33a33170dc4 100644 --- a/docs/creating-a-new-sdk.md +++ b/docs/creating-a-new-sdk.md @@ -66,8 +66,8 @@ A purely server SDK generally should cover the following things: ### 2a. Error Monitoring We have global error handlers out of the box. However, in many frameworks there are ways for users to capture errors -too, which may lead to them not bubbling up to our global handlers. Generally, the goal is that all errors are captured by -Sentry. +too, which may lead to them not bubbling up to our global handlers. Generally, the goal is that all errors are captured +by Sentry. Either we should use some hook (e.g. `app.on('error')`) to capture exceptions, or provide composables (e.g. `setupFastifyErrorHandler(app)`) that user can call. @@ -93,8 +93,8 @@ Some of the following concepts may be relevant to your SDK: #### Middleware Tracking -Additionally, Node SDKs may also do **Middleware Tracking**. If possible, we may want to instrument middlewares, and create -spans for them. These are stretch goals, though, and do not need to be part of an MVP. +Additionally, Node SDKs may also do **Middleware Tracking**. If possible, we may want to instrument middlewares, and +create spans for them. These are stretch goals, though, and do not need to be part of an MVP. ### 2c. OPTIONAL: Additional features