Skip to content

Commit 827c62f

Browse files
committed
move shared environments docs
1 parent 77cd63d commit 827c62f

File tree

9 files changed

+196
-109
lines changed

9 files changed

+196
-109
lines changed
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
---
2+
title: Browser Extensions
3+
sidebar_order: 50
4+
description: Learn how to use Sentry in Shared Environments (for example in Browser Extensions or VSCode Extensions).
5+
keywords:
6+
[
7+
"BrowserClient",
8+
"NodeClient",
9+
"shared environment",
10+
"browser extension",
11+
"VSCode extension"
12+
]
13+
---
14+
15+
When setting up Sentry in a shared environment where multiple Sentry instances may run, for example, in a browser extension or similar, you should **not use `Sentry.init()`**, as this will pollute the global state. If your browser extension uses `Sentry.init()`, and the website the extension is running on also uses Sentry, the extension may send events to the website's Sentry project, or vice versa.
16+
17+
For such scenarios, you have to set up a client manually as seen in the example below.
18+
In addition, you should also avoid adding any integrations that use global state, like `Breadcrumbs` or `TryCatch`.
19+
As a rule of thumb, it's best to avoid using any integrations and to rely on manual capture of errors only in such scenarios.
20+
21+
<SignInNote />
22+
23+
```javascript
24+
import {
25+
BrowserClient,
26+
defaultStackParser,
27+
defaultIntegrations,
28+
makeFetchTransport,
29+
Scope,
30+
} from "@sentry/browser";
31+
32+
const client = new BrowserClient({
33+
dsn: "___PUBLIC_DSN___",
34+
transport: makeFetchTransport,
35+
stackParser: defaultStackParser,
36+
integrations: defaultIntegrations,
37+
});
38+
39+
const scope = new Scope();
40+
scope.setClient(client);
41+
42+
client.init() // initializing has to be done after setting the client on the scope
43+
44+
// You can capture exceptions manually for this client like this:
45+
scope.captureException(new Error("example"));
46+
47+
```
48+
49+
If you notice that Sentry is not capturing error events from the browser extension,
50+
try disabling the Browser extension errors option in the Inbound Filters of your Sentry configuration.
51+
Read more about Inbound Filters in the product documentation under [Inbound filters](/product/data-management-settings/filtering/#inbound-data-filters).
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
title: Best Practices
3+
description: "Learn how to set up Sentry in specific scenarios with those best practice guides"
4+
sidebar_order: 3
5+
---
6+
7+
<PageGrid />
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
---
2+
title: Multiple Sentry Instances
3+
sidebar_order: 300
4+
description: Learn how to manage several Sentry instances by creating your own clients.
5+
keywords:
6+
[
7+
"multiple instances",
8+
"multiple clients",
9+
"BrowserClient",
10+
"NodeClient",
11+
"monorepo"
12+
]
13+
---
14+
15+
<Note>
16+
17+
Creating multiple Sentry clients is not recommended in general, as it can lead to unexpected behavior. If you are using Micro Frontends or similar, multiplexing might be a better solution that using multiple clients. Check out [Micro Frontends](/micro-frontends) in the Best Practices for more information.
18+
19+
</ Note>
20+
21+
To be able to manage several Sentry instances without any conflicts between them you need to create your own `Client`.
22+
This also helps to prevent tracking of any parent application errors in case your application is integrated
23+
inside of it. In this example we use `BrowserClient` from `@sentry/browser` but it's also applicable to `NodeClient` from `@sentry/node`.
24+
25+
<SignInNote />
26+
27+
```javascript
28+
import {
29+
BrowserClient,
30+
defaultStackParser,
31+
defaultIntegrations,
32+
makeFetchTransport,
33+
Scope,
34+
} from "@sentry/browser";
35+
36+
const client = new BrowserClient({
37+
dsn: "___PUBLIC_DSN___",
38+
transport: makeFetchTransport,
39+
stackParser: defaultStackParser,
40+
integrations: defaultIntegrations,
41+
});
42+
43+
const scope = new Scope();
44+
scope.setClient(client);
45+
46+
client.init() // initializing has to be done after setting the client on the scope
47+
48+
// You can capture exceptions manually for this client like this:
49+
scope.captureException(new Error("example"));
50+
```
51+
52+
You can now customize the scope to your liking, without affecting other hubs/clients.
53+
54+
### Dealing with Integrations
55+
56+
Integrations are setup on the `Client`, if you need to deal with multiple clients and hubs you have to make sure to also do the integration handling correctly.
57+
58+
We do not recommend doing this if you are using Sentry in a browser extension or in similar scenarios.
59+
If you can't avoid using global integrations (e.g. in a micro frontend application), here is a working example of how to use multiple clients with multiple scopes running global integrations.
60+
61+
<SignInNote />
62+
63+
```javascript
64+
import * as Sentry from "@sentry/browser";
65+
66+
// Very happy integration that'll prepend and append very happy stick figure to the message
67+
function happyIntegration() {
68+
return {
69+
name: 'Happy',
70+
setupOnce() {
71+
Sentry.addGlobalEventProcessor((event) => {
72+
const self = Sentry.getClient().getIntegration(HappyIntegration);
73+
// Run the integration ONLY when it was installed on the current Hub
74+
if (self) {
75+
event.message = `\\o/ ${event.message} \\o/`;
76+
}
77+
return event;
78+
});
79+
}
80+
}
81+
}
82+
83+
const client1 = new Sentry.BrowserClient({
84+
dsn: "___PUBLIC_DSN___",
85+
transport: Sentry.makeFetchTransport,
86+
stackParser: Sentry.defaultStackParser,
87+
integrations: [...Sentry.defaultIntegrations, happyIntegration()],
88+
beforeSend(event) {
89+
console.log("client 1", event);
90+
return null; // Returning `null` prevents the event from being sent
91+
},
92+
});
93+
const scope1 = new Sentry.Scope(client1);
94+
95+
const client2 = new Sentry.BrowserClient({
96+
dsn: "___PUBLIC_DSN___", // Can be a different DSN
97+
transport: Sentry.makeFetchTransport,
98+
stackParser: Sentry.defaultStackParser,
99+
integrations: [...Sentry.defaultIntegrations, happyIntegration()],
100+
beforeSend(event) {
101+
console.log("client 2", event);
102+
return null; // Returning `null` prevents the event from being sent
103+
},
104+
});
105+
const scope2 = new Sentry.Scope(client2);
106+
107+
scope1.captureMessage("a");
108+
scope1.setTag("a", "b");
109+
110+
scope2.captureMessage("x");
111+
scope2.setTag("c", "d");
112+
```
113+
114+

docs/platforms/javascript/common/troubleshooting/index.mdx

Lines changed: 0 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -284,115 +284,6 @@ If you would like to copy and paste the snippet directly, here it is minified:
284284
</script>
285285
```
286286
287-
## Using a Client directly
288-
289-
To be able to manage several Sentry instances without any conflicts between them you need to create your own `Client`.
290-
This also helps to prevent tracking of any parent application errors in case your application is integrated
291-
inside of it. In this example we use `@sentry/browser` but it's also applicable to `@sentry/node`.
292-
293-
<SignInNote />
294-
295-
```javascript
296-
import {
297-
BrowserClient,
298-
defaultStackParser,
299-
defaultIntegrations,
300-
makeFetchTransport,
301-
Scope,
302-
} from "@sentry/browser";
303-
304-
const client = new BrowserClient({
305-
dsn: "___PUBLIC_DSN___",
306-
transport: makeFetchTransport,
307-
stackParser: defaultStackParser,
308-
integrations: defaultIntegrations,
309-
});
310-
311-
const scope = new Scope();
312-
scope.setClient(client);
313-
314-
client.init() // initializing has to be done after setting the client on the scope
315-
316-
// You can capture exceptions manually for this client like this:
317-
scope.captureException(new Error("example"));
318-
```
319-
320-
You can now customize the hub to your liking, without affecting other hubs/clients.
321-
322-
### Setting up Sentry in shared environments (e.g. Browser Extensions)
323-
324-
When setting up Sentry in a shared environment where multiple Sentry instances may run, for example, in a browser extension or similar, you should **not use `Sentry.init()`**, as this will pollute the global state. If your browser extension uses `Sentry.init()`, and the website the extension is running on also uses Sentry, the extension may send events to the website's Sentry project, or vice versa.
325-
326-
For such scenarios, you have to set up a client manually as seen in the example above.
327-
In addition, you should also avoid adding any integrations that use global state, like `Breadcrumbs` or `TryCatch`.
328-
As a rule of thumb, it's best to avoid using any integrations and to rely on manual capture of errors only in such scenarios.
329-
330-
### Dealing with Integrations
331-
332-
Integrations are setup on the `Client`, if you need to deal with multiple clients and hubs you have to make sure to also do the integration handling correctly.
333-
334-
We do not recommend doing this if you are using Sentry in a browser extension or in similar scenarios.
335-
If you can't avoid using global integrations (e.g. in a micro frontend application), here is a working example of how to use multiple clients with multiple hubs running global integrations.
336-
337-
<SignInNote />
338-
339-
```javascript
340-
import * as Sentry from "@sentry/browser";
341-
342-
// Very happy integration that'll prepend and append very happy stick figure to the message
343-
function happyIntegration() {
344-
return {
345-
name: 'Happy',
346-
setupOnce() {
347-
Sentry.addGlobalEventProcessor((event) => {
348-
const self = Sentry.getClient().getIntegration(HappyIntegration);
349-
// Run the integration ONLY when it was installed on the current Hub
350-
if (self) {
351-
event.message = `\\o/ ${event.message} \\o/`;
352-
}
353-
return event;
354-
});
355-
}
356-
}
357-
}
358-
359-
const client1 = new Sentry.BrowserClient({
360-
dsn: "___PUBLIC_DSN___",
361-
transport: Sentry.makeFetchTransport,
362-
stackParser: Sentry.defaultStackParser,
363-
integrations: [...Sentry.defaultIntegrations, happyIntegration()],
364-
beforeSend(event) {
365-
console.log("client 1", event);
366-
return null; // Returning `null` prevents the event from being sent
367-
},
368-
});
369-
const hub1 = new Sentry.Hub(client1);
370-
371-
const client2 = new Sentry.BrowserClient({
372-
dsn: "___PUBLIC_DSN___", // Can be a different DSN
373-
transport: Sentry.makeFetchTransport,
374-
stackParser: Sentry.defaultStackParser,
375-
integrations: [...Sentry.defaultIntegrations, happyIntegration()],
376-
beforeSend(event) {
377-
console.log("client 2", event);
378-
return null; // Returning `null` prevents the event from being sent
379-
},
380-
});
381-
const hub2 = new Sentry.Hub(client2);
382-
383-
hub1.run((currentHub) => {
384-
// The `hub.run` method makes sure that `Sentry.getCurrentHub()` returns this hub during the callback
385-
currentHub.captureMessage("a");
386-
Sentry.getCurrentScope().setTag("a", "b");
387-
});
388-
389-
hub2.run((currentHub) => {
390-
// The `hub.run` method makes sure that `Sentry.getCurrentHub()` returns this hub during the callback
391-
currentHub.captureMessage("x");
392-
Sentry.getCurrentScope().setTag("c", "d");
393-
});
394-
```
395-
396287
## Third Party Promise Libraries
397288
398289
When you include and configure Sentry, our JavaScript SDK automatically attaches global handlers to _capture_ uncaught exceptions and unhandled promise rejections. You can disable this default behavior by changing the `onunhandledrejection` option to `false` in your GlobalHandlers integration and manually hook into each event handler, then call `Sentry.captureException` or `Sentry.captureMessage` directly.

src/middleware.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2488,6 +2488,18 @@ const REDIRECTS: {from: PathWithTrailingSlash; to: string}[] = [
24882488
from: '/product/sentry-basics/search/searchable-properties/session-replay/',
24892489
to: '/product/reference/search/searchable-properties/session-replay/',
24902490
},
2491+
{
2492+
from: '/platforms/javascript/configuration/micro-frontend-support/',
2493+
to: '/platforms/javascript/best-practices/micro-frontends/',
2494+
},
2495+
{
2496+
from: '/platforms/javascript/configuration/sentry-testkit/',
2497+
to: '/platforms/javascript/best-practices/sentry-testkit/',
2498+
},
2499+
{
2500+
from: 'platforms/javascript/configuration/webworkers/',
2501+
to: '/platforms/javascript/best-practices/web-workers/',
2502+
},
24912503
];
24922504

24932505
const redirectMap = new Map(REDIRECTS.map(r => [r.from as string, r.to]));

vercel.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -734,6 +734,18 @@
734734
"source": "/platforms/javascript/sourcemaps/tools/",
735735
"destination": "/platforms/javascript/sourcemaps/"
736736
},
737+
{
738+
"source": "/platforms/javascript/guides/([^/]*)/configuration/micro-frontend-support/",
739+
"destination": "/platforms/javascript/guides/$1/best-practices/micro-frontends/"
740+
},
741+
{
742+
"source": "/platforms/javascript/guides/([^/]*)/configuration/sentry-testkit/",
743+
"destination": "/platforms/javascript/guides/$1/best-practices/sentry-testkit/"
744+
},
745+
{
746+
"source": "/platforms/javascript/guides/([^/]*)/configuration/webworkers/",
747+
"destination": "/platforms/javascript/guides/$1/best-practices/web-workers/"
748+
},
737749
{
738750
"source": "/platforms/apple/guides/([^/]*)/configuration/integrations/([^/]*)/",
739751
"destination": "/platforms/apple/guides/$1/integrations/$2/"

0 commit comments

Comments
 (0)