sf-veritas 0.11.10__cp314-cp314-manylinux_2_28_x86_64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- sf_veritas/__init__.py +46 -0
- sf_veritas/_auto_preload.py +73 -0
- sf_veritas/_sfconfig.c +162 -0
- sf_veritas/_sfconfig.cpython-314-x86_64-linux-gnu.so +0 -0
- sf_veritas/_sfcrashhandler.c +267 -0
- sf_veritas/_sfcrashhandler.cpython-314-x86_64-linux-gnu.so +0 -0
- sf_veritas/_sffastlog.c +953 -0
- sf_veritas/_sffastlog.cpython-314-x86_64-linux-gnu.so +0 -0
- sf_veritas/_sffastnet.c +994 -0
- sf_veritas/_sffastnet.cpython-314-x86_64-linux-gnu.so +0 -0
- sf_veritas/_sffastnetworkrequest.c +727 -0
- sf_veritas/_sffastnetworkrequest.cpython-314-x86_64-linux-gnu.so +0 -0
- sf_veritas/_sffuncspan.c +2791 -0
- sf_veritas/_sffuncspan.cpython-314-x86_64-linux-gnu.so +0 -0
- sf_veritas/_sffuncspan_config.c +730 -0
- sf_veritas/_sffuncspan_config.cpython-314-x86_64-linux-gnu.so +0 -0
- sf_veritas/_sfheadercheck.c +341 -0
- sf_veritas/_sfheadercheck.cpython-314-x86_64-linux-gnu.so +0 -0
- sf_veritas/_sfnetworkhop.c +1454 -0
- sf_veritas/_sfnetworkhop.cpython-314-x86_64-linux-gnu.so +0 -0
- sf_veritas/_sfservice.c +1223 -0
- sf_veritas/_sfservice.cpython-314-x86_64-linux-gnu.so +0 -0
- sf_veritas/_sfteepreload.c +6227 -0
- sf_veritas/app_config.py +57 -0
- sf_veritas/cli.py +336 -0
- sf_veritas/constants.py +10 -0
- sf_veritas/custom_excepthook.py +304 -0
- sf_veritas/custom_log_handler.py +146 -0
- sf_veritas/custom_output_wrapper.py +153 -0
- sf_veritas/custom_print.py +153 -0
- sf_veritas/django_app.py +5 -0
- sf_veritas/env_vars.py +186 -0
- sf_veritas/exception_handling_middleware.py +18 -0
- sf_veritas/exception_metaclass.py +69 -0
- sf_veritas/fast_frame_info.py +116 -0
- sf_veritas/fast_network_hop.py +293 -0
- sf_veritas/frame_tools.py +112 -0
- sf_veritas/funcspan_config_loader.py +693 -0
- sf_veritas/function_span_profiler.py +1313 -0
- sf_veritas/get_preload_path.py +34 -0
- sf_veritas/import_hook.py +62 -0
- sf_veritas/infra_details/__init__.py +3 -0
- sf_veritas/infra_details/get_infra_details.py +24 -0
- sf_veritas/infra_details/kubernetes/__init__.py +3 -0
- sf_veritas/infra_details/kubernetes/get_cluster_name.py +147 -0
- sf_veritas/infra_details/kubernetes/get_details.py +7 -0
- sf_veritas/infra_details/running_on/__init__.py +17 -0
- sf_veritas/infra_details/running_on/kubernetes.py +11 -0
- sf_veritas/interceptors.py +543 -0
- sf_veritas/libsfnettee.so +0 -0
- sf_veritas/local_env_detect.py +118 -0
- sf_veritas/package_metadata.py +6 -0
- sf_veritas/patches/__init__.py +0 -0
- sf_veritas/patches/_patch_tracker.py +74 -0
- sf_veritas/patches/concurrent_futures.py +19 -0
- sf_veritas/patches/constants.py +1 -0
- sf_veritas/patches/exceptions.py +82 -0
- sf_veritas/patches/multiprocessing.py +32 -0
- sf_veritas/patches/network_libraries/__init__.py +99 -0
- sf_veritas/patches/network_libraries/aiohttp.py +294 -0
- sf_veritas/patches/network_libraries/curl_cffi.py +363 -0
- sf_veritas/patches/network_libraries/http_client.py +670 -0
- sf_veritas/patches/network_libraries/httpcore.py +580 -0
- sf_veritas/patches/network_libraries/httplib2.py +315 -0
- sf_veritas/patches/network_libraries/httpx.py +557 -0
- sf_veritas/patches/network_libraries/niquests.py +218 -0
- sf_veritas/patches/network_libraries/pycurl.py +399 -0
- sf_veritas/patches/network_libraries/requests.py +595 -0
- sf_veritas/patches/network_libraries/ssl_socket.py +822 -0
- sf_veritas/patches/network_libraries/tornado.py +360 -0
- sf_veritas/patches/network_libraries/treq.py +270 -0
- sf_veritas/patches/network_libraries/urllib_request.py +483 -0
- sf_veritas/patches/network_libraries/utils.py +598 -0
- sf_veritas/patches/os.py +17 -0
- sf_veritas/patches/threading.py +231 -0
- sf_veritas/patches/web_frameworks/__init__.py +54 -0
- sf_veritas/patches/web_frameworks/aiohttp.py +798 -0
- sf_veritas/patches/web_frameworks/async_websocket_consumer.py +337 -0
- sf_veritas/patches/web_frameworks/blacksheep.py +532 -0
- sf_veritas/patches/web_frameworks/bottle.py +513 -0
- sf_veritas/patches/web_frameworks/cherrypy.py +683 -0
- sf_veritas/patches/web_frameworks/cors_utils.py +122 -0
- sf_veritas/patches/web_frameworks/django.py +963 -0
- sf_veritas/patches/web_frameworks/eve.py +401 -0
- sf_veritas/patches/web_frameworks/falcon.py +931 -0
- sf_veritas/patches/web_frameworks/fastapi.py +738 -0
- sf_veritas/patches/web_frameworks/flask.py +526 -0
- sf_veritas/patches/web_frameworks/klein.py +501 -0
- sf_veritas/patches/web_frameworks/litestar.py +616 -0
- sf_veritas/patches/web_frameworks/pyramid.py +440 -0
- sf_veritas/patches/web_frameworks/quart.py +841 -0
- sf_veritas/patches/web_frameworks/robyn.py +708 -0
- sf_veritas/patches/web_frameworks/sanic.py +874 -0
- sf_veritas/patches/web_frameworks/starlette.py +742 -0
- sf_veritas/patches/web_frameworks/strawberry.py +1446 -0
- sf_veritas/patches/web_frameworks/tornado.py +485 -0
- sf_veritas/patches/web_frameworks/utils.py +170 -0
- sf_veritas/print_override.py +13 -0
- sf_veritas/regular_data_transmitter.py +444 -0
- sf_veritas/request_interceptor.py +401 -0
- sf_veritas/request_utils.py +550 -0
- sf_veritas/segfault_handler.py +116 -0
- sf_veritas/server_status.py +1 -0
- sf_veritas/shutdown_flag.py +11 -0
- sf_veritas/subprocess_startup.py +3 -0
- sf_veritas/test_cli.py +145 -0
- sf_veritas/thread_local.py +1319 -0
- sf_veritas/timeutil.py +114 -0
- sf_veritas/transmit_exception_to_sailfish.py +28 -0
- sf_veritas/transmitter.py +132 -0
- sf_veritas/types.py +47 -0
- sf_veritas/unified_interceptor.py +1678 -0
- sf_veritas/utils.py +39 -0
- sf_veritas-0.11.10.dist-info/METADATA +97 -0
- sf_veritas-0.11.10.dist-info/RECORD +141 -0
- sf_veritas-0.11.10.dist-info/WHEEL +5 -0
- sf_veritas-0.11.10.dist-info/entry_points.txt +2 -0
- sf_veritas-0.11.10.dist-info/top_level.txt +1 -0
- sf_veritas.libs/libbrotlicommon-6ce2a53c.so.1.0.6 +0 -0
- sf_veritas.libs/libbrotlidec-811d1be3.so.1.0.6 +0 -0
- sf_veritas.libs/libcom_err-730ca923.so.2.1 +0 -0
- sf_veritas.libs/libcrypt-52aca757.so.1.1.0 +0 -0
- sf_veritas.libs/libcrypto-bdaed0ea.so.1.1.1k +0 -0
- sf_veritas.libs/libcurl-eaa3cf66.so.4.5.0 +0 -0
- sf_veritas.libs/libgssapi_krb5-323bbd21.so.2.2 +0 -0
- sf_veritas.libs/libidn2-2f4a5893.so.0.3.6 +0 -0
- sf_veritas.libs/libk5crypto-9a74ff38.so.3.1 +0 -0
- sf_veritas.libs/libkeyutils-2777d33d.so.1.6 +0 -0
- sf_veritas.libs/libkrb5-a55300e8.so.3.3 +0 -0
- sf_veritas.libs/libkrb5support-e6594cfc.so.0.1 +0 -0
- sf_veritas.libs/liblber-2-d20824ef.4.so.2.10.9 +0 -0
- sf_veritas.libs/libldap-2-cea2a960.4.so.2.10.9 +0 -0
- sf_veritas.libs/libnghttp2-39367a22.so.14.17.0 +0 -0
- sf_veritas.libs/libpcre2-8-516f4c9d.so.0.7.1 +0 -0
- sf_veritas.libs/libpsl-99becdd3.so.5.3.1 +0 -0
- sf_veritas.libs/libsasl2-7de4d792.so.3.0.0 +0 -0
- sf_veritas.libs/libselinux-d0805dcb.so.1 +0 -0
- sf_veritas.libs/libssh-c11d285b.so.4.8.7 +0 -0
- sf_veritas.libs/libssl-60250281.so.1.1.1k +0 -0
- sf_veritas.libs/libunistring-05abdd40.so.2.1.0 +0 -0
- sf_veritas.libs/libuuid-95b83d40.so.1.3.0 +0 -0
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import time
|
|
3
|
+
from typing import List, Optional
|
|
4
|
+
|
|
5
|
+
try:
|
|
6
|
+
import wrapt
|
|
7
|
+
|
|
8
|
+
HAS_WRAPT = True
|
|
9
|
+
except ImportError:
|
|
10
|
+
HAS_WRAPT = False
|
|
11
|
+
|
|
12
|
+
from ...constants import SAILFISH_TRACING_HEADER, PARENT_SESSION_ID_HEADER
|
|
13
|
+
from ...env_vars import SF_DEBUG
|
|
14
|
+
from ...thread_local import trace_id_ctx
|
|
15
|
+
from .utils import (
|
|
16
|
+
init_fast_header_check,
|
|
17
|
+
inject_headers_ultrafast,
|
|
18
|
+
record_network_request,
|
|
19
|
+
is_ssl_socket_active,
|
|
20
|
+
has_sailfish_header,
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
# JSON serialization - try fast orjson first, fallback to stdlib json
|
|
24
|
+
try:
|
|
25
|
+
import orjson
|
|
26
|
+
|
|
27
|
+
HAS_ORJSON = True
|
|
28
|
+
except ImportError:
|
|
29
|
+
import json
|
|
30
|
+
|
|
31
|
+
HAS_ORJSON = False
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def _tee_preload_active() -> bool:
|
|
35
|
+
"""Detect if LD_PRELOAD tee is active (same logic as http_client.py)."""
|
|
36
|
+
if os.getenv("SF_TEE_PRELOAD_ONLY", "0") == "1":
|
|
37
|
+
return True
|
|
38
|
+
ld = os.getenv("LD_PRELOAD", "")
|
|
39
|
+
return "libsfnettee.so" in ld or "_sfteepreload" in ld
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def patch_httplib2(domains_to_not_propagate_headers_to: Optional[List[str]] = None):
|
|
43
|
+
"""
|
|
44
|
+
Monkey-patch httplib2.Http.request so that:
|
|
45
|
+
1. We skip header injection for configured domains.
|
|
46
|
+
2. We inject SAILFISH_TRACING_HEADER + FUNCSPAN_OVERRIDE_HEADER (fast: <20ns).
|
|
47
|
+
3. We call NetworkRequestTransmitter().do_send via record_network_request() UNLESS LD_PRELOAD active.
|
|
48
|
+
4. All HTTP methods (GET, POST, etc.) continue to work as before.
|
|
49
|
+
|
|
50
|
+
When LD_PRELOAD is active: ULTRA-FAST path with <10ns overhead (header injection only).
|
|
51
|
+
When LD_PRELOAD is NOT active: Full capture path with body/header recording.
|
|
52
|
+
|
|
53
|
+
CRITICAL: If http.client is already patched, httplib2 only does header injection
|
|
54
|
+
to avoid double-capture (httplib2 uses http.client.HTTPConnection underneath).
|
|
55
|
+
"""
|
|
56
|
+
TRACE_HEADER_LOWER = SAILFISH_TRACING_HEADER.lower()
|
|
57
|
+
PARENT_HEADER_LOWER = PARENT_SESSION_ID_HEADER.lower()
|
|
58
|
+
|
|
59
|
+
def _log_headers(stage: str, hdrs: Optional[dict]) -> None:
|
|
60
|
+
if not (SF_DEBUG and hdrs):
|
|
61
|
+
return
|
|
62
|
+
try:
|
|
63
|
+
snapshot = {}
|
|
64
|
+
for key, value in hdrs.items():
|
|
65
|
+
if not isinstance(key, str):
|
|
66
|
+
continue
|
|
67
|
+
key_lower = key.lower()
|
|
68
|
+
if key_lower in (TRACE_HEADER_LOWER, PARENT_HEADER_LOWER):
|
|
69
|
+
snapshot[key] = value
|
|
70
|
+
print(f"[httplib2.patch] {stage} headers={snapshot}", log=False)
|
|
71
|
+
except Exception as exc: # pragma: no cover - debug logging only
|
|
72
|
+
print(f"[httplib2.patch] {stage} header log failed: {exc}", log=False)
|
|
73
|
+
|
|
74
|
+
try:
|
|
75
|
+
import httplib2
|
|
76
|
+
except ImportError:
|
|
77
|
+
return
|
|
78
|
+
|
|
79
|
+
original_conn_request = getattr(httplib2.Http, "_conn_request", None)
|
|
80
|
+
if (
|
|
81
|
+
original_conn_request
|
|
82
|
+
and not getattr(original_conn_request, "_sf_debug_logged", False)
|
|
83
|
+
and SF_DEBUG
|
|
84
|
+
):
|
|
85
|
+
def _logged_conn_request(self, conn, request_uri, method, body, headers):
|
|
86
|
+
_log_headers(
|
|
87
|
+
f"conn_request:{method}:{request_uri}",
|
|
88
|
+
headers or {},
|
|
89
|
+
)
|
|
90
|
+
return original_conn_request(self, conn, request_uri, method, body, headers)
|
|
91
|
+
|
|
92
|
+
_logged_conn_request._sf_debug_logged = True # type: ignore[attr-defined]
|
|
93
|
+
httplib2.Http._conn_request = _logged_conn_request
|
|
94
|
+
|
|
95
|
+
skip = domains_to_not_propagate_headers_to or []
|
|
96
|
+
preload_active = _tee_preload_active()
|
|
97
|
+
|
|
98
|
+
# CRITICAL: Check if http.client is already patched (handles capture for us)
|
|
99
|
+
# httplib2 uses http.client.HTTPConnection underneath, so if http_client patch
|
|
100
|
+
# is active, we should ONLY do header injection to avoid double-capture
|
|
101
|
+
http_client_patched = False
|
|
102
|
+
try:
|
|
103
|
+
import http.client as _hc
|
|
104
|
+
# Check if request method has been wrapped (indicates http_client patch is active)
|
|
105
|
+
http_client_patched = hasattr(_hc.HTTPConnection.request, '__wrapped__') or \
|
|
106
|
+
getattr(_hc.HTTPConnection.request, '__name__', '') == 'patched_request'
|
|
107
|
+
except Exception:
|
|
108
|
+
pass
|
|
109
|
+
|
|
110
|
+
# Initialize C extension for ultra-fast header checking (if available)
|
|
111
|
+
if preload_active or http_client_patched:
|
|
112
|
+
init_fast_header_check(skip)
|
|
113
|
+
|
|
114
|
+
# Store original for both fast and slow paths
|
|
115
|
+
original_request = httplib2.Http.request
|
|
116
|
+
|
|
117
|
+
# Use fast path (header injection only) if LD_PRELOAD is active OR http.client is already patched
|
|
118
|
+
use_fast_path = preload_active or http_client_patched
|
|
119
|
+
|
|
120
|
+
if use_fast_path:
|
|
121
|
+
# ========== ULTRA-FAST PATH: Header injection only ==========
|
|
122
|
+
# Used when: LD_PRELOAD is active OR http.client is already patched
|
|
123
|
+
# This avoids double-capture since http.client handles it for us
|
|
124
|
+
if HAS_WRAPT:
|
|
125
|
+
# FASTEST: Use wrapt directly (OTEL-style for minimal overhead)
|
|
126
|
+
def instrumented_request(wrapped, instance, args, kwargs):
|
|
127
|
+
"""Ultra-fast header injection using inject_headers_ultrafast() via wrapt."""
|
|
128
|
+
# args = (uri, method, ...), kwargs = {body, headers, ...}
|
|
129
|
+
uri = args[0] if len(args) > 0 else kwargs.get("uri", "")
|
|
130
|
+
|
|
131
|
+
# Ensure headers dict exists
|
|
132
|
+
headers = kwargs.get("headers")
|
|
133
|
+
if not headers:
|
|
134
|
+
headers = {}
|
|
135
|
+
elif not isinstance(headers, dict):
|
|
136
|
+
headers = dict(headers)
|
|
137
|
+
|
|
138
|
+
if SF_DEBUG:
|
|
139
|
+
_log_headers("pre-inject", headers)
|
|
140
|
+
|
|
141
|
+
# Check if headers are already injected (avoid double-injection with http.client)
|
|
142
|
+
# Fast O(1) check for common cases, fallback to O(n) for rare mixed-case variants
|
|
143
|
+
if not has_sailfish_header(headers):
|
|
144
|
+
# ULTRA-FAST: inject_headers_ultrafast does domain filtering + header injection (~100ns)
|
|
145
|
+
inject_headers_ultrafast(headers, uri, skip)
|
|
146
|
+
if SF_DEBUG:
|
|
147
|
+
_log_headers("post-inject", headers)
|
|
148
|
+
elif SF_DEBUG:
|
|
149
|
+
dup_snapshot = {
|
|
150
|
+
k: headers[k]
|
|
151
|
+
for k in headers
|
|
152
|
+
if isinstance(k, str) and k.lower() == TRACE_HEADER_LOWER
|
|
153
|
+
}
|
|
154
|
+
print(f"[httplib2.patch] Skip inject (wrapt) - existing headers={dup_snapshot}", log=False)
|
|
155
|
+
|
|
156
|
+
kwargs["headers"] = headers
|
|
157
|
+
|
|
158
|
+
# Immediately call original and return - NO timing, NO capture!
|
|
159
|
+
return wrapped(*args, **kwargs)
|
|
160
|
+
|
|
161
|
+
wrapt.wrap_function_wrapper(
|
|
162
|
+
"httplib2", "Http.request", instrumented_request
|
|
163
|
+
)
|
|
164
|
+
else:
|
|
165
|
+
# Fallback: Direct patching if wrapt not available
|
|
166
|
+
def patched_request(
|
|
167
|
+
self, uri, method="GET", body=None, headers=None, **kwargs
|
|
168
|
+
):
|
|
169
|
+
# Ensure headers dict exists
|
|
170
|
+
if not headers:
|
|
171
|
+
headers = {}
|
|
172
|
+
elif not isinstance(headers, dict):
|
|
173
|
+
headers = dict(headers)
|
|
174
|
+
|
|
175
|
+
if SF_DEBUG:
|
|
176
|
+
_log_headers("pre-inject", headers)
|
|
177
|
+
|
|
178
|
+
# Check if headers are already injected (avoid double-injection with http.client)
|
|
179
|
+
# Fast O(1) check for common cases, fallback to O(n) for rare mixed-case variants
|
|
180
|
+
if not has_sailfish_header(headers):
|
|
181
|
+
# ULTRA-FAST: inject_headers_ultrafast does domain filtering + header injection (~100ns)
|
|
182
|
+
inject_headers_ultrafast(headers, uri, skip)
|
|
183
|
+
if SF_DEBUG:
|
|
184
|
+
_log_headers("post-inject", headers)
|
|
185
|
+
elif SF_DEBUG:
|
|
186
|
+
dup_snapshot = {
|
|
187
|
+
k: headers[k]
|
|
188
|
+
for k in headers
|
|
189
|
+
if isinstance(k, str) and k.lower() == TRACE_HEADER_LOWER
|
|
190
|
+
}
|
|
191
|
+
print(f"[httplib2.patch] Skip inject (fallback) - existing headers={dup_snapshot}", log=False)
|
|
192
|
+
|
|
193
|
+
# Immediately call original and return - NO timing, NO capture!
|
|
194
|
+
return original_request(
|
|
195
|
+
self, uri, method, body=body, headers=headers, **kwargs
|
|
196
|
+
)
|
|
197
|
+
|
|
198
|
+
httplib2.Http.request = patched_request
|
|
199
|
+
|
|
200
|
+
else:
|
|
201
|
+
# ========== FULL CAPTURE PATH: When neither LD_PRELOAD nor http.client patch is active ==========
|
|
202
|
+
# Only used when httplib2 needs to handle capture itself (rare case)
|
|
203
|
+
def patched_request(self, uri, method="GET", body=None, headers=None, **kwargs):
|
|
204
|
+
start_ts = int(time.time() * 1_000)
|
|
205
|
+
|
|
206
|
+
# Ensure headers dict exists
|
|
207
|
+
if not headers:
|
|
208
|
+
headers = {}
|
|
209
|
+
elif not isinstance(headers, dict):
|
|
210
|
+
headers = dict(headers)
|
|
211
|
+
|
|
212
|
+
if SF_DEBUG:
|
|
213
|
+
_log_headers("pre-inject-full", headers)
|
|
214
|
+
|
|
215
|
+
# Check if headers are already injected (avoid double-injection with http.client)
|
|
216
|
+
# Fast O(1) check for common cases, fallback to O(n) for rare mixed-case variants
|
|
217
|
+
if not has_sailfish_header(headers):
|
|
218
|
+
# ULTRA-FAST: inject_headers_ultrafast does domain filtering + header injection (~100ns)
|
|
219
|
+
inject_headers_ultrafast(headers, uri, skip)
|
|
220
|
+
if SF_DEBUG:
|
|
221
|
+
_log_headers("post-inject-full", headers)
|
|
222
|
+
elif SF_DEBUG:
|
|
223
|
+
dup_snapshot = {
|
|
224
|
+
k: headers[k]
|
|
225
|
+
for k in headers
|
|
226
|
+
if isinstance(k, str) and k.lower() == TRACE_HEADER_LOWER
|
|
227
|
+
}
|
|
228
|
+
print(f"[httplib2.patch] Skip inject (full path) - existing headers={dup_snapshot}", log=False)
|
|
229
|
+
|
|
230
|
+
# Skip capture for HTTPS when ssl_socket.py is active (avoids double-capture)
|
|
231
|
+
# ssl_socket.py captures ALL SSL traffic at socket layer when enabled
|
|
232
|
+
is_https = uri.startswith("https://")
|
|
233
|
+
if is_https and is_ssl_socket_active():
|
|
234
|
+
# ssl_socket.py will handle capture, just make the request
|
|
235
|
+
return original_request(self, uri, method, body=body, headers=headers, **kwargs)
|
|
236
|
+
|
|
237
|
+
# Get trace_id for capture
|
|
238
|
+
trace_id = trace_id_ctx.get(None) or ""
|
|
239
|
+
|
|
240
|
+
# Capture request data
|
|
241
|
+
req_data = b""
|
|
242
|
+
req_headers = b""
|
|
243
|
+
try:
|
|
244
|
+
if body:
|
|
245
|
+
if isinstance(body, bytes):
|
|
246
|
+
req_data = body
|
|
247
|
+
elif isinstance(body, str):
|
|
248
|
+
req_data = body.encode("utf-8")
|
|
249
|
+
|
|
250
|
+
# Capture request headers
|
|
251
|
+
if HAS_ORJSON:
|
|
252
|
+
req_headers = orjson.dumps({str(k): str(v) for k, v in headers.items()})
|
|
253
|
+
else:
|
|
254
|
+
req_headers = json.dumps({str(k): str(v) for k, v in headers.items()}).encode("utf-8")
|
|
255
|
+
except Exception: # noqa: BLE001
|
|
256
|
+
pass
|
|
257
|
+
|
|
258
|
+
try:
|
|
259
|
+
# perform the actual HTTP call
|
|
260
|
+
response, content = original_request(
|
|
261
|
+
self, uri, method, body=body, headers=headers, **kwargs
|
|
262
|
+
)
|
|
263
|
+
status_code = getattr(response, "status", None) or getattr(
|
|
264
|
+
response, "status_code", None
|
|
265
|
+
)
|
|
266
|
+
success = isinstance(status_code, int) and 200 <= status_code < 400
|
|
267
|
+
|
|
268
|
+
# Capture response data and headers
|
|
269
|
+
resp_data = b""
|
|
270
|
+
resp_headers = b""
|
|
271
|
+
|
|
272
|
+
# content is already the response body in httplib2
|
|
273
|
+
resp_data = content if isinstance(content, bytes) else b""
|
|
274
|
+
# Capture response headers
|
|
275
|
+
if HAS_ORJSON:
|
|
276
|
+
resp_headers = orjson.dumps({str(k): str(v) for k, v in response.items()})
|
|
277
|
+
else:
|
|
278
|
+
resp_headers = json.dumps({str(k): str(v) for k, v in response.items()}).encode("utf-8")
|
|
279
|
+
|
|
280
|
+
# record success (only when LD_PRELOAD is NOT active)
|
|
281
|
+
record_network_request(
|
|
282
|
+
trace_id,
|
|
283
|
+
uri,
|
|
284
|
+
method,
|
|
285
|
+
status_code,
|
|
286
|
+
success,
|
|
287
|
+
timestamp_start=start_ts,
|
|
288
|
+
timestamp_end=int(time.time() * 1_000),
|
|
289
|
+
request_data=req_data,
|
|
290
|
+
response_data=resp_data,
|
|
291
|
+
request_headers=req_headers,
|
|
292
|
+
response_headers=resp_headers,
|
|
293
|
+
)
|
|
294
|
+
|
|
295
|
+
return response, content
|
|
296
|
+
|
|
297
|
+
except Exception as e:
|
|
298
|
+
# record failures (only when LD_PRELOAD is NOT active)
|
|
299
|
+
record_network_request(
|
|
300
|
+
trace_id,
|
|
301
|
+
uri,
|
|
302
|
+
method,
|
|
303
|
+
0,
|
|
304
|
+
False,
|
|
305
|
+
error=str(e)[:255],
|
|
306
|
+
timestamp_start=start_ts,
|
|
307
|
+
timestamp_end=int(time.time() * 1_000),
|
|
308
|
+
request_data=req_data,
|
|
309
|
+
request_headers=req_headers,
|
|
310
|
+
)
|
|
311
|
+
raise
|
|
312
|
+
|
|
313
|
+
# apply our patch (only if not using wrapt in fast path)
|
|
314
|
+
if not (use_fast_path and HAS_WRAPT):
|
|
315
|
+
httplib2.Http.request = patched_request
|