sf-veritas 0.10.3__cp313-cp313-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.

Potentially problematic release.


This version of sf-veritas might be problematic. Click here for more details.

Files changed (132) hide show
  1. sf_veritas/__init__.py +20 -0
  2. sf_veritas/_sffastlog.c +889 -0
  3. sf_veritas/_sffastlog.cpython-313-x86_64-linux-gnu.so +0 -0
  4. sf_veritas/_sffastnet.c +924 -0
  5. sf_veritas/_sffastnet.cpython-313-x86_64-linux-gnu.so +0 -0
  6. sf_veritas/_sffastnetworkrequest.c +730 -0
  7. sf_veritas/_sffastnetworkrequest.cpython-313-x86_64-linux-gnu.so +0 -0
  8. sf_veritas/_sffuncspan.c +2155 -0
  9. sf_veritas/_sffuncspan.cpython-313-x86_64-linux-gnu.so +0 -0
  10. sf_veritas/_sffuncspan_config.c +617 -0
  11. sf_veritas/_sffuncspan_config.cpython-313-x86_64-linux-gnu.so +0 -0
  12. sf_veritas/_sfheadercheck.c +341 -0
  13. sf_veritas/_sfheadercheck.cpython-313-x86_64-linux-gnu.so +0 -0
  14. sf_veritas/_sfnetworkhop.c +1451 -0
  15. sf_veritas/_sfnetworkhop.cpython-313-x86_64-linux-gnu.so +0 -0
  16. sf_veritas/_sfservice.c +1175 -0
  17. sf_veritas/_sfservice.cpython-313-x86_64-linux-gnu.so +0 -0
  18. sf_veritas/_sfteepreload.c +5167 -0
  19. sf_veritas/app_config.py +49 -0
  20. sf_veritas/cli.py +336 -0
  21. sf_veritas/constants.py +10 -0
  22. sf_veritas/custom_excepthook.py +304 -0
  23. sf_veritas/custom_log_handler.py +129 -0
  24. sf_veritas/custom_output_wrapper.py +144 -0
  25. sf_veritas/custom_print.py +146 -0
  26. sf_veritas/django_app.py +5 -0
  27. sf_veritas/env_vars.py +186 -0
  28. sf_veritas/exception_handling_middleware.py +18 -0
  29. sf_veritas/exception_metaclass.py +69 -0
  30. sf_veritas/fast_frame_info.py +116 -0
  31. sf_veritas/fast_network_hop.py +293 -0
  32. sf_veritas/frame_tools.py +112 -0
  33. sf_veritas/funcspan_config_loader.py +556 -0
  34. sf_veritas/function_span_profiler.py +1174 -0
  35. sf_veritas/import_hook.py +62 -0
  36. sf_veritas/infra_details/__init__.py +3 -0
  37. sf_veritas/infra_details/get_infra_details.py +24 -0
  38. sf_veritas/infra_details/kubernetes/__init__.py +3 -0
  39. sf_veritas/infra_details/kubernetes/get_cluster_name.py +147 -0
  40. sf_veritas/infra_details/kubernetes/get_details.py +7 -0
  41. sf_veritas/infra_details/running_on/__init__.py +17 -0
  42. sf_veritas/infra_details/running_on/kubernetes.py +11 -0
  43. sf_veritas/interceptors.py +497 -0
  44. sf_veritas/libsfnettee.so +0 -0
  45. sf_veritas/local_env_detect.py +118 -0
  46. sf_veritas/package_metadata.py +6 -0
  47. sf_veritas/patches/__init__.py +0 -0
  48. sf_veritas/patches/concurrent_futures.py +19 -0
  49. sf_veritas/patches/constants.py +1 -0
  50. sf_veritas/patches/exceptions.py +82 -0
  51. sf_veritas/patches/multiprocessing.py +32 -0
  52. sf_veritas/patches/network_libraries/__init__.py +76 -0
  53. sf_veritas/patches/network_libraries/aiohttp.py +281 -0
  54. sf_veritas/patches/network_libraries/curl_cffi.py +363 -0
  55. sf_veritas/patches/network_libraries/http_client.py +419 -0
  56. sf_veritas/patches/network_libraries/httpcore.py +515 -0
  57. sf_veritas/patches/network_libraries/httplib2.py +204 -0
  58. sf_veritas/patches/network_libraries/httpx.py +515 -0
  59. sf_veritas/patches/network_libraries/niquests.py +211 -0
  60. sf_veritas/patches/network_libraries/pycurl.py +385 -0
  61. sf_veritas/patches/network_libraries/requests.py +633 -0
  62. sf_veritas/patches/network_libraries/tornado.py +341 -0
  63. sf_veritas/patches/network_libraries/treq.py +270 -0
  64. sf_veritas/patches/network_libraries/urllib_request.py +468 -0
  65. sf_veritas/patches/network_libraries/utils.py +398 -0
  66. sf_veritas/patches/os.py +17 -0
  67. sf_veritas/patches/threading.py +218 -0
  68. sf_veritas/patches/web_frameworks/__init__.py +54 -0
  69. sf_veritas/patches/web_frameworks/aiohttp.py +793 -0
  70. sf_veritas/patches/web_frameworks/async_websocket_consumer.py +317 -0
  71. sf_veritas/patches/web_frameworks/blacksheep.py +527 -0
  72. sf_veritas/patches/web_frameworks/bottle.py +502 -0
  73. sf_veritas/patches/web_frameworks/cherrypy.py +678 -0
  74. sf_veritas/patches/web_frameworks/cors_utils.py +122 -0
  75. sf_veritas/patches/web_frameworks/django.py +944 -0
  76. sf_veritas/patches/web_frameworks/eve.py +395 -0
  77. sf_veritas/patches/web_frameworks/falcon.py +926 -0
  78. sf_veritas/patches/web_frameworks/fastapi.py +724 -0
  79. sf_veritas/patches/web_frameworks/flask.py +520 -0
  80. sf_veritas/patches/web_frameworks/klein.py +501 -0
  81. sf_veritas/patches/web_frameworks/litestar.py +551 -0
  82. sf_veritas/patches/web_frameworks/pyramid.py +428 -0
  83. sf_veritas/patches/web_frameworks/quart.py +824 -0
  84. sf_veritas/patches/web_frameworks/robyn.py +697 -0
  85. sf_veritas/patches/web_frameworks/sanic.py +857 -0
  86. sf_veritas/patches/web_frameworks/starlette.py +723 -0
  87. sf_veritas/patches/web_frameworks/strawberry.py +813 -0
  88. sf_veritas/patches/web_frameworks/tornado.py +481 -0
  89. sf_veritas/patches/web_frameworks/utils.py +91 -0
  90. sf_veritas/print_override.py +13 -0
  91. sf_veritas/regular_data_transmitter.py +409 -0
  92. sf_veritas/request_interceptor.py +401 -0
  93. sf_veritas/request_utils.py +550 -0
  94. sf_veritas/server_status.py +1 -0
  95. sf_veritas/shutdown_flag.py +11 -0
  96. sf_veritas/subprocess_startup.py +3 -0
  97. sf_veritas/test_cli.py +145 -0
  98. sf_veritas/thread_local.py +970 -0
  99. sf_veritas/timeutil.py +114 -0
  100. sf_veritas/transmit_exception_to_sailfish.py +28 -0
  101. sf_veritas/transmitter.py +132 -0
  102. sf_veritas/types.py +47 -0
  103. sf_veritas/unified_interceptor.py +1580 -0
  104. sf_veritas/utils.py +39 -0
  105. sf_veritas-0.10.3.dist-info/METADATA +97 -0
  106. sf_veritas-0.10.3.dist-info/RECORD +132 -0
  107. sf_veritas-0.10.3.dist-info/WHEEL +5 -0
  108. sf_veritas-0.10.3.dist-info/entry_points.txt +2 -0
  109. sf_veritas-0.10.3.dist-info/top_level.txt +1 -0
  110. sf_veritas.libs/libbrotlicommon-6ce2a53c.so.1.0.6 +0 -0
  111. sf_veritas.libs/libbrotlidec-811d1be3.so.1.0.6 +0 -0
  112. sf_veritas.libs/libcom_err-730ca923.so.2.1 +0 -0
  113. sf_veritas.libs/libcrypt-52aca757.so.1.1.0 +0 -0
  114. sf_veritas.libs/libcrypto-bdaed0ea.so.1.1.1k +0 -0
  115. sf_veritas.libs/libcurl-eaa3cf66.so.4.5.0 +0 -0
  116. sf_veritas.libs/libgssapi_krb5-323bbd21.so.2.2 +0 -0
  117. sf_veritas.libs/libidn2-2f4a5893.so.0.3.6 +0 -0
  118. sf_veritas.libs/libk5crypto-9a74ff38.so.3.1 +0 -0
  119. sf_veritas.libs/libkeyutils-2777d33d.so.1.6 +0 -0
  120. sf_veritas.libs/libkrb5-a55300e8.so.3.3 +0 -0
  121. sf_veritas.libs/libkrb5support-e6594cfc.so.0.1 +0 -0
  122. sf_veritas.libs/liblber-2-d20824ef.4.so.2.10.9 +0 -0
  123. sf_veritas.libs/libldap-2-cea2a960.4.so.2.10.9 +0 -0
  124. sf_veritas.libs/libnghttp2-39367a22.so.14.17.0 +0 -0
  125. sf_veritas.libs/libpcre2-8-516f4c9d.so.0.7.1 +0 -0
  126. sf_veritas.libs/libpsl-99becdd3.so.5.3.1 +0 -0
  127. sf_veritas.libs/libsasl2-7de4d792.so.3.0.0 +0 -0
  128. sf_veritas.libs/libselinux-d0805dcb.so.1 +0 -0
  129. sf_veritas.libs/libssh-c11d285b.so.4.8.7 +0 -0
  130. sf_veritas.libs/libssl-60250281.so.1.1.1k +0 -0
  131. sf_veritas.libs/libunistring-05abdd40.so.2.1.0 +0 -0
  132. sf_veritas.libs/libuuid-95b83d40.so.1.3.0 +0 -0
