Commit 387441e
Fix Gevent patch regression with correct import order (#522)
### Issue
[This
PR](#218)
first fixed the Gevent monkey patching issue by calling the patch
operation when the ADOT Python starts up and before the modules are
loaded.
Later on in v0.10.0, [this
commit](aed584f#diff-8edce37d4d49a64bdb9e89ba42e612aeea53757a4f317a94b80b883ce54008e9)
broke the above fix by adding
the line `from
amazon.opentelemetry.distro.aws_opentelemetry_configurator` which
transitively imports the `requests` library before the gevent patch
operation is called, causing inconsistencies in the patched libraries
resulting in seeing the `RecursionError: maximum recursion depth
exceeded` error reappearing.
### Changes
1. Adding back the earlier logic to run the gevent's monkey patch (only
if `gevent` is installed) which was removed in [this
commit](1326576#diff-acd1d4a6916a3593419e6117394fe1c7d07b69d1562917dc0a2af45cd7ee8526)
to unblock development.
2. Refactoring the patch into its own file and adding comprehensive
comments to avoid the same issue in future.
3. Updated unit tests to mock the `gevent` module and validate only the
ADOT logic without running the gevent monkey patch. The actual behavior
of the patch should be tested in a higher level test such as a contract
test.
### Testing
Did a manual E2E testing using a sample flask application. Confirmed the
following:
- Saw `RecursionError` in the application with ADOT Python v0.10.0
- No such error when using ADOT with this fix.
#### Setup
##### Sample app
```python
from flask import Flask, request, jsonify
import logging
import sys
from datetime import datetime
import requests
# Configure logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
app = Flask(__name__)
logger = logging.getLogger(__name__)
@app.route('/requests')
def make_request():
res = requests.get('https://httpbin.org/get', timeout=5)
return jsonify({
'status': 'success',
'status_code': res.status_code,
'url': res.url,
'timestamp': datetime.now().isoformat()
})
if __name__ == '__main__':
app.run(debug=False, host='0.0.0.0', port=5001)
```
##### Running with problematic version (see the `MonkeyPatchWarning`)
```shell
((venv) ) ➜ flask git:(fix_gevent_regression) ✗ opentelemetry-instrument gunicorn -w 1 -k gevent --bind 0.0.0.0:5001 app:app
/Users/srprash/aws-otel-python-instrumentation/venv/lib/python3.12/site-packages/amazon/opentelemetry/distro/patches/_instrumentation_patch.py:36: MonkeyPatchWarning: Monkey-patching ssl after ssl has already been imported may lead to errors, including RecursionError on Python 3.6. It may also silently lead to incorrect behaviour on Python 3.7. Please monkey-patch earlier. See gevent/gevent#1016. Modules that had direct imports (NOT patched): ['urllib3.util.ssl_ (/Users/srprash/aws-otel-python-instrumentation/venv/lib/python3.12/site-packages/urllib3/util/ssl_.py)', 'urllib3.util (/Users/srprash/aws-otel-python-instrumentation/venv/lib/python3.12/site-packages/urllib3/util/__init__.py)'].
monkey.patch_all()
Failed to get k8s token: [Errno 2] No such file or directory: '/var/run/secrets/kubernetes.io/serviceaccount/token'
AwsEksResourceDetector failed: [Errno 2] No such file or directory: '/var/run/secrets/kubernetes.io/serviceaccount/token'
AwsEcsResourceDetector failed: Missing ECS_CONTAINER_METADATA_URI therefore process is not on ECS.
AwsEc2ResourceDetector failed: <urlopen error [Errno 65] No route to host>
[2025-10-29 11:00:55 -0700] [54080] [INFO] Starting gunicorn 23.0.0
[2025-10-29 11:00:55 -0700] [54080] [INFO] Listening at: http://0.0.0.0:5001 (54080)
[2025-10-29 11:00:55 -0700] [54080] [INFO] Using worker: gevent
[2025-10-29 11:00:55 -0700] [54290] [INFO] Booting worker with pid: 54290
2025-10-29 11:02:12,464 - app - ERROR - Exception on /requests [GET]
```
##### Running with the fix
```shell
((venv) ) ➜ flask git:(fix_gevent_regression) ✗ opentelemetry-instrument gunicorn -w 1 -k gevent --bind 0.0.0.0:5001 app:app
Failed to get k8s token: [Errno 2] No such file or directory: '/var/run/secrets/kubernetes.io/serviceaccount/token'
AwsEksResourceDetector failed: [Errno 2] No such file or directory: '/var/run/secrets/kubernetes.io/serviceaccount/token'
AwsEcsResourceDetector failed: Missing ECS_CONTAINER_METADATA_URI therefore process is not on ECS.
AwsEc2ResourceDetector failed: <urlopen error [Errno 65] No route to host>
[2025-10-29 11:04:45 -0700] [60707] [INFO] Starting gunicorn 23.0.0
[2025-10-29 11:04:45 -0700] [60707] [INFO] Listening at: http://0.0.0.0:5001 (60707)
[2025-10-29 11:04:45 -0700] [60707] [INFO] Using worker: gevent
[2025-10-29 11:04:45 -0700] [60734] [INFO] Booting worker with pid: 60734
```
By submitting this pull request, I confirm that you can use, modify,
copy, and redistribute this contribution, under the terms of your
choice.
---------
Co-authored-by: Thomas Pierce <thp@amazon.com>1 parent 6ae6225 commit 387441e
File tree
5 files changed
+420
-1
lines changed- aws-opentelemetry-distro
- src/amazon/opentelemetry/distro
- patches
- tests/amazon/opentelemetry/distro/patches
5 files changed
+420
-1
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
17 | 17 | | |
18 | 18 | | |
19 | 19 | | |
| 20 | + | |
| 21 | + | |
Lines changed: 11 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
3 | 14 | | |
4 | 15 | | |
5 | 16 | | |
| |||
Lines changed: 82 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
0 commit comments