We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Incorrect data in events when adding large integers to context data 
Sentry is treating big values differently in tags and context causing some values to be in correct after event processing. Below is an example event I sent using the ruby SDK, the same behaviour happens in Python as well: 

Script:
```
::Sentry.init do |config|
  config.dsn = "_MY_DSN_"
end

Sentry.set_tags('bigNumber': 608548899684111178)
Sentry.configure_scope do |scope|
  scope.set_context(
    'arguments',
    {
      name: 'A big value',
      age: 608548899684111178,
    }
  )
end

Sentry.capture_message("le big number test")
```

I expect to see both tag and context showing the same value, but in the context session it is showing as `608548899684111200` This is a common issue with large integer/floating point in Node.  

A possible workaround is to add the value as a string when it is added manually, but it is not applicable when the data is automatically added by the SDK.

![Screenshot 2024-03-11 at 11 48 50](https://github.com/getsentry/relay/assets/64906376/1d25a2b3-d369-4b0c-bb80-9cf038fde3df)


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `src/sentry/interfaces/contexts.py`
Content:
```
1 from __future__ import annotations
2 
3 import string
4 from typing import ClassVar, TypeVar
5 
6 from django.utils.encoding import force_str
7 
8 from sentry.interfaces.base import Interface
9 from sentry.utils.json import prune_empty_keys
10 from sentry.utils.safe import get_path
11 
12 __all__ = ("Contexts",)
13 
14 ContextTypeT = TypeVar("ContextTypeT", bound="ContextType")
15 
16 context_types: dict[str, type[ContextType]] = {}
17 
18 
19 class _IndexFormatter(string.Formatter):
20     def format_field(self, value, format_spec):
21         if not format_spec and isinstance(value, bool):
22             return value and "yes" or "no"
23         return string.Formatter.format_field(self, value, format_spec)
24 
25 
26 def format_index_expr(format_string, data):
27     return str(_IndexFormatter().vformat(str(format_string), (), data).strip())
28 
29 
30 def contexttype(cls: type[ContextTypeT]) -> type[ContextTypeT]:
31     context_types[cls.type] = cls
32     return cls
33 
34 
35 # NOTE: Are you adding a new context? Make sure to also update the
36 # documentation in the sentry develop docs [0]!
37 #
38 # [0]: https://develop.sentry.dev/sdk/event-payloads/contexts
39 
40 
41 class ContextType:
42     context_to_tag_mapping: ClassVar[dict[str, str]] = {}
43     """
44     This indicates which fields should be promoted into tags during event
45     normalization. (See EventManager)
46 
47     The key for each entry is used as the name of the tag suffixed by the
48     "alias" of the context (this is the key of the context in the contexts
49     object, it is NOT the `type` of the context, though they are often the
50     same).
51 
52     The value is a format string spec that uses python string.Formatter to
53     interpolate any value from the context object.
54 
55     There is one special case:
56 
57      - When the key of the mapping is an empty string the tag name will simply be
58        the alias.
59 
60     For example if you have a context named "myContext" with the data:
61 
62     ```json
63     "myContext": {
64         "some_value": "hello world",
65         "subkey": "whatever",
66         "type": "myContext"
67     }
68     ```
69 
70     and you have a context_to_tag_mapping that looks like
71 
72     ```python
73     context_to_tag_mapping = {"": "{some_value}", "subkey": "{subkey}"}
74     ```
75 
76     Then normalization will result in two tags being promoted:
77 
78      - myContext: "hello world"
79      - myContext.subkey: "whatever"
80     """
81 
82     type: str
83     """This should match the `type` key in context object"""
84 
85     def __init__(self, alias, data):
86         self.alias = alias
87         ctx_data = {}
88         for key, value in data.items():
89             # we use a simple check here, rather than ' in set()' to avoid
90             # issues with maps/lists.
91 
92             # Even if the value is an empty string,
93             # we still want to display the info the UI
94             if value is not None:
95                 ctx_data[force_str(key)] = value
96         self.data = ctx_data
97 
98     def to_json(self):
99         rv = dict(self.data)
100         rv["type"] = self.type
101         return prune_empty_keys(rv)
102 
103     @classmethod
104     def values_for_data(cls, data):
105         rv = []
106         for context in (data.get("contexts") or {}).values():
107             if context and context.get("type") == cls.type:
108                 rv.append(context)
109         return rv
110 
111     @classmethod
112     def primary_value_for_data(cls, data):
113         val = get_path(data, "contexts", cls.type)
114         if val and val.get("type") == cls.type:
115             return val
116 
117         rv = cls.values_for_data(data)
118         if len(rv) == 1:
119             return rv[0]
120 
121     def iter_tags(self):
122         if self.context_to_tag_mapping:
123             for field, f_string in self.context_to_tag_mapping.items():
124                 try:
125                     value = format_index_expr(f_string, self.data)
126                 except KeyError:
127                     continue
128                 if value:
129                     if not field:
130                         yield (self.alias, value)
131                     else:
132                         yield (f"{self.alias}.{field}", value)
133 
134 
135 # TODO(dcramer): contexts need to document/describe expected (optional) fields
136 @contexttype
137 class DefaultContextType(ContextType):
138     type = "default"
139 
140 
141 @contexttype
142 class AppContextType(ContextType):
143     type = "app"
144     context_to_tag_mapping = {"device": "{device_app_hash}"}
145 
146 
147 @contexttype
148 class DeviceContextType(ContextType):
149     type = "device"
150     context_to_tag_mapping = {"": "{model}", "family": "{family}"}
151     # model_id, arch
152 
153 
154 @contexttype
155 class RuntimeContextType(ContextType):
156     type = "runtime"
157     context_to_tag_mapping = {"": "{name} {version}", "name": "{name}"}
158 
159 
160 @contexttype
161 class BrowserContextType(ContextType):
162     type = "browser"
163     context_to_tag_mapping = {"": "{name} {version}", "name": "{name}"}
164     # viewport
165 
166 
167 @contexttype
168 class OsContextType(ContextType):
169     type = "os"
170     context_to_tag_mapping = {"": "{name} {version}", "name": "{name}", "rooted": "{rooted}"}
171     # build, rooted
172 
173 
174 @contexttype
175 class GpuContextType(ContextType):
176     type = "gpu"
177     context_to_tag_mapping = {"name": "{name}", "vendor": "{vendor_name}"}
178 
179 
180 @contexttype
181 class MonitorContextType(ContextType):
182     type = "monitor"
183     context_to_tag_mapping = {"id": "{id}", "slug": "{slug}"}
184 
185 
186 @contexttype
187 class TraceContextType(ContextType):
188     type = "trace"
189     context_to_tag_mapping = {}
190 
191 
192 @contexttype
193 class OtelContextType(ContextType):
194     type = "otel"
195     context_to_tag_mapping = {}
196 
197 
198 class Contexts(Interface):
199     """
200     This interface stores context specific information.
201     """
202 
203     display_score = 1100
204     score = 800
205 
206     @classmethod
207     def to_python(cls, data, **kwargs):
208         rv = {}
209 
210         # Note the alias is the key of the context entry
211         for alias, value in data.items():
212             # XXX(markus): The `None`-case should be handled in the UI and
213             # other consumers of this interface
214             if value is not None:
215                 rv[alias] = cls.normalize_context(alias, value)
216 
217         return super().to_python(rv, **kwargs)
218 
219     @classmethod
220     def normalize_context(cls, alias, data):
221         ctx_type = data.get("type", alias)
222         ctx_cls = context_types.get(ctx_type, DefaultContextType)
223         return ctx_cls(alias, data)
224 
225     def iter_contexts(self):
226         return self._data.values()
227 
228     def to_json(self):
229         rv = {}
230         for alias, inst in self._data.items():
231             rv[alias] = inst.to_json()
232         return rv
233 
234     def iter_tags(self):
235         for inst in self.iter_contexts():
236             yield from inst.iter_tags()
237
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/src/sentry/interfaces/contexts.py b/src/sentry/interfaces/contexts.py
--- a/src/sentry/interfaces/contexts.py
+++ b/src/sentry/interfaces/contexts.py
@@ -93,6 +93,9 @@
             # we still want to display the info the UI
             if value is not None:
                 ctx_data[force_str(key)] = value
+            # Numbers exceeding 15 place values will be converted to strings to avoid rendering issues
+            if isinstance(value, (int, float)) and len(str_value := force_str(value)) > 15:
+                ctx_data[force_str(key)] = str_value
         self.data = ctx_data
 
     def to_json(self):

{"golden_diff": "diff --git a/src/sentry/interfaces/contexts.py b/src/sentry/interfaces/contexts.py\n--- a/src/sentry/interfaces/contexts.py\n+++ b/src/sentry/interfaces/contexts.py\n@@ -93,6 +93,9 @@\n             # we still want to display the info the UI\n             if value is not None:\n                 ctx_data[force_str(key)] = value\n+            # Numbers exceeding 15 place values will be converted to strings to avoid rendering issues\n+            if isinstance(value, (int, float)) and len(str_value := force_str(value)) > 15:\n+                ctx_data[force_str(key)] = str_value\n         self.data = ctx_data\n \n     def to_json(self):\n", "issue": "Incorrect data in events when adding large integers to context data \nSentry is treating big values differently in tags and context causing some values to be in correct after event processing. Below is an example event I sent using the ruby SDK, the same behaviour happens in Python as well: \r\n\r\nScript:\r\n```\r\n::Sentry.init do |config|\r\n  config.dsn = \"_MY_DSN_\"\r\nend\r\n\r\nSentry.set_tags('bigNumber': 608548899684111178)\r\nSentry.configure_scope do |scope|\r\n  scope.set_context(\r\n    'arguments',\r\n    {\r\n      name: 'A big value',\r\n      age: 608548899684111178,\r\n    }\r\n  )\r\nend\r\n\r\nSentry.capture_message(\"le big number test\")\r\n```\r\n\r\nI expect to see both tag and context showing the same value, but in the context session it is showing as `608548899684111200` This is a common issue with large integer/floating point in Node.  \r\n\r\nA possible workaround is to add the value as a string when it is added manually, but it is not applicable when the data is automatically added by the SDK.\r\n\r\n![Screenshot 2024-03-11 at 11 48 50](https://github.com/getsentry/relay/assets/64906376/1d25a2b3-d369-4b0c-bb80-9cf038fde3df)\r\n\n", "before_files": [{"content": "from __future__ import annotations\n\nimport string\nfrom typing import ClassVar, TypeVar\n\nfrom django.utils.encoding import force_str\n\nfrom sentry.interfaces.base import Interface\nfrom sentry.utils.json import prune_empty_keys\nfrom sentry.utils.safe import get_path\n\n__all__ = (\"Contexts\",)\n\nContextTypeT = TypeVar(\"ContextTypeT\", bound=\"ContextType\")\n\ncontext_types: dict[str, type[ContextType]] = {}\n\n\nclass _IndexFormatter(string.Formatter):\n    def format_field(self, value, format_spec):\n        if not format_spec and isinstance(value, bool):\n            return value and \"yes\" or \"no\"\n        return string.Formatter.format_field(self, value, format_spec)\n\n\ndef format_index_expr(format_string, data):\n    return str(_IndexFormatter().vformat(str(format_string), (), data).strip())\n\n\ndef contexttype(cls: type[ContextTypeT]) -> type[ContextTypeT]:\n    context_types[cls.type] = cls\n    return cls\n\n\n# NOTE: Are you adding a new context? Make sure to also update the\n# documentation in the sentry develop docs [0]!\n#\n# [0]: https://develop.sentry.dev/sdk/event-payloads/contexts\n\n\nclass ContextType:\n    context_to_tag_mapping: ClassVar[dict[str, str]] = {}\n    \"\"\"\n    This indicates which fields should be promoted into tags during event\n    normalization. (See EventManager)\n\n    The key for each entry is used as the name of the tag suffixed by the\n    \"alias\" of the context (this is the key of the context in the contexts\n    object, it is NOT the `type` of the context, though they are often the\n    same).\n\n    The value is a format string spec that uses python string.Formatter to\n    interpolate any value from the context object.\n\n    There is one special case:\n\n     - When the key of the mapping is an empty string the tag name will simply be\n       the alias.\n\n    For example if you have a context named \"myContext\" with the data:\n\n    ```json\n    \"myContext\": {\n        \"some_value\": \"hello world\",\n        \"subkey\": \"whatever\",\n        \"type\": \"myContext\"\n    }\n    ```\n\n    and you have a context_to_tag_mapping that looks like\n\n    ```python\n    context_to_tag_mapping = {\"\": \"{some_value}\", \"subkey\": \"{subkey}\"}\n    ```\n\n    Then normalization will result in two tags being promoted:\n\n     - myContext: \"hello world\"\n     - myContext.subkey: \"whatever\"\n    \"\"\"\n\n    type: str\n    \"\"\"This should match the `type` key in context object\"\"\"\n\n    def __init__(self, alias, data):\n        self.alias = alias\n        ctx_data = {}\n        for key, value in data.items():\n            # we use a simple check here, rather than ' in set()' to avoid\n            # issues with maps/lists.\n\n            # Even if the value is an empty string,\n            # we still want to display the info the UI\n            if value is not None:\n                ctx_data[force_str(key)] = value\n        self.data = ctx_data\n\n    def to_json(self):\n        rv = dict(self.data)\n        rv[\"type\"] = self.type\n        return prune_empty_keys(rv)\n\n    @classmethod\n    def values_for_data(cls, data):\n        rv = []\n        for context in (data.get(\"contexts\") or {}).values():\n            if context and context.get(\"type\") == cls.type:\n                rv.append(context)\n        return rv\n\n    @classmethod\n    def primary_value_for_data(cls, data):\n        val = get_path(data, \"contexts\", cls.type)\n        if val and val.get(\"type\") == cls.type:\n            return val\n\n        rv = cls.values_for_data(data)\n        if len(rv) == 1:\n            return rv[0]\n\n    def iter_tags(self):\n        if self.context_to_tag_mapping:\n            for field, f_string in self.context_to_tag_mapping.items():\n                try:\n                    value = format_index_expr(f_string, self.data)\n                except KeyError:\n                    continue\n                if value:\n                    if not field:\n                        yield (self.alias, value)\n                    else:\n                        yield (f\"{self.alias}.{field}\", value)\n\n\n# TODO(dcramer): contexts need to document/describe expected (optional) fields\n@contexttype\nclass DefaultContextType(ContextType):\n    type = \"default\"\n\n\n@contexttype\nclass AppContextType(ContextType):\n    type = \"app\"\n    context_to_tag_mapping = {\"device\": \"{device_app_hash}\"}\n\n\n@contexttype\nclass DeviceContextType(ContextType):\n    type = \"device\"\n    context_to_tag_mapping = {\"\": \"{model}\", \"family\": \"{family}\"}\n    # model_id, arch\n\n\n@contexttype\nclass RuntimeContextType(ContextType):\n    type = \"runtime\"\n    context_to_tag_mapping = {\"\": \"{name} {version}\", \"name\": \"{name}\"}\n\n\n@contexttype\nclass BrowserContextType(ContextType):\n    type = \"browser\"\n    context_to_tag_mapping = {\"\": \"{name} {version}\", \"name\": \"{name}\"}\n    # viewport\n\n\n@contexttype\nclass OsContextType(ContextType):\n    type = \"os\"\n    context_to_tag_mapping = {\"\": \"{name} {version}\", \"name\": \"{name}\", \"rooted\": \"{rooted}\"}\n    # build, rooted\n\n\n@contexttype\nclass GpuContextType(ContextType):\n    type = \"gpu\"\n    context_to_tag_mapping = {\"name\": \"{name}\", \"vendor\": \"{vendor_name}\"}\n\n\n@contexttype\nclass MonitorContextType(ContextType):\n    type = \"monitor\"\n    context_to_tag_mapping = {\"id\": \"{id}\", \"slug\": \"{slug}\"}\n\n\n@contexttype\nclass TraceContextType(ContextType):\n    type = \"trace\"\n    context_to_tag_mapping = {}\n\n\n@contexttype\nclass OtelContextType(ContextType):\n    type = \"otel\"\n    context_to_tag_mapping = {}\n\n\nclass Contexts(Interface):\n    \"\"\"\n    This interface stores context specific information.\n    \"\"\"\n\n    display_score = 1100\n    score = 800\n\n    @classmethod\n    def to_python(cls, data, **kwargs):\n        rv = {}\n\n        # Note the alias is the key of the context entry\n        for alias, value in data.items():\n            # XXX(markus): The `None`-case should be handled in the UI and\n            # other consumers of this interface\n            if value is not None:\n                rv[alias] = cls.normalize_context(alias, value)\n\n        return super().to_python(rv, **kwargs)\n\n    @classmethod\n    def normalize_context(cls, alias, data):\n        ctx_type = data.get(\"type\", alias)\n        ctx_cls = context_types.get(ctx_type, DefaultContextType)\n        return ctx_cls(alias, data)\n\n    def iter_contexts(self):\n        return self._data.values()\n\n    def to_json(self):\n        rv = {}\n        for alias, inst in self._data.items():\n            rv[alias] = inst.to_json()\n        return rv\n\n    def iter_tags(self):\n        for inst in self.iter_contexts():\n            yield from inst.iter_tags()\n", "path": "src/sentry/interfaces/contexts.py"}], "after_files": [{"content": "from __future__ import annotations\n\nimport string\nfrom typing import ClassVar, TypeVar\n\nfrom django.utils.encoding import force_str\n\nfrom sentry.interfaces.base import Interface\nfrom sentry.utils.json import prune_empty_keys\nfrom sentry.utils.safe import get_path\n\n__all__ = (\"Contexts\",)\n\nContextTypeT = TypeVar(\"ContextTypeT\", bound=\"ContextType\")\n\ncontext_types: dict[str, type[ContextType]] = {}\n\n\nclass _IndexFormatter(string.Formatter):\n    def format_field(self, value, format_spec):\n        if not format_spec and isinstance(value, bool):\n            return value and \"yes\" or \"no\"\n        return string.Formatter.format_field(self, value, format_spec)\n\n\ndef format_index_expr(format_string, data):\n    return str(_IndexFormatter().vformat(str(format_string), (), data).strip())\n\n\ndef contexttype(cls: type[ContextTypeT]) -> type[ContextTypeT]:\n    context_types[cls.type] = cls\n    return cls\n\n\n# NOTE: Are you adding a new context? Make sure to also update the\n# documentation in the sentry develop docs [0]!\n#\n# [0]: https://develop.sentry.dev/sdk/event-payloads/contexts\n\n\nclass ContextType:\n    context_to_tag_mapping: ClassVar[dict[str, str]] = {}\n    \"\"\"\n    This indicates which fields should be promoted into tags during event\n    normalization. (See EventManager)\n\n    The key for each entry is used as the name of the tag suffixed by the\n    \"alias\" of the context (this is the key of the context in the contexts\n    object, it is NOT the `type` of the context, though they are often the\n    same).\n\n    The value is a format string spec that uses python string.Formatter to\n    interpolate any value from the context object.\n\n    There is one special case:\n\n     - When the key of the mapping is an empty string the tag name will simply be\n       the alias.\n\n    For example if you have a context named \"myContext\" with the data:\n\n    ```json\n    \"myContext\": {\n        \"some_value\": \"hello world\",\n        \"subkey\": \"whatever\",\n        \"type\": \"myContext\"\n    }\n    ```\n\n    and you have a context_to_tag_mapping that looks like\n\n    ```python\n    context_to_tag_mapping = {\"\": \"{some_value}\", \"subkey\": \"{subkey}\"}\n    ```\n\n    Then normalization will result in two tags being promoted:\n\n     - myContext: \"hello world\"\n     - myContext.subkey: \"whatever\"\n    \"\"\"\n\n    type: str\n    \"\"\"This should match the `type` key in context object\"\"\"\n\n    def __init__(self, alias, data):\n        self.alias = alias\n        ctx_data = {}\n        for key, value in data.items():\n            # we use a simple check here, rather than ' in set()' to avoid\n            # issues with maps/lists.\n\n            # Even if the value is an empty string,\n            # we still want to display the info the UI\n            if value is not None:\n                ctx_data[force_str(key)] = value\n            # Numbers exceeding 15 place values will be converted to strings to avoid rendering issues\n            if isinstance(value, (int, float)) and len(str_value := force_str(value)) > 15:\n                ctx_data[force_str(key)] = str_value\n        self.data = ctx_data\n\n    def to_json(self):\n        rv = dict(self.data)\n        rv[\"type\"] = self.type\n        return prune_empty_keys(rv)\n\n    @classmethod\n    def values_for_data(cls, data):\n        rv = []\n        for context in (data.get(\"contexts\") or {}).values():\n            if context and context.get(\"type\") == cls.type:\n                rv.append(context)\n        return rv\n\n    @classmethod\n    def primary_value_for_data(cls, data):\n        val = get_path(data, \"contexts\", cls.type)\n        if val and val.get(\"type\") == cls.type:\n            return val\n\n        rv = cls.values_for_data(data)\n        if len(rv) == 1:\n            return rv[0]\n\n    def iter_tags(self):\n        if self.context_to_tag_mapping:\n            for field, f_string in self.context_to_tag_mapping.items():\n                try:\n                    value = format_index_expr(f_string, self.data)\n                except KeyError:\n                    continue\n                if value:\n                    if not field:\n                        yield (self.alias, value)\n                    else:\n                        yield (f\"{self.alias}.{field}\", value)\n\n\n# TODO(dcramer): contexts need to document/describe expected (optional) fields\n@contexttype\nclass DefaultContextType(ContextType):\n    type = \"default\"\n\n\n@contexttype\nclass AppContextType(ContextType):\n    type = \"app\"\n    context_to_tag_mapping = {\"device\": \"{device_app_hash}\"}\n\n\n@contexttype\nclass DeviceContextType(ContextType):\n    type = \"device\"\n    context_to_tag_mapping = {\"\": \"{model}\", \"family\": \"{family}\"}\n    # model_id, arch\n\n\n@contexttype\nclass RuntimeContextType(ContextType):\n    type = \"runtime\"\n    context_to_tag_mapping = {\"\": \"{name} {version}\", \"name\": \"{name}\"}\n\n\n@contexttype\nclass BrowserContextType(ContextType):\n    type = \"browser\"\n    context_to_tag_mapping = {\"\": \"{name} {version}\", \"name\": \"{name}\"}\n    # viewport\n\n\n@contexttype\nclass OsContextType(ContextType):\n    type = \"os\"\n    context_to_tag_mapping = {\"\": \"{name} {version}\", \"name\": \"{name}\", \"rooted\": \"{rooted}\"}\n    # build, rooted\n\n\n@contexttype\nclass GpuContextType(ContextType):\n    type = \"gpu\"\n    context_to_tag_mapping = {\"name\": \"{name}\", \"vendor\": \"{vendor_name}\"}\n\n\n@contexttype\nclass MonitorContextType(ContextType):\n    type = \"monitor\"\n    context_to_tag_mapping = {\"id\": \"{id}\", \"slug\": \"{slug}\"}\n\n\n@contexttype\nclass TraceContextType(ContextType):\n    type = \"trace\"\n    context_to_tag_mapping = {}\n\n\n@contexttype\nclass OtelContextType(ContextType):\n    type = \"otel\"\n    context_to_tag_mapping = {}\n\n\nclass Contexts(Interface):\n    \"\"\"\n    This interface stores context specific information.\n    \"\"\"\n\n    display_score = 1100\n    score = 800\n\n    @classmethod\n    def to_python(cls, data, **kwargs):\n        rv = {}\n\n        # Note the alias is the key of the context entry\n        for alias, value in data.items():\n            # XXX(markus): The `None`-case should be handled in the UI and\n            # other consumers of this interface\n            if value is not None:\n                rv[alias] = cls.normalize_context(alias, value)\n\n        return super().to_python(rv, **kwargs)\n\n    @classmethod\n    def normalize_context(cls, alias, data):\n        ctx_type = data.get(\"type\", alias)\n        ctx_cls = context_types.get(ctx_type, DefaultContextType)\n        return ctx_cls(alias, data)\n\n    def iter_contexts(self):\n        return self._data.values()\n\n    def to_json(self):\n        rv = {}\n        for alias, inst in self._data.items():\n            rv[alias] = inst.to_json()\n        return rv\n\n    def iter_tags(self):\n        for inst in self.iter_contexts():\n            yield from inst.iter_tags()\n", "path": "src/sentry/interfaces/contexts.py"}]}