@@ -0,0 +1,633 @@
1
+ """
2
+ Monkey-patch the `requests` stack (requests → urllib3 → http.client):
3
+
4
+ • For every outbound request, propagate the SAILFISH_TRACING_HEADER + FUNCSPAN_OVERRIDE_HEADER
5
+ unless the destination host is in `domains_to_not_propagate_headers_to`.
6
+ • Fire NetworkRequestTransmitter via utils.record_network_request
7
+ so we always capture (url, status, timings, success, error).
8
+ • When LD_PRELOAD is active, ONLY inject headers (skip capture - socket layer handles it).
9
+ """
10
+
11
+ from __future__ import annotations
12
+
13
+ import http.client
14
+ import os
15
+ import time
16
+ from typing import Dict, List, Optional, Tuple
17
+
18
+ import requests
19
+ import urllib3
20
+ from requests.sessions import Session
21
+
22
+ try:
23
+ import wrapt
24
+
25
+ HAS_WRAPT = True
26
+ except ImportError:
27
+ HAS_WRAPT = False
28
+
29
+ # JSON serialization - try fast orjson first, fallback to stdlib json
30
+ try:
31
+ import orjson
32
+
33
+ HAS_ORJSON = True
34
+ except ImportError:
35
+ import json
36
+
37
+ HAS_ORJSON = False
38
+
39
+
40
+ from ...constants import FUNCSPAN_OVERRIDE_HEADER, SAILFISH_TRACING_HEADER
41
+ from ...thread_local import (
42
+ activate_reentrancy_guards_exception,
43
+ activate_reentrancy_guards_logging,
44
+ activate_reentrancy_guards_print,
45
+ get_funcspan_override,
46
+ )
47
+ from .utils import (
48
+ get_trace_and_should_propagate,
49
+ get_trace_and_should_propagate_fast,
50
+ init_fast_header_check,
51
+ inject_headers_ultrafast,
52
+ record_network_request,
53
+ )
54
+
55
+ ###############################################################################
56
+ # Internal helpers
57
+ ###############################################################################
58
+
59
+ # header names used for re-entrancy guards
60
+ REENTRANCY_GUARD_LOGGING_PREACTIVE = "reentrancy_guard_logging_preactive"
61
+ REENTRANCY_GUARD_PRINT_PREACTIVE = "reentrancy_guard_print_preactive"
62
+ REENTRANCY_GUARD_EXCEPTIONS_PREACTIVE = "reentrancy_guard_exception_preactive"
63
+
64
+
65
+ def _tee_preload_active() -> bool:
66
+ """Detect if LD_PRELOAD tee is active (same logic as http_client.py)."""
67
+ if os.getenv("SF_TEE_PRELOAD_ONLY", "0") == "1":
68
+ return True
69
+ ld = os.getenv("LD_PRELOAD", "")
70
+ return "libsfnettee.so" in ld or "_sfteepreload" in ld
71
+
72
+
73
+ # PERFORMANCE: Reentrancy guards disabled - they add ~10-20μs per request
74
+ # The socket layer (LD_PRELOAD) handles everything we need
75
+ # def _activate_rg(headers: Dict[str, str]) -> None:
76
+ # """Turn the three 'preactive' guard flags ON for downstream hops."""
77
+ # headers[REENTRANCY_GUARD_LOGGING_PREACTIVE] = "true"
78
+ # headers[REENTRANCY_GUARD_PRINT_PREACTIVE] = "true"
79
+ # headers[REENTRANCY_GUARD_EXCEPTIONS_PREACTIVE] = "true"
80
+
81
+
82
+ # def _check_rg(headers: Dict[str, str]) -> None:
83
+ # """If any pre-active guard present, switch the corresponding guard on."""
84
+ # if headers.get(REENTRANCY_GUARD_LOGGING_PREACTIVE, "false").lower() == "true":
85
+ # activate_reentrancy_guards_logging()
86
+ # if headers.get(REENTRANCY_GUARD_PRINT_PREACTIVE, "false").lower() == "true":
87
+ # activate_reentrancy_guards_print()
88
+ # if headers.get(REENTRANCY_GUARD_EXCEPTIONS_PREACTIVE, "false").lower() == "true":
89
+ # activate_reentrancy_guards_exception()
90
+
91
+
92
+ def _prepare(
93
+ url: str,
94
+ domains_to_skip: List[str],
95
+ headers: Optional[Dict[str, str]],
96
+ ) -> Tuple[str, Dict[str, str], int]:
97
+ """
98
+ Inject trace header + funcspan override header (unless excluded) and return:
99
+ trace_id, merged_headers, timestamp_ms
100
+
101
+ ULTRA-FAST: <20ns overhead for header injection.
102
+
103
+ PERFORMANCE: Reentrancy guards removed - saves ~10-20μs per request.
104
+ """
105
+ trace_id, propagate = get_trace_and_should_propagate(url, domains_to_skip)
106
+ hdrs: Dict[str, str] = dict(headers or {})
107
+ # _check_rg(hdrs) # DISABLED for performance
108
+ if propagate:
109
+ hdrs[SAILFISH_TRACING_HEADER] = trace_id
110
+
111
+ # Inject funcspan override header if present (ContextVar lookup ~8ns)
112
+ try:
113
+ funcspan_override = get_funcspan_override()
114
+ if funcspan_override is not None:
115
+ hdrs[FUNCSPAN_OVERRIDE_HEADER] = funcspan_override
116
+ except Exception:
117
+ pass
118
+
119
+ # _activate_rg(hdrs) # DISABLED for performance
120
+ return trace_id, hdrs, int(time.time() * 1_000)
121
+
122
+
123
+ def _capture_and_record_requests(
124
+ resp, trace_id, url, method, status, success, err, t0, t1, req_data, hdrs
125
+ ):
126
+ """Capture response data in background thread AFTER response is returned to user."""
127
+ resp_data: bytes = b""
128
+ req_headers: bytes = b""
129
+ resp_headers: bytes = b""
130
+
131
+ try:
132
+ # Capture headers efficiently
133
+ if HAS_ORJSON:
134
+ req_headers = orjson.dumps({str(k): str(v) for k, v in hdrs.items()})
135
+ if resp:
136
+ resp_headers = orjson.dumps({str(k): str(v) for k, v in resp.headers.items()})
137
+ else:
138
+ req_headers = json.dumps({str(k): str(v) for k, v in hdrs.items()}).encode("utf-8")
139
+ if resp:
140
+ resp_headers = json.dumps({str(k): str(v) for k, v in resp.headers.items()}).encode("utf-8")
141
+
142
+ # For response body: check if already cached in _content
143
+ if resp:
144
+ try:
145
+ if hasattr(resp, "_content") and resp._content is not None:
146
+ resp_data = resp._content
147
+ except Exception: # noqa: BLE001
148
+ pass
149
+ except Exception: # noqa: BLE001
150
+ pass
151
+
152
+ # Send to C extension in background
153
+ record_network_request(
154
+ trace_id,
155
+ url,
156
+ method,
157
+ status,
158
+ success,
159
+ err,
160
+ timestamp_start=t0,
161
+ timestamp_end=t1,
162
+ request_data=req_data,
163
+ response_data=resp_data,
164
+ request_headers=req_headers,
165
+ response_headers=resp_headers,
166
+ )
167
+
168
+
169
+ def _capture_and_record_urllib3(
170
+ resp, trace_id, url, method, status, success, err, t0, t1, req_data, hdrs
171
+ ):
172
+ """Capture urllib3 response data in background thread AFTER response is returned to user."""
173
+ resp_data: bytes = b""
174
+ req_headers: bytes = b""
175
+ resp_headers: bytes = b""
176
+
177
+ try:
178
+ # Capture headers efficiently
179
+ if HAS_ORJSON:
180
+ req_headers = orjson.dumps({str(k): str(v) for k, v in hdrs.items()})
181
+ if resp:
182
+ resp_headers = orjson.dumps({str(k): str(v) for k, v in resp.headers.items()})
183
+ else:
184
+ req_headers = json.dumps({str(k): str(v) for k, v in hdrs.items()}).encode("utf-8")
185
+ if resp:
186
+ resp_headers = json.dumps({str(k): str(v) for k, v in resp.headers.items()}).encode("utf-8")
187
+
188
+ # For response body: check if already available in data attribute
189
+ if resp:
190
+ try:
191
+ resp_data = getattr(resp, "data", b"")
192
+ except Exception: # noqa: BLE001
193
+ pass
194
+ except Exception: # noqa: BLE001
195
+ pass
196
+
197
+ # Send to C extension in background
198
+ record_network_request(
199
+ trace_id,
200
+ url,
201
+ method,
202
+ status,
203
+ success,
204
+ err,
205
+ timestamp_start=t0,
206
+ timestamp_end=t1,
207
+ request_data=req_data,
208
+ response_data=resp_data,
209
+ request_headers=req_headers,
210
+ response_headers=resp_headers,
211
+ )
212
+
213
+
214
+ def _capture_and_record_http_client(
215
+ resp, trace_id, url, method, status, success, err, t0, t1, req_data, hdrs
216
+ ):
217
+ """Capture http.client response data in background thread AFTER response is returned to user."""
218
+ resp_data: bytes = b""
219
+ req_headers: bytes = b""
220
+ resp_headers: bytes = b""
221
+
222
+ try:
223
+ # Capture headers efficiently
224
+ if HAS_ORJSON:
225
+ req_headers = orjson.dumps({str(k): str(v) for k, v in hdrs.items()})
226
+ else:
227
+ req_headers = json.dumps({str(k): str(v) for k, v in hdrs.items()}).encode("utf-8")
228
+
229
+ # http.client doesn't easily expose response data, skip body capture
230
+ except Exception: # noqa: BLE001
231
+ pass
232
+
233
+ # Send to C extension in background
234
+ record_network_request(
235
+ trace_id,
236
+ url,
237
+ method,
238
+ status,
239
+ success,
240
+ err,
241
+ timestamp_start=t0,
242
+ timestamp_end=t1,
243
+ request_data=req_data,
244
+ response_data=resp_data,
245
+ request_headers=req_headers,
246
+ response_headers=resp_headers,
247
+ )
248
+
249
+
250
+ ###############################################################################
251
+ # Top-level patch function
252
+ ###############################################################################
253
+ def patch_requests(domains_to_not_propagate_headers_to: Optional[List[str]] = None):
254
+ """
255
+ Apply all monkey-patches. Safe to call multiple times.
256
+
257
+ When LD_PRELOAD is active:
258
+ - ALWAYS inject headers (trace_id + funcspan_override)
259
+ - SKIP capture/emission (LD_PRELOAD handles at socket layer)
260
+ """
261
+ exclude = domains_to_not_propagate_headers_to or []
262
+ preload_active = _tee_preload_active()
263
+
264
+ # PERFORMANCE DEBUG: Log preload detection
265
+ SF_DEBUG = os.getenv("SF_DEBUG", "false").lower() == "true"
266
+ if SF_DEBUG:
267
+ ld_preload = os.getenv("LD_PRELOAD", "")
268
+ print(f"[[patch_requests]] LD_PRELOAD={ld_preload}", flush=True)
269
+ print(f"[[patch_requests]] preload_active={preload_active}", flush=True)
270
+ print(
271
+ f"[[patch_requests]] Using {'ULTRA-FAST' if preload_active else 'FULL CAPTURE'} path",
272
+ flush=True,
273
+ )
274
+
275
+ # Initialize C extension for ultra-fast header checking (if available)
276
+ if preload_active:
277
+ init_fast_header_check(exclude)
278
+
279
+ # --------------------------------------------------------------------- #
280
+ # 1. Patch `requests.Session.request`
281
+ # --------------------------------------------------------------------- #
282
+ # Save original function BEFORE any patching
283
+ original_request = Session.request
284
+
285
+ if preload_active:
286
+ # ========== ULTRA-FAST PATH: When LD_PRELOAD is active ==========
287
+ if HAS_WRAPT:
288
+ # FASTEST: Use wrapt directly (OTEL-style for minimal overhead)
289
+ def instrumented_request(wrapped, instance, args, kwargs):
290
+ """ULTRA-FAST header injection (<100ns) via wrapt."""
291
+ # args = (method, url, ...), kwargs = {...}
292
+ url = args[1] if len(args) > 1 else kwargs.get("url", "")
293
+
294
+ # OPTIMIZED: Avoid kwargs.pop() - use get() with or-pattern (10x faster!)
295
+ headers = kwargs.get("headers") or {}
296
+
297
+ # CRITICAL: Skip if already injected (prevents double injection in requests→urllib3→http.client chain)
298
+ if SAILFISH_TRACING_HEADER not in headers:
299
+ # ULTRA-FAST: Thread-local cache + direct ContextVar.get() (<100ns!)
300
+ inject_headers_ultrafast(headers, url, exclude)
301
+
302
+ kwargs["headers"] = headers
303
+
304
+ # NO timing, NO capture, NO threads - immediate return!
305
+ return wrapped(*args, **kwargs)
306
+
307
+ wrapt.wrap_function_wrapper(Session, "request", instrumented_request)
308
+ else:
309
+ # Fallback: Direct patching if wrapt not available
310
+ def patched_request(self: Session, method, url, **kwargs): # type: ignore[override]
311
+ # OPTIMIZED: Avoid kwargs.pop() - use get() with or-pattern (10x faster!)
312
+ headers = kwargs.get("headers") or {}
313
+
314
+ # CRITICAL: Skip if already injected (prevents double injection in requests→urllib3→http.client chain)
315
+ if SAILFISH_TRACING_HEADER not in headers:
316
+ # ULTRA-FAST: Thread-local cache + direct ContextVar.get() (<100ns!)
317
+ inject_headers_ultrafast(headers, url, exclude)
318
+
319
+ kwargs["headers"] = headers
320
+
321
+ # NO timing, NO capture, NO threads - immediate return!
322
+ return original_request(self, method, url, **kwargs)
323
+
324
+ Session.request = patched_request
325
+ requests.Session.request = (
326
+ patched_request # cover direct `requests.Session(...)`
327
+ )
328
+
329
+ else:
330
+ # ========== FULL CAPTURE PATH: When LD_PRELOAD is NOT active ==========
331
+ # PERFORMANCE: Removed thread spawning - saves ~50-200μs per request
332
+ # Direct C extension call instead of background threads
333
+ def patched_request(self: Session, method, url, **kwargs): # type: ignore[override]
334
+ # --- header handling / injection --------------------------------- #
335
+ trace_id, hdrs, t0 = _prepare(url, exclude, kwargs.pop("headers", {}))
336
+ kwargs["headers"] = hdrs
337
+
338
+ status: int = 0
339
+ success: bool = False
340
+ err: str | None = None
341
+ req_data: bytes = b""
342
+
343
+ # PERFORMANCE: Skip request body capture - saves ~10-50μs
344
+ # C extension captures everything at socket layer
345
+ # try:
346
+ # if "json" in kwargs:
347
+ # try:
348
+ # import orjson
349
+ # req_data = orjson.dumps(kwargs["json"])
350
+ # except ImportError:
351
+ # import json
352
+ # req_data = json.dumps(kwargs["json"]).encode('utf-8')
353
+ # elif "data" in kwargs:
354
+ # data = kwargs["data"]
355
+ # if isinstance(data, bytes):
356
+ # req_data = data
357
+ # elif isinstance(data, str):
358
+ # req_data = data.encode('utf-8')
359
+ # except Exception: # noqa: BLE001
360
+ # pass
361
+
362
+ try:
363
+ resp = original_request(self, method, url, **kwargs)
364
+ status = resp.status_code
365
+ success = resp.ok
366
+ t1 = int(time.time() * 1_000)
367
+
368
+ # PERFORMANCE: Direct C call (NO thread spawning!) - saves ~50-200μs
369
+ record_network_request(
370
+ trace_id,
371
+ url,
372
+ str(method).upper(),
373
+ status,
374
+ success,
375
+ None,
376
+ timestamp_start=t0,
377
+ timestamp_end=t1,
378
+ request_data=req_data,
379
+ response_data=b"",
380
+ request_headers=b"",
381
+ response_headers=b"",
382
+ )
383
+
384
+ return resp
385
+ except Exception as exc: # noqa: BLE001
386
+ err = str(exc)[:255]
387
+ t1 = int(time.time() * 1_000)
388
+ # PERFORMANCE: Direct C call (NO thread spawning!)
389
+ record_network_request(
390
+ trace_id,
391
+ url,
392
+ str(method).upper(),
393
+ status,
394
+ success,
395
+ err,
396
+ timestamp_start=t0,
397
+ timestamp_end=t1,
398
+ request_data=req_data,
399
+ response_data=b"",
400
+ request_headers=b"",
401
+ response_headers=b"",
402
+ )
403
+ raise
404
+
405
+ if not HAS_WRAPT:
406
+ Session.request = patched_request
407
+ requests.Session.request = (
408
+ patched_request # cover direct `requests.Session(...)`
409
+ )
410
+
411
+ # --------------------------------------------------------------------- #
412
+ # 2. Patch urllib3's low-level ConnectionPool.urlopen (used by requests)
413
+ # --------------------------------------------------------------------- #
414
+ # Save original function BEFORE any patching
415
+ original_urlopen = urllib3.connectionpool.HTTPConnectionPool.urlopen
416
+
417
+ if preload_active:
418
+ # ========== ULTRA-FAST PATH: When LD_PRELOAD is active ==========
419
+ if HAS_WRAPT:
420
+ # FASTEST: Use wrapt directly (OTEL-style for minimal overhead)
421
+ def instrumented_urlopen(wrapped, instance, args, kwargs):
422
+ """ULTRA-FAST header injection (<100ns) via wrapt."""
423
+ # args = (method, url, ...), kwargs = {body, headers, ...}
424
+ url = args[1] if len(args) > 1 else kwargs.get("url", "")
425
+
426
+ # OPTIMIZED: Use or-pattern (10x faster!)
427
+ headers = kwargs.get("headers") or {}
428
+
429
+ # CRITICAL: Skip if already injected by requests.Session (prevents double injection)
430
+ if SAILFISH_TRACING_HEADER not in headers:
431
+ # ULTRA-FAST: Thread-local cache + direct ContextVar.get() (<100ns!)
432
+ inject_headers_ultrafast(headers, url, exclude)
433
+
434
+ kwargs["headers"] = headers
435
+
436
+ # NO timing, NO capture, NO threads - immediate return!
437
+ return wrapped(*args, **kwargs)
438
+
439
+ wrapt.wrap_function_wrapper(
440
+ urllib3.connectionpool.HTTPConnectionPool,
441
+ "urlopen",
442
+ instrumented_urlopen,
443
+ )
444
+ else:
445
+ # Fallback: Direct patching if wrapt not available
446
+ def patched_urlopen(self, method, url, body=None, headers=None, **kw): # type: ignore[override]
447
+ # OPTIMIZED: Use or-pattern (10x faster!)
448
+ headers = headers or {}
449
+
450
+ # CRITICAL: Skip if already injected by requests.Session (prevents double injection)
451
+ if SAILFISH_TRACING_HEADER not in headers:
452
+ # ULTRA-FAST: Thread-local cache + direct ContextVar.get() (<100ns!)
453
+ inject_headers_ultrafast(headers, url, exclude)
454
+
455
+ # NO timing, NO capture, NO threads - immediate return!
456
+ return original_urlopen(
457
+ self, method, url, body=body, headers=headers, **kw
458
+ )
459
+
460
+ urllib3.connectionpool.HTTPConnectionPool.urlopen = patched_urlopen
461
+
462
+ else:
463
+ # ========== FULL CAPTURE PATH: When LD_PRELOAD is NOT active ==========
464
+ # PERFORMANCE: Removed thread spawning and body capture
465
+ def patched_urlopen(self, method, url, body=None, headers=None, **kw): # type: ignore[override]
466
+ trace_id, hdrs, t0 = _prepare(url, exclude, headers)
467
+ status: int = 0
468
+ success: bool = False
469
+ err: str | None = None
470
+
471
+ try:
472
+ resp = original_urlopen(
473
+ self, method, url, body=body, headers=hdrs, **kw
474
+ )
475
+ status = getattr(resp, "status", 0)
476
+ success = status < 400
477
+ t1 = int(time.time() * 1_000)
478
+
479
+ # PERFORMANCE: Direct C call (NO thread spawning!)
480
+ record_network_request(
481
+ trace_id,
482
+ url,
483
+ str(method).upper(),
484
+ status,
485
+ success,
486
+ None,
487
+ timestamp_start=t0,
488
+ timestamp_end=t1,
489
+ request_data=b"",
490
+ response_data=b"",
491
+ request_headers=b"",
492
+ response_headers=b"",
493
+ )
494
+
495
+ return resp
496
+ except Exception as exc: # noqa: BLE001
497
+ err = str(exc)[:255]
498
+ t1 = int(time.time() * 1_000)
499
+ record_network_request(
500
+ trace_id,
501
+ url,
502
+ str(method).upper(),
503
+ status,
504
+ success,
505
+ err,
506
+ timestamp_start=t0,
507
+ timestamp_end=t1,
508
+ request_data=b"",
509
+ response_data=b"",
510
+ request_headers=b"",
511
+ response_headers=b"",
512
+ )
513
+ raise
514
+
515
+ if not HAS_WRAPT:
516
+ urllib3.connectionpool.HTTPConnectionPool.urlopen = patched_urlopen
517
+
518
+ # --------------------------------------------------------------------- #
519
+ # 3. Patch http.client for "raw" stdlib usage (rare but easy to support)
520
+ # --------------------------------------------------------------------- #
521
+ # Save original function BEFORE any patching
522
+ original_http_client_request = http.client.HTTPConnection.request
523
+
524
+ if preload_active:
525
+ # ========== ULTRA-FAST PATH: When LD_PRELOAD is active ==========
526
+ if HAS_WRAPT:
527
+ # FASTEST: Use wrapt directly (OTEL-style for minimal overhead)
528
+ def instrumented_http_request(wrapped, instance, args, kwargs):
529
+ """ULTRA-FAST header injection (<100ns) via wrapt."""
530
+ # args = (method, url, ...), kwargs = {body, headers, encode_chunked, ...}
531
+ url = args[1] if len(args) > 1 else kwargs.get("url", "")
532
+
533
+ # OPTIMIZED: Use or-pattern (10x faster!)
534
+ headers = kwargs.get("headers") or {}
535
+
536
+ # CRITICAL: Skip if already injected by requests/urllib3 (prevents triple injection)
537
+ if SAILFISH_TRACING_HEADER not in headers:
538
+ # ULTRA-FAST: Thread-local cache + direct ContextVar.get() (<100ns!)
539
+ inject_headers_ultrafast(headers, url, exclude)
540
+
541
+ kwargs["headers"] = headers
542
+
543
+ # NO timing, NO capture, NO threads - immediate return!
544
+ return wrapped(*args, **kwargs)
545
+
546
+ wrapt.wrap_function_wrapper(
547
+ http.client.HTTPConnection, "request", instrumented_http_request
548
+ )
549
+ else:
550
+ # Fallback: Direct patching if wrapt not available
551
+ def patched_http_request(self, method, url, body=None, headers=None, *, encode_chunked=False): # type: ignore[override]
552
+ # OPTIMIZED: Use or-pattern (10x faster!)
553
+ headers = headers or {}
554
+
555
+ # CRITICAL: Skip if already injected by requests/urllib3 (prevents triple injection)
556
+ if SAILFISH_TRACING_HEADER not in headers:
557
+ # ULTRA-FAST: Thread-local cache + direct ContextVar.get() (<100ns!)
558
+ inject_headers_ultrafast(headers, url, exclude)
559
+
560
+ # NO timing, NO capture, NO threads - immediate return!
561
+ return original_http_client_request(
562
+ self,
563
+ method,
564
+ url,
565
+ body=body,
566
+ headers=headers,
567
+ encode_chunked=encode_chunked,
568
+ )
569
+
570
+ http.client.HTTPConnection.request = patched_http_request
571
+
572
+ else:
573
+ # ========== FULL CAPTURE PATH: When LD_PRELOAD is NOT active ==========
574
+ # PERFORMANCE: Removed thread spawning and body capture
575
+ def patched_http_request(self, method, url, body=None, headers=None, *, encode_chunked=False): # type: ignore[override]
576
+ trace_id, hdrs, t0 = _prepare(url, exclude, headers)
577
+ status: int = 0
578
+ success: bool = False
579
+ err: str | None = None
580
+
581
+ try:
582
+ resp = original_http_client_request(
583
+ self,
584
+ method,
585
+ url,
586
+ body=body,
587
+ headers=hdrs,
588
+ encode_chunked=encode_chunked,
589
+ )
590
+ status = getattr(
591
+ self, "response", getattr(resp, "status", 0)
592
+ ) # best-effort
593
+ success = bool(status) and status < 400
594
+ t1 = int(time.time() * 1_000)
595
+
596
+ # PERFORMANCE: Direct C call (NO thread spawning!)
597
+ record_network_request(
598
+ trace_id,
599
+ url,
600
+ str(method).upper(),
601
+ status,
602
+ success,
603
+ None,
604
+ timestamp_start=t0,
605
+ timestamp_end=t1,
606
+ request_data=b"",
607
+ response_data=b"",
608
+ request_headers=b"",
609
+ response_headers=b"",
610
+ )
611
+
612
+ return resp
613
+ except Exception as exc: # noqa: BLE001
614
+ err = str(exc)[:255]
615
+ t1 = int(time.time() * 1_000)
616
+ record_network_request(
617
+ trace_id,
618
+ url,
619
+ str(method).upper(),
620
+ status,
621
+ success,
622
+ err,
623
+ timestamp_start=t0,
624
+ timestamp_end=t1,
625
+ request_data=b"",
626
+ response_data=b"",
627
+ request_headers=b"",
628
+ response_headers=b"",
629
+ )
630
+ raise
631
+
632
+ if not HAS_WRAPT:
633
+ http.client.HTTPConnection.request = patched_http_request