|
| 1 | +--- |
| 2 | +title: Scopes and Hubs |
| 3 | +description: "SDKs will typically automatically manage the scopes for you in the framework integrations. Learn what a scope is and how you can use it to your advantage." |
| 4 | +--- |
| 5 | + |
| 6 | +When an event is captured and sent to Sentry, SDKs will merge that event data with extra |
| 7 | +information from the current scope. SDKs will typically automatically manage the scopes |
| 8 | +for you in the framework integrations and you don't need to think about them. However, |
| 9 | +you should know what a scope is and how you can use it for your advantage. |
| 10 | + |
| 11 | +## What's a Scope, What's a Hub |
| 12 | + |
| 13 | +You can think of the hub as the central point that our SDKs use to route an |
| 14 | +event to Sentry. When you call `init()` a hub is created and a client and a |
| 15 | +blank scope are created on it. That hub is then associated with the current |
| 16 | +thread and will internally hold a stack of scopes. |
| 17 | + |
| 18 | +The scope will hold useful information that should be sent along with the |
| 19 | +event. For instance [contexts](../context/) or |
| 20 | +[breadcrumbs](../breadcrumbs/) are stored on |
| 21 | +the scope. When a scope is pushed, it inherits all data from the parent scope |
| 22 | +and when it pops all modifications are reverted. |
| 23 | + |
| 24 | +The default SDK integrations will push and pop scopes intelligently. For |
| 25 | +instance web framework integrations will create and destroy scopes around your |
| 26 | +routes or controllers. |
| 27 | + |
| 28 | +## How the Scope and Hub Work |
| 29 | + |
| 30 | +As you start using an SDK, a scope and hub are automatically created for you out |
| 31 | +of the box. It's unlikely that you'll interact with the hub directly unless you're |
| 32 | +writing an integration or you want to create or destroy scopes. Scopes, on the |
| 33 | +other hand are more user facing. You can call <PlatformIdentifier name="configure-scope" /> at any point in |
| 34 | +time to modify data stored on the scope. This is useful for doing things like |
| 35 | +[modifying the context](../context/). |
| 36 | + |
| 37 | +When you call a global function such as <PlatformIdentifier name="capture-event" /> internally Sentry |
| 38 | +discovers the current hub and asks it to capture an event. Internally the hub will |
| 39 | +then merge the event with the topmost scope's data. |
| 40 | + |
| 41 | +## Configuring the Scope |
| 42 | + |
| 43 | +The most useful operation when working with scopes is the <PlatformIdentifier name="configure-scope" /> function. It can be used to reconfigure the current scope. |
| 44 | + |
| 45 | +You can, for instance, add custom tags or inform Sentry about the currently authenticated user. |
| 46 | + |
| 47 | +<PlatformContent includePath="enriching-events/scopes/configure-scope" /> |
| 48 | + |
| 49 | +You can also apply this configuration when unsetting a user at logout: |
| 50 | + |
| 51 | +<PlatformContent includePath="enriching-events/unset-user" /> |
| 52 | + |
| 53 | +To learn what useful information can be associated with scopes see |
| 54 | +[the context documentation](../context/). |
| 55 | + |
| 56 | +## Local Scopes |
| 57 | + |
| 58 | +We also support pushing and configuring a scope within a single call. This is typically |
| 59 | +called <PlatformIdentifier name="with-scope" />, <PlatformIdentifier name="push-scope" /> or implemented as a function parameter on the capture methods, depending on the SDK. It's very helpful if |
| 60 | +you only want to send data for one specific event. |
| 61 | + |
| 62 | +### Using <PlatformIdentifier name="with-scope" /> |
| 63 | + |
| 64 | +In the following example we use <PlatformIdentifier name="with-scope" /> to attach a `level` and a `tag` to only one specific error: |
| 65 | + |
| 66 | +<PlatformContent includePath="enriching-events/scopes/with-scope" /> |
| 67 | + |
| 68 | +While this example looks similar to <PlatformIdentifier name="configure-scope" />, it is actually very different. |
| 69 | +Calls to <PlatformIdentifier name="configure-scope" /> change the current active scope; all successive calls to <PlatformIdentifier name="configure-scope" /> will maintain previously set changes unless they are explicitly unset. |
| 70 | + |
| 71 | +On the other hand, <PlatformIdentifier name="with-scope" /> creates a clone of the current scope, and the changes |
| 72 | +made will stay isolated within the <PlatformIdentifier name="with-scope" /> callback function. This allows you to |
| 73 | +more easily isolate pieces of context information to specific locations in your code or |
| 74 | +even call <PlatformIdentifier name="clear" /> to briefly remove all context information. |
| 75 | + |
| 76 | +### Using Scope Callback Parameter |
| 77 | + |
| 78 | +In the following example we use the scope callback parameter that is available for all `capture` methods to attach a `level` and a `tag` to only one specific error: |
| 79 | + |
| 80 | +<PlatformContent includePath="enriching-events/scopes/scope-callback-param" /> |
| 81 | + |
| 82 | +Before the callback is invoked the SDK creates a clone of the current scope, and the changes |
| 83 | +made will stay isolated within the callback function. This allows you to |
| 84 | +more easily isolate pieces of context information to specific locations in your code or |
| 85 | +even call `clear` to briefly remove all context information. |
| 86 | + |
| 87 | +<Alert level="info" title="Important"> |
| 88 | + |
| 89 | +Any exceptions that occur within the callback function for configuring a local scope will not be |
| 90 | +caught, and all errors that occur will be silently ignored and **not** reported. |
| 91 | + |
| 92 | +</Alert> |
| 93 | + |
| 94 | +## Kotlin Coroutines |
| 95 | + |
| 96 | +Sentry's SDK for Java stores the scope and the context in a thread-local variable. To make sure that a coroutine has access to the correct Sentry context, an instance of `SentryContext` must be provided when launching a coroutine. |
| 97 | + |
| 98 | +### Installation |
| 99 | + |
| 100 | +```xml {tabTitle:Maven} |
| 101 | +<dependency> |
| 102 | + <groupId>io.sentry</groupId> |
| 103 | + <artifactId>sentry-kotlin-extensions</artifactId> |
| 104 | + <version>{{@inject packages.version('sentry.java.kotlin-extensions', '5.0.0') }}</version> |
| 105 | +</dependency> |
| 106 | +``` |
| 107 | + |
| 108 | +```groovy {tabTitle:Gradle} |
| 109 | +implementation 'io.sentry:sentry-kotlin-extensions:{{@inject packages.version('sentry.java.kotlin-extensions', '5.0.0') }}' |
| 110 | +``` |
| 111 | + |
| 112 | +```scala {tabTitle: SBT} |
| 113 | +libraryDependencies += "io.sentry" % "sentry-kotlin-extensions" % "{{@inject packages.version('sentry.java.kotlin-extensions', '5.0.0') }}" |
| 114 | +``` |
| 115 | + |
| 116 | +### Usage |
| 117 | + |
| 118 | +```kotlin |
| 119 | +import io.sentry.kotlin.SentryContext |
| 120 | +import io.sentry.Sentry |
| 121 | + |
| 122 | +launch(SentryContext()) { |
| 123 | + // tag set in parent coroutine is visible to child coroutine |
| 124 | + Sentry.setTag("parent-tag", "value") |
| 125 | + launch() { |
| 126 | + // tag set in child coroutine is not visible in parent coroutine |
| 127 | + Sentry.setTag("child-tag", "value") |
| 128 | + } |
| 129 | +} |
| 130 | +``` |
0 commit comments