Repository: getsentry/sentry-python

Issue:
Sentry crashing - python 3.11, AWS Lambda - x86_64
### How do you use Sentry?

Sentry Saas (sentry.io)

### Version

2.23.1

### Steps to Reproduce

Invoke a lambda more than once.
The first time works.
All subsequent invocations fail.

### Expected Result

No crash. :) 

### Actual Result

Crashes with the following stack trace

```
[ERROR] InvalidOperation: [<class 'decimal.InvalidOperation'>]
Traceback (most recent call last):
  File "/var/task/sentry_sdk/integrations/aws_lambda.py", line 152, in sentry_handler
    transaction = continue_trace(
  File "/var/task/sentry_sdk/api.py", line 431, in continue_trace
    return get_isolation_scope().continue_trace(
  File "/var/task/sentry_sdk/scope.py", line 1161, in continue_trace
    transaction = Transaction.continue_from_headers(
  File "/var/task/sentry_sdk/tracing.py", line 518, in continue_from_headers
    transaction = Transaction(**kwargs)
  File "/var/task/sentry_sdk/tracing.py", line 818, in __init__
    self._sample_rand = _generate_sample_rand(self.trace_id)
  File "/var/task/sentry_sdk/tracing_utils.py", line 874, in _generate_sample_rand
    return Decimal(sample_rand).quantize(Decimal("0.000001"), rounding=ROUND_DOWN)
```


Discussion hints:
codecov[bot]: ## [Codecov](https://app.codecov.io/gh/getsentry/sentry-python/pull/4179?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getsentry) Report
All modified and coverable lines are covered by tests :white_check_mark:
> Project coverage is 78.27%. Comparing base [(`5715734`)](https://app.codecov.io/gh/getsentry/sentry-python/commit/5715734eac1c5fb4b6ec61ef459080c74fa777b5?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getsentry) to head [(`2ae8835`)](https://app.codecov.io/gh/getsentry/sentry-python/commit/2ae883518f1808d8eb0a78e1a5c40bf132ab1cc5?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getsentry).

:white_check_mark: All tests successful. No failed tests found.

<details><summary>Additional details and impacted files</summary>


```diff
@@            Coverage Diff             @@
##           master    #4179      +/-   ##
==========================================
- Coverage   79.56%   78.27%   -1.30%     
==========================================
  Files         141      141              
  Lines       15736    15736              
  Branches     2675     2675              
==========================================
- Hits        12520    12317     -203     
- Misses       2369     2576     +207     
+ Partials      847      843       -4     
```

| [Files with missing lines](https://app.codecov.io/gh/getsentry/sentry-python/pull/4179?dropdown=coverage&src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getsentry) | Coverage Δ | |
|---|---|---|
| [sentry\_sdk/tracing\_utils.py](https://app.codecov.io/gh/getsentry/sentry-python/pull/4179?src=pr&el=tree&filepath=sentry_sdk%2Ftracing_utils.py&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getsentry#diff-c2VudHJ5X3Nkay90cmFjaW5nX3V0aWxzLnB5) | `84.29% <100.00%> (-1.21%)` | :arrow_down: |

... and [27 files with indirect coverage changes](https://app.codecov.io/gh/getsentry/sentry-python/pull/4179/indirect-changes?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getsentry)

</details>

Solution patch:
diff --git a/sentry_sdk/tracing_utils.py b/sentry_sdk/tracing_utils.py
index 6aa4e488..ba566957 100644
--- a/sentry_sdk/tracing_utils.py
+++ b/sentry_sdk/tracing_utils.py
@@ -5,7 +5,7 @@ import re
 import sys
 from collections.abc import Mapping
 from datetime import timedelta
-from decimal import ROUND_DOWN, Decimal
+from decimal import ROUND_DOWN, Context, Decimal
 from functools import wraps
 from random import Random
 from urllib.parse import quote, unquote
@@ -871,7 +871,11 @@ def _generate_sample_rand(
         sample_rand = rng.uniform(lower, upper)
 
     # Round down to exactly six decimal-digit precision.
-    return Decimal(sample_rand).quantize(Decimal("0.000001"), rounding=ROUND_DOWN)
+    # Setting the context is needed to avoid an InvalidOperation exception
+    # in case the user has changed the default precision.
+    return Decimal(sample_rand).quantize(
+        Decimal("0.000001"), rounding=ROUND_DOWN, context=Context(prec=6)
+    )
 
 
 def _sample_rand_range(parent_sampled, sample_rate):


Test patch:
diff --git a/tests/tracing/test_sample_rand.py b/tests/tracing/test_sample_rand.py
index b8f5c042..ef277a3d 100644
--- a/tests/tracing/test_sample_rand.py
+++ b/tests/tracing/test_sample_rand.py
@@ -1,3 +1,4 @@
+import decimal
 from unittest import mock
 
 import pytest
@@ -53,3 +54,28 @@ def test_transaction_uses_incoming_sample_rand(
     # Transaction event captured if sample_rand < sample_rate, indicating that
     # sample_rand is used to make the sampling decision.
     assert len(events) == int(sample_rand < sample_rate)
+
+
+def test_decimal_context(sentry_init, capture_events):
+    """
+    Ensure that having a decimal context with a precision below 6
+    does not cause an InvalidOperation exception.
+    """
+    sentry_init(traces_sample_rate=1.0)
+    events = capture_events()
+
+    old_prec = decimal.getcontext().prec
+    decimal.getcontext().prec = 2
+
+    try:
+        with mock.patch(
+            "sentry_sdk.tracing_utils.Random.uniform", return_value=0.123456789
+        ):
+            with sentry_sdk.start_transaction() as transaction:
+                assert (
+                    transaction.get_baggage().sentry_items["sample_rand"] == "0.123456"
+                )
+    finally:
+        decimal.getcontext().prec = old_prec
+
+    assert len(events) == 1