diff --git a/develop-docs/sdk/foundations/index.mdx b/develop-docs/sdk/foundations/index.mdx new file mode 100644 index 00000000000000..199ca91aeb4653 --- /dev/null +++ b/develop-docs/sdk/foundations/index.mdx @@ -0,0 +1,9 @@ +--- +title: Foundations +description: Core concepts and infrastructure that every SDK builds on - transport protocol, data model, contexts, scopes, and attributes. +sidebar_order: 2 +--- + +The building blocks every SDK depends on. Understand how SDKs communicate with Sentry and the data structures they share. + + diff --git a/develop-docs/sdk/foundations/overview.mdx b/develop-docs/sdk/foundations/overview.mdx new file mode 100644 index 00000000000000..e2ad968efbe5af --- /dev/null +++ b/develop-docs/sdk/foundations/overview.mdx @@ -0,0 +1,91 @@ +--- +title: Overview +description: What an SDK is, what it does, and how end-users interact with it. +sidebar_order: 1 +--- + +## Writing an SDK + +At its core an SDK is a set of utilities for capturing data about an exceptional state in an application. Given this data, it then builds and sends a JSON payload to the Sentry server. + +The following items are expected of production-ready SDKs: + +- DSN configuration +- Graceful failures (e.g. Sentry server is unreachable) +- Setting attributes (e.g. tags and extra data) +- Support for Linux, Windows and OS X (where applicable) + +Feature based support is required for the following: + +- If cookie data is available, it's not sent by default +- If POST data is available, it's not sent by default + +Additionally, the following features are highly encouraged: + +- Automated error capturing (e.g. uncaught exception handlers) +- Logging framework integration +- Non-blocking event submission +- Context data helpers (e.g. setting the current user, recording breadcrumbs) +- Event sampling +- Honor Sentry's [Rate Limiting](/sdk/foundations/transport/rate-limiting/) HTTP headers +- Pre and Post event send hooks +- Local variable values in stack trace (on platforms where this is possible) +- Send an `environment` on each event. If none was detected or set by the user, `production` should be used. + +Please see the expected features page for descriptions of commonly Sentry SDK features. + +## Usage for End-users + +Generally, using an SDK consists of three steps for the end user, which should look almost identical no matter the language: + +1. Initialization of the SDK (sometimes this is hidden from the user): + + ```javascript + Sentry.init({dsn: '___PROJECT.DSN___'}); + ``` + + ```python + sentry_sdk.init('___PROJECT.DSN___') + ``` + +2. Capturing an event: + + ```javascript + var resultId = Sentry.captureException(myException); + ``` + + ```python + result_id = sentry_sdk.capture_exception(my_exception); + ``` + +3. Using the result of an event capture: + + ```javascript + alert(`Your exception was recorded as ${resultId}`); + ``` + + ```python + print('Your exception was recorded as %s', result_id); + ``` + +`init` ideally allows several configuration methods. The first argument should always be the DSN value (if possible): + +```javascript +Sentry.init({ + 'dsn': '___PROJECT.DSN___', + 'foo': 'bar' +}) +``` + + +SDKs should accept an empty DSN as valid configuration. + +If an SDK is not initialized or if it is initialized with an empty DSN, the SDK should not send any data over the network, such as captured exceptions. +Depending on the platform, the SDK may avoid performing unnecessary initialization work and reduce its runtime footprint to a minimum. + + +Additionally, you should provide global functions which allow for capturing of +a basic message or exception: + +- `Sentry.captureMessage(message)` +- `Sentry.captureException(exception)` diff --git a/develop-docs/sdk/foundations/transport/authentication.mdx b/develop-docs/sdk/foundations/transport/authentication.mdx new file mode 100644 index 00000000000000..475647e124ba0b --- /dev/null +++ b/develop-docs/sdk/foundations/transport/authentication.mdx @@ -0,0 +1,146 @@ +--- +title: Authentication +description: DSN format, authentication headers, and HTTP conventions for communicating with Sentry. +sidebar_order: 1 +--- + +## Parsing the DSN + +SDKs are encouraged to allow arbitrary options via the constructor, but must allow the first argument as a DSN string. This string contains the following bits: + +``` +'{PROTOCOL}://{PUBLIC_KEY}:{SECRET_KEY}@{HOST}{PATH}/{PROJECT_ID}' +``` + +The final endpoint you'll be sending requests to is constructed per the following: + +``` + {BASE_URI} = '{PROTOCOL}://{HOST}{PATH}' + +'{BASE_URI}/api/{PROJECT_ID}/{ENDPOINT}/' +``` + +Within the `HOST` segment you will find the ingest domain for your organization. For self-hosted instances this will be the base host of your instance, and for sentry.io it will contain a host in the pattern of `o{orgid}.ingest.{region}.sentry.io`. For US based accounts `o{orgid}.ingest.sentry.io` will also work. + + +All segments, including PROJECT_ID, are of type String. + + +Sentry provides the following endpoints: + +- [/envelope/](../envelopes/) for any submission using Envelopes. +- [`/minidump/`](https://docs.sentry.io/platforms/native/minidump/) for multipart requests containing Minidumps. +- [`/unreal/`](https://docs.sentry.io/platforms/unreal/configuration/setup-crashreporter/) for Unreal + Engine 4 crash reports. +- [`/playstation/`](https://docs.sentry.io/platforms/playstation/) for PlayStation crash reports. + + The PlayStation endpoint has limited access and requires allowlisting. Support involves components that are part of a partnership with Sony which cannot be made public or redistributed. This endpoint is only available in SaaS. + +- [`/security/`](https://docs.sentry.io/error-reporting/security-policy-reporting/) for Browser + CSP reports, usually configured in a browser instead of an SDK. + +See the respective endpoints for information on how to compose proper request payloads. + +For example, given the following constructor: + +```javascript +Sentry.init({dsn: 'https://public@sentry.example.com/1'}) +``` + +You should parse the following settings: + +- URI = `https://sentry.example.com` +- Public Key = `public` +- Project ID = `1` + +The resulting POST request for a plain JSON payload would then transmit to: + +``` +'https://sentry.example.com/api/1/store/' +``` + + +The secret part of the DSN is optional and effectively deprecated at this point. While clients are still supposed to honor it if supplied future versions of Sentry will entirely ignore it. The DSN parsing code must not require the secret key to be set. + + +## Authentication Header + +An authentication header is expected to be sent along with the message body, which acts as an ownership identifier: + +``` +X-Sentry-Auth: Sentry sentry_version=7, + sentry_client=, + sentry_key=, + sentry_secret= +``` + +The `sentry_secret` must only be included if a secret key portion was contained in the DSN. Future versions of the protocol will fully deprecate the secret key. + + +You should include the SDK version string in the User-Agent portion of the header, and it will be used if `sentry_client` is not sent in the auth header. + + +In situations where it's not possible to send the custom `X-Sentry-Auth` header, it's possible to send these values via the querystring: + +``` +?sentry_version=7&sentry_key=&sentry_secret=... +``` + +`sentry_key` + +: **Required.** The public key which should be provided as part of the SDK configuration. + +`sentry_version` + +: **Required.** The protocol version. The current version of the protocol is `7`. + +`sentry_client` + +: **Recommended.** An arbitrary string that identifies your SDK, including its version. The typical pattern for this is `client_name/client_version`. For example, the Python SDK might send this as `sentry.python/1.0`. + +`sentry_timestamp` + +: The unix timestamp representing the time at which this event was generated. *This key is effectively deprecated, and it is ignored on the receiving side. Use the [`sent_at` envelope header](../envelopes/#envelope-headers) instead.* + +`sentry_secret` + +: The secret key which should be provided as part of the SDK configuration. *This key is effectively deprecated, and no longer needs to be set. However, since it was required in older versions, it should still be allowed and passed through to Sentry if set.* + +## HTTP Headers + +We recommend always sending the following headers: + +- `content-type` +- `content-length` +- `user-agent` + +The following additional headers are permitted as per CORS policy: + +- `x-sentry-auth` +- `x-requested-with` +- `x-forwarded-for` +- `origin` +- `referer` +- `accept` +- `authentication` +- `authorization` +- `content-encoding` +- `transfer-encoding` + +### User Agent + +All SDKs are expected to report their name and version via the `user-agent` header. The following format should be used (unless required or recommended differently by the platform, e.g. for browser SDKs, where the user agent header must be set by the browser itself): + +`{sdk-name}/{sdk-version}` + +For example: +- `sentry.python/1.45.0` +- `sentry.php/4.7.0` +- `sentry-ruby/5.17.3` +- `sentry.cocoa/8.24.0` + +Additional information about the runtime, operating system, and others can be appended as comments in parentheses, separated by `; ` (semicolon and space), like so: + +`{sdk-name}/{sdk-version} ({runtime-name} {runtime-version}; {os-name} {os-version})` + +There is no expectation towards the presence or order of fields. The user agent must not contain PII or otherwise sensitive data. In general it should not contain any information that is not already present in the payload. diff --git a/develop-docs/sdk/foundations/transport/compression.mdx b/develop-docs/sdk/foundations/transport/compression.mdx new file mode 100644 index 00000000000000..3b8f87220e98e6 --- /dev/null +++ b/develop-docs/sdk/foundations/transport/compression.mdx @@ -0,0 +1,20 @@ +--- +title: Compression +description: Request compression and transfer encoding for Sentry envelope submissions. +sidebar_order: 4 +--- + +## Request Compression + +SDKs are heavily encouraged to compress the request body before sending it to the server to keep the data small. The preferred method for this is to send a `content-encoding` header. The following content encodings are accepted by Relay and Sentry: + +- `gzip`: Using the [LZ77](http://en.wikipedia.org/wiki/LZ77_and_LZ78#LZ77) compression algorithm. +- `deflate`: Using [zlib](http://tools.ietf.org/html/rfc1950) structure with the [deflate](http://tools.ietf.org/html/rfc1951) compression algorithm. +- `br`: Using the [Brotli](https://en.wikipedia.org/wiki/Brotli) algorithm. +- `zstd`: Using the [zstd](https://datatracker.ietf.org/doc/html/rfc8878) algorithm. + +## Transfer Encoding + +Transfer encoding is recommended for only very large requests. Set the header to `transfer-encoding: chunked`, which allows omission of the `content-length` header and requires the request body to be wrapped into chunk headers. + +See [MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Transfer-Encoding) for more details. diff --git a/develop-docs/sdk/data-model/envelope-items.mdx b/develop-docs/sdk/foundations/transport/envelope-items.mdx similarity index 98% rename from develop-docs/sdk/data-model/envelope-items.mdx rename to develop-docs/sdk/foundations/transport/envelope-items.mdx index c8ae111923965c..025b4c61c86efb 100644 --- a/develop-docs/sdk/data-model/envelope-items.mdx +++ b/develop-docs/sdk/foundations/transport/envelope-items.mdx @@ -1,13 +1,13 @@ --- title: Envelope Items -sidebar_order: 2 +sidebar_order: 3 --- Each Envelope consists of headers and a potentially empty list of Items, each with their own headers. Which Headers are required depends on the Items in an Envelope. This section describes all Item types and their respective required headers. It is worth noting that the list of Item types doesn't match the data -categories used for [rate limiting](/sdk/expected-features/rate-limiting/#definitions) and +categories used for [rate limiting](/sdk/foundations/transport/rate-limiting/#definitions) and client reports. The type of an Item is declared in the `type` header, as well as the payload @@ -263,7 +263,7 @@ project. Sentry uses this ID to render a Replay clip in the feedback UI. **Attaching Files:** You can attach files of any type to a feedback (screenshots, logs, documents, etc.) by sending them as -[attachment items](/sdk/data-model/envelope-items/#attachment), with `event_id` +[attachment items](/sdk/foundations/transport/envelope-items/#attachment), with `event_id` corresponding to the feedback item. We recommend sending the attachment items in the same Envelope as the feedback item. diff --git a/develop-docs/sdk/data-model/envelopes.mdx b/develop-docs/sdk/foundations/transport/envelopes.mdx similarity index 97% rename from develop-docs/sdk/data-model/envelopes.mdx rename to develop-docs/sdk/foundations/transport/envelopes.mdx index d8e0d8d238c63a..c1644fdb2c7a5b 100644 --- a/develop-docs/sdk/data-model/envelopes.mdx +++ b/develop-docs/sdk/foundations/transport/envelopes.mdx @@ -1,6 +1,6 @@ --- title: Envelopes -sidebar_order: 1 +sidebar_order: 2 --- This document defines the Envelope and Item formats used by Sentry for data @@ -44,7 +44,7 @@ POST /api//envelope/ ## Serialization Format This section defines the Envelope data format and serialization. For details on -data integrity and a list of valid Item types refer to [Envelope Items](/sdk/data-model/envelope-items/). +data integrity and a list of valid Item types refer to [Envelope Items](/sdk/foundations/transport/envelope-items/). ### Prerequisites @@ -101,7 +101,7 @@ Payload = { * } ; [Headers](#headers) section. Attributes defined in the Envelope header scope the contents of the Envelope and can be thought of as applying to all Items. - Based on the contents of the Envelope, certain header attributes may be - required. See [Envelope Items](/sdk/data-model/envelope-items/) for a specification of required + required. See [Envelope Items](/sdk/foundations/transport/envelope-items/) for a specification of required attributes. - **Items** comprise their own headers and a payload. There can be an arbitrary number of **Items** in an Envelope separated by a newline. An @@ -184,7 +184,7 @@ There are two generic headers for every Item: `type` : **String, required.** Specifies the type of this Item and its contents. Based - on the Item type, more headers may be required. See [Envelope Items](/sdk/data-model/envelope-items/) for a list + on the Item type, more headers may be required. See [Envelope Items](/sdk/foundations/transport/envelope-items/) for a list of all Item types. `length` @@ -297,7 +297,7 @@ EOF:** ## Data Model -This section has been moved to [Envelope Items](/sdk/data-model/envelope-items/). +This section has been moved to [Envelope Items](/sdk/foundations/transport/envelope-items/). ## Ingestion This section describes how to ingest Envelopes into Relay or Sentry. The main diff --git a/develop-docs/sdk/foundations/transport/index.mdx b/develop-docs/sdk/foundations/transport/index.mdx new file mode 100644 index 00000000000000..5a8cdc484d089e --- /dev/null +++ b/develop-docs/sdk/foundations/transport/index.mdx @@ -0,0 +1,50 @@ +--- +title: Transport +description: How SDKs send data to Sentry - envelope format, authentication, compression, and rate limiting. +sidebar_order: 1 +--- + +The transport layer handles all communication between an SDK and the Sentry server. SDKs serialize data into [envelopes](envelopes/), [authenticate](authentication/) requests using DSN-derived credentials, optionally [compress](compression/) payloads, and respect [rate limits](rate-limiting/) communicated via response headers. + +## Reading the Response + +On success, you will receive an HTTP response from the server containing a JSON payload with information on the submitted payload: + +```http +HTTP/1.1 200 OK +Content-Type: application/json + +{ + "id": "fc6d8c0c43fc4630ad850ee518f1b9d0" +} +``` + +**Always** check for a `200` response, which confirms the message was delivered. A small level of validation happens immediately that may result in a different response code (and message). + +## Handling Server Errors + +SDKs **MUST** honor the `429` status code and not attempt sending until the `Retry-After` kicks in. SDKs **SHOULD** drop events if Sentry is unavailable instead of retrying. + +To debug an error during development, inspect the response headers and response body. For example, you may get a response similar to: + +```http +HTTP/1.1 400 Bad Request +Content-Type: application/json +X-Sentry-Error: failed to read request body + +{ + "detail":"failed to read request body", + "causes":[ + "failed to decode zlib payload", + "corrupt deflate stream" + ] +} +``` + +The `X-Sentry-Error` header and response body will not always contain a message, but they can still be helpful in debugging clients. When emitted, they will contain a precise error message, which is useful to identify root cause. + + +We do not recommend that SDKs retry event submissions automatically on error — not even if `Retry-After` is declared in the response headers. If a request fails once, it is very likely to fail again on the next attempt. Retrying too often may cause further rate limiting or blocking by the Sentry server. + + + diff --git a/develop-docs/sdk/expected-features/rate-limiting.mdx b/develop-docs/sdk/foundations/transport/rate-limiting.mdx similarity index 96% rename from develop-docs/sdk/expected-features/rate-limiting.mdx rename to develop-docs/sdk/foundations/transport/rate-limiting.mdx index d487c247b54c6e..7cebc01b4f23b2 100644 --- a/develop-docs/sdk/expected-features/rate-limiting.mdx +++ b/develop-docs/sdk/foundations/transport/rate-limiting.mdx @@ -1,6 +1,6 @@ --- title: Rate Limiting -sidebar_order: 2 +sidebar_order: 5 --- Rate limits are communicated to SDKs via status codes and response headers. For regular rate limit responses, we emit a [`429`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/429) status code and specify a [`Retry-After`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After) header. @@ -15,7 +15,7 @@ Each *quota_limit* has the form `retry_after:categories:scope:reason_code:namesp - `retry_after`: Number of seconds (as an integer or a floating point number) until this rate limit expires. - `categories`: Semicolon-separated list of [data categories](https://github.com/getsentry/relay/blob/master/relay-base-schema/src/data_category.rs#L91). **If empty, this limit applies to all categories**. - While these categories might look similar to the [envelope item types](/sdk/data-model/envelope-items/), they are not identical, and have slight differences. + While these categories might look similar to the [envelope item types](/sdk/foundations/transport/envelope-items/), they are not identical, and have slight differences. - `scope`: The scope that this limit applies to. Can be ignored by SDKs. - `reason_code`: A unique identifier for the quota hinting at the rate limiting reason. Can be ignored by SDKs. - `namespaces`: Semicolon-separated list of metric namespace identifiers. This will only be present if the rate limit applies to the `metric_bucket` data category. If the namespace is not present, the backoff applies to all metrics. @@ -83,7 +83,7 @@ Guidelines for how SDKs should determine the current rate limits: As stated earlier, SDKs can ignore the `scope` dimension. These definitions are here as a supplement to explain what the `X-Sentry-Rate-Limits` header is made of. - **Category:** Classifies the type of data that is being counted. Arbitrary categories can be added as long as they can be inferred from the event or data being ingested. -While these [data categories](https://github.com/getsentry/relay/blob/master/relay-base-schema/src/data_category.rs#L91) might look similar to the [envelope item types](/sdk/data-model/envelope-items/), they are not identical, and have slight differences. +While these [data categories](https://github.com/getsentry/relay/blob/master/relay-base-schema/src/data_category.rs#L91) might look similar to the [envelope item types](/sdk/foundations/transport/envelope-items/), they are not identical, and have slight differences. - `default`: Events with an event_type not listed explicitly below. - `error`: Error events. - `transaction`: Transaction type events. diff --git a/develop-docs/sdk/overview.mdx b/develop-docs/sdk/overview.mdx deleted file mode 100644 index 8229dbe8bcfe98..00000000000000 --- a/develop-docs/sdk/overview.mdx +++ /dev/null @@ -1,363 +0,0 @@ ---- -title: Overview -description: The following is a guide for implementing a new Sentry SDK. It covers the protocol for event submission as well as guidelines for how clients should typically look and behave. -sidebar_order: 1 ---- - -## Writing an SDK - -At its core an SDK is a set of utilities for capturing data about an exceptional state in an application. Given this data, it then builds and sends a JSON payload to the Sentry server. - -The following items are expected of production-ready SDKs: - -- DSN configuration -- Graceful failures (e.g. Sentry server is unreachable) -- Setting attributes (e.g. tags and extra data) -- Support for Linux, Windows and OS X (where applicable) - -Feature based support is required for the following: - -- If cookie data is available, it’s not sent by default -- If POST data is available, it’s not sent by default - -Additionally, the following features are highly encouraged: - -- Automated error capturing (e.g. uncaught exception handlers) -- Logging framework integration -- Non-blocking event submission -- Context data helpers (e.g. setting the current user, recording breadcrumbs) -- Event sampling -- Honor Sentry’s Rate Limiting HTTP headers -- Pre and Post event send hooks -- Local variable values in stack trace (on platforms where this is possible) -- Send an `environment` on each event. If none was detected or set by the user, `production` should be used. - -Please see the expected features page for descriptions of commonly Sentry SDK features. - -## Usage for End-users - -Generally, using an SDK consists of three steps for the end user, which should look almost identical no matter the language: - -1. Initialization of the SDK (sometimes this is hidden from the user): - - ```javascript - Sentry.init({dsn: '___PROJECT.DSN___'}); - ``` - - ```python - sentry_sdk.init('___PROJECT.DSN___') - ``` - -2. Capturing an event: - - ```javascript - var resultId = Sentry.captureException(myException); - ``` - - ```python - result_id = sentry_sdk.capture_exception(my_exception); - ``` - -3. Using the result of an event capture: - - ```javascript - alert(`Your exception was recorded as ${resultId}`); - ``` - - ```python - print('Your exception was recorded as %s', result_id); - ``` - -`init` ideally allows several configuration methods. The first argument should always be the DSN value (if possible): - -```javascript -Sentry.init({ - 'dsn': '___PROJECT.DSN___', - 'foo': 'bar' -}) -``` - - -SDKs should accept an empty DSN as valid configuration. - -If an SDK is not initialized or if it is initialized with an empty DSN, the SDK should not send any data over the network, such as captured exceptions. -Depending on the platform, the SDK may avoid performing unnecessary initialization work and reduce its runtime footprint to a minimum. - - -Additionally, you should provide global functions which allow for capturing of -a basic message or exception: - -- `Sentry.captureMessage(message)` -- `Sentry.captureException(exception)` - -## Parsing the DSN - -SDKs are encouraged to allow arbitrary options via the constructor, but must allow the first argument as a DSN string. This string contains the following bits: - -``` -'{PROTOCOL}://{PUBLIC_KEY}:{SECRET_KEY}@{HOST}{PATH}/{PROJECT_ID}' -``` - -The final endpoint you’ll be sending requests to is constructed per the following: - -``` - {BASE_URI} = '{PROTOCOL}://{HOST}{PATH}' - -'{BASE_URI}/api/{PROJECT_ID}/{ENDPOINT}/' -``` - -Within the `HOST` segment you will find the ingest domain for your organization. -For self-hosted instance this will be the base host of your instance, and for -sentry.io it will contain a host in the pattern of -`o{orgid}.ingest.{region}.sentry.io`. For US based accounts -`o{orgid}.ingest.sentry.io` will also work. - - -All segments, including PROJECT_ID, are of type String. - - -Sentry provides the following endpoints: - -- /envelope/ for any submission using Envelopes. -- [`/minidump/`](https://docs.sentry.io/platforms/native/minidump/) for multipart requests containing Minidumps. -- [`/unreal/`](https://docs.sentry.io/platforms/unreal/configuration/setup-crashreporter/) for Unreal - Engine 4 crash reports. -- [`/playstation/`](https://docs.sentry.io/platforms/playstation/) for PlayStation crash reports. - - The PlayStation endpoint has limited access and requires allowlisting. Support involves components that are part of a partnership with Sony which cannot be made public or redistributed. This endpoint is only available in SaaS. - -- [`/security/`](https://docs.sentry.io/error-reporting/security-policy-reporting/) for Browser - CSP reports, usually configured in a browser instead of an SDK. - -See the respective endpoints for information on how to compose proper request -payloads. - -For example, given the following constructor: - -```javascript -Sentry.init({dsn: 'https://public@sentry.example.com/1'}) -``` - -You should parse the following settings: - -- URI = `https://sentry.example.com` -- Public Key = `public` -- Project ID = `1` - -The resulting POST request for a plain JSON payload would then transmit to: - -``` -'https://sentry.example.com/api/1/store/' -``` - - -The secret part of the DSN is optional and effectively deprecated at this point. While clients are -still supposed to honor it if supplied future versions of Sentry will entirely ignore it. The DSN parsing -code must not require the secret key to be set. - - -## Authentication - -An authentication header is expected to be sent along with the message body, -which acts as an ownership identifier: - -``` -X-Sentry-Auth: Sentry sentry_version=7, - sentry_client=, - sentry_key=, - sentry_secret= -``` - -The `sentry_secret` must only be included if a secret key portion was contained -in the DSN. Future versions of the protocol will fully deprecate the secret -key. - - -You should include the SDK version string in the User-Agent portion of the header, and it will be used if `sentry_client` is not sent in the auth header. - - -In situations where it’s not possible to send the custom `X-Sentry-Auth` header, -it’s possible to send these values via the querystring: - -``` -?sentry_version=7&sentry_key=&sentry_secret=... -``` - -`sentry_key` - -: **Required.** The public key which should be provided as part of the SDK - configuration. - -`sentry_version` - -: **Required.** The protocol version. The current version of the protocol is - `7`. - -`sentry_client` - -: **Recommended.** An arbitrary string that identifies your SDK, including its version. The - typical pattern for this is `client_name/client_version`. - For example, the Python SDK might send this as `sentry.python/1.0`. - -`sentry_timestamp` - -: The unix timestamp representing the time at which this event was generated. - *This key is effectively deprecated, and it is ignored on the receiving side. Use the [`sent_at` envelope header](/sdk/data-model/envelopes/#envelope-headers) instead.* - -`sentry_secret` - -: The secret key which should be provided as part of the SDK configuration. - *This key is effectively deprecated, and no longer needs to be set. However, since it was required in older versions, it should still be allowed and passed through to Sentry if set.* - -## HTTP Headers - -We recommend always sending the following headers: - -- `content-type` -- `content-length` -- `user-agent` - -The following additional headers are permitted as per CORS policy: - -- `x-sentry-auth` -- `x-requested-with` -- `x-forwarded-for` -- `origin` -- `referer` -- `accept` -- `authentication` -- `authorization` -- `content-encoding` -- `transfer-encoding` - -### User Agent - -All SDKs are expected to report their name and version via the `user-agent` header. -The following format should be used (unless required or recommended differently by the platform, -e.g. for browser SDKs, where the user agent header must be set by the browser itself): - -`{sdk-name}/{sdk-version}` - -For example: -- `sentry.python/1.45.0` -- `sentry.php/4.7.0` -- `sentry-ruby/5.17.3` -- `sentry.cocoa/8.24.0` - -Additional information about the runtime, operating system, and others can be -appended as comments in parentheses, separated by `; ` (semicolon and space), like so: - -`{sdk-name}/{sdk-version} ({runtime-name} {runtime-version}; {os-name} {os-version})` - -There is no expectation towards the presence or order of fields. The user agent -must not contain PII or otherwise sensitive data. In general it should not contain -any information that is not already present in the payload. - - -## Request Compression - -SDKs are heavily encouraged to compress the request body before sending it to -the server to keep the data small. The preferred method for this is to send a -`content-encoding` header. The following content encodings are accepted by Relay -and Sentry: - -- `gzip`: Using the [LZ77](http://en.wikipedia.org/wiki/LZ77_and_LZ78#LZ77) - compression algorithm. -- `deflate`: Using [zlib](http://tools.ietf.org/html/rfc1950) structure with the - [deflate](http://tools.ietf.org/html/rfc1951) compression algorithm. -- `br`: Using the [Brotli](https://en.wikipedia.org/wiki/Brotli) algorithm. -- `zstd`: Using the [zstd](https://datatracker.ietf.org/doc/html/rfc8878) algorithm. - -## Transfer Encoding - -Transfer encoding is recommended for only very large requests. Set the header to -`transfer-encoding: chunked`, which allows omission of the `content-length` -header and requires the request body to be wrapped into chunk headers. - -See -[MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Transfer-Encoding) -for more details. - -## Reading the Response - -On success, you will receive an HTTP response from the server containing a JSON -payload with information on the submitted payload: - -```http -HTTP/1.1 200 OK -Content-Type: application/json - -{ - "id": "fc6d8c0c43fc4630ad850ee518f1b9d0" -} -``` - -Note the response code which Sentry will use. **Always** check for a `200` -response, which confirms the message was delivered. A small level of validation -happens immediately that may result in a different response code (and message). - -## Handling Errors - -### Server Errors - -We **highly encourage** that your SDK handle failures from the Sentry server -gracefully. Specifically, SDKs must honor the `429` status code and not attempt -sending until the `Retry-After` kicks in. SDKs should drop events if Sentry is -unavailable instead of retrying. - -To debug an error during development, inspect the response headers and response -body. For example, you may get a response similar to: - -```http -HTTP/1.1 400 Bad Request -Content-Type: application/json -X-Sentry-Error: failed to read request body - -{ - "detail":"failed to read request body", - "causes":[ - "failed to decode zlib payload", - "corrupt deflate stream" - ] -} -``` - -The `X-Sentry-Error` header and response body will not always contain a message, -but they can still be helpful in debugging clients. When emitted, they will -contain a precise error message, which is useful to identify root cause. - - -We do not recommend that SDKs retry event submissions automatically on error -  not even if `Retry-After` is declared in the response headers. If a -request fails once, it is very likely to fail again on the next attempt. -Retrying too often may cause further rate limiting or blocking by the Sentry -server. - - -### SDK Errors - -We try our best to make our SDKs error-free. We are an exception monitoring service after all -and throwing our own exceptions is awkward. However, if our SDKs do throw exceptions, we have to make -sure we swallow them gracefully and emit an error level log describing the failure. - -As a **design principle**, we never capture Sentry events for exceptions happening within our SDKs, including within user-defined callbacks and hooks such as `before_send` or `traces_sampler`. - -The reason we avoid capturing internal SDK exceptions is that we are already in an event capturing flow -where the scope has been applied and capturing another event at that point in the lifecycle -would lead to undefined behavior. In the worst case, we could create a busy loop of creating and sending events repeatedly until the system crashes. - -In mobile SDKs, unhandled crashes will still make it to Sentry via the crash handlers. See [SDK Crash Detection](https://github.com/getsentry/sentry/tree/master/src/sentry/utils/sdk_crashes#sdk-crash-detection) for more details. - -## Concurrency (Scope and Hubs) - -SDKs are supposed to provide standardized concurrency handling through the -concept of hubs and scopes. This is explained in more details in the -Concurrency chapter of the unified API docs. - -## Layer of Integration - -SDKs when possible are supposed to integrate on a low level which will capture as much of the runtime -as possible. This means that if an SDK can hook the runtime or a framework directly this is preferred -over requiring users to subclass specific base classes (or mix in helpers). For instance the Python -SDK will monkey patch core functionality in frameworks to automatically pick up on errors and to integrate -scope handling. diff --git a/develop-docs/sdk/processes/index.mdx b/develop-docs/sdk/processes/index.mdx index d5ccd6814648b4..2d48e5f8cb322d 100644 --- a/develop-docs/sdk/processes/index.mdx +++ b/develop-docs/sdk/processes/index.mdx @@ -1,7 +1,7 @@ --- title: Processes description: In this section, we aim to highlight some key processes that are essential for SDK development at Sentry. -sidebar_order: 3 +sidebar_order: 99 --- diff --git a/src/middleware.ts b/src/middleware.ts index 8873f84fccd741..92e345becac1b1 100644 --- a/src/middleware.ts +++ b/src/middleware.ts @@ -4330,6 +4330,22 @@ const DEVELOPER_DOCS_REDIRECTS: Redirect[] = [ from: '/sdk/philosophy/', to: '/sdk/getting-started/philosophy/', }, + { + from: '/sdk/data-model/envelopes/', + to: '/sdk/foundations/transport/envelopes/', + }, + { + from: '/sdk/data-model/envelope-items/', + to: '/sdk/foundations/transport/envelope-items/', + }, + { + from: '/sdk/expected-features/rate-limiting/', + to: '/sdk/foundations/transport/rate-limiting/', + }, + { + from: '/sdk/overview/', + to: '/sdk/foundations/overview/', + }, ]; const redirectMap = new Map(