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,317 @@
1
+ import inspect
2
+ import sys
3
+ import sysconfig
4
+ from functools import lru_cache, wraps
5
+ from typing import Any, Callable, Optional, Set, Tuple
6
+
7
+ from ...constants import SAILFISH_TRACING_HEADER
8
+ from ...custom_excepthook import custom_excepthook
9
+ from ...env_vars import (
10
+ PRINT_CONFIGURATION_STATUSES,
11
+ SF_DEBUG,
12
+ SF_NETWORKHOP_CAPTURE_REQUEST_BODY,
13
+ SF_NETWORKHOP_CAPTURE_REQUEST_HEADERS,
14
+ SF_NETWORKHOP_CAPTURE_RESPONSE_BODY,
15
+ SF_NETWORKHOP_CAPTURE_RESPONSE_HEADERS,
16
+ SF_NETWORKHOP_REQUEST_LIMIT_MB,
17
+ SF_NETWORKHOP_RESPONSE_LIMIT_MB,
18
+ )
19
+ from ...thread_local import get_or_set_sf_trace_id
20
+ from ...fast_network_hop import fast_send_network_hop_fast, fast_send_network_hop, register_endpoint
21
+ from .utils import _unwrap_user_func
22
+
23
+ # Size limits in bytes
24
+ _REQUEST_LIMIT_BYTES = SF_NETWORKHOP_REQUEST_LIMIT_MB * 1024 * 1024
25
+ _RESPONSE_LIMIT_BYTES = SF_NETWORKHOP_RESPONSE_LIMIT_MB * 1024 * 1024
26
+
27
+ # Pre-registered endpoint IDs
28
+ _ENDPOINT_REGISTRY: dict[tuple, int] = {}
29
+
30
+ # ────────────────────────────────────────────────────
31
+ # User-code predicate: skip stdlib & site-packages
32
+ # ────────────────────────────────────────────────────
33
+ _STDLIB = sysconfig.get_paths()["stdlib"]
34
+ _SITE_TAGS = ("site-packages", "dist-packages")
35
+ _SKIP_PREFIXES = (_STDLIB, "/usr/local/lib/python", "/usr/lib/python")
36
+
37
+
38
+ @lru_cache(maxsize=512)
39
+ def _is_user_code(path: Optional[str] = None) -> bool:
40
+ """True only for your application files."""
41
+ if not path or path.startswith("<"):
42
+ return False
43
+ for p in _SKIP_PREFIXES:
44
+ if path.startswith(p):
45
+ return False
46
+ return not any(tag in path for tag in _SITE_TAGS)
47
+
48
+
49
+ # ────────────────────────────────────────────────────
50
+ # Patch AsyncConsumer.__call__ to hook connect + receive
51
+ # ────────────────────────────────────────────────────
52
+ def patch_async_consumer_call():
53
+ """
54
+ Wraps AsyncConsumer.__call__ so that for each HTTP or WebSocket
55
+ connection:
56
+ 1) SAILFISH_TRACING_HEADER → ContextVar
57
+ 2) Emit a NetworkHop at first user frame in websocket_connect
58
+ 3) Dynamically wrap websocket_receive to emit a hop on first message
59
+ 4) Forward any exception to custom_excepthook
60
+ """
61
+ try:
62
+ from channels.consumer import AsyncConsumer # type: ignore
63
+
64
+ orig_call = AsyncConsumer.__call__
65
+ except:
66
+ if PRINT_CONFIGURATION_STATUSES:
67
+ print("Channels AsyncConsumer not found; skipping patch", log=False)
68
+ return
69
+
70
+ if PRINT_CONFIGURATION_STATUSES:
71
+ print("Patching AsyncConsumer.__call__ for NetworkHops", log=False)
72
+
73
+ @wraps(orig_call)
74
+ async def custom_call(self, scope, receive, send):
75
+ # — Propagate header into ContextVar —
76
+ header_val = None
77
+ if scope["type"] in ("http", "websocket"):
78
+ for name, val in scope.get("headers", []):
79
+ if name.lower() == SAILFISH_TRACING_HEADER.lower().encode():
80
+ header_val = val.decode("utf-8")
81
+ break
82
+ get_or_set_sf_trace_id(header_val, is_associated_with_inbound_request=True)
83
+
84
+ # — Capture request headers if enabled —
85
+ req_headers = None
86
+ if SF_NETWORKHOP_CAPTURE_REQUEST_HEADERS:
87
+ try:
88
+ headers = scope.get("headers", [])
89
+ req_headers = {
90
+ name.decode("utf-8"): val.decode("utf-8")
91
+ for name, val in headers
92
+ }
93
+ if SF_DEBUG:
94
+ print(f"[[async_websocket_consumer]] Captured request headers: {len(req_headers)} headers", log=False)
95
+ except Exception as e:
96
+ if SF_DEBUG:
97
+ print(f"[[async_websocket_consumer]] Failed to capture request headers: {e}", log=False)
98
+
99
+ # — Capture request body if enabled (for HTTP, not WebSocket) —
100
+ req_body = None
101
+ body_parts = []
102
+ body_size = 0
103
+ if SF_NETWORKHOP_CAPTURE_REQUEST_BODY and scope["type"] == "http":
104
+ try:
105
+ # Save original receive before wrapping
106
+ original_receive = receive
107
+
108
+ async def receive_with_body():
109
+ nonlocal body_size
110
+ message = await original_receive()
111
+ if message["type"] == "http.request":
112
+ body_part = message.get("body", b"")
113
+ if body_part and body_size < _REQUEST_LIMIT_BYTES:
114
+ remaining = _REQUEST_LIMIT_BYTES - body_size
115
+ body_parts.append(body_part[:remaining])
116
+ body_size += len(body_part)
117
+ return message
118
+
119
+ receive = receive_with_body
120
+ except Exception as e:
121
+ if SF_DEBUG:
122
+ print(f"[[async_websocket_consumer]] Failed to setup request body capture: {e}", log=False)
123
+
124
+ # OTEL-STYLE: Capture endpoint info and pre-register
125
+ endpoint_id = None
126
+ endpoint_metadata = {} # Store metadata for fallback
127
+
128
+ def tracer(frame, event, _arg):
129
+ nonlocal endpoint_id
130
+ if event == "call":
131
+ fn_path = frame.f_code.co_filename
132
+ fn_name = frame.f_code.co_name
133
+
134
+ if SF_DEBUG:
135
+ print(
136
+ f"[[async_websocket_consumer]] Tracer saw: {fn_name} @ {fn_path}:{frame.f_lineno} "
137
+ f"is_user_code={_is_user_code(fn_path)}",
138
+ log=False,
139
+ )
140
+
141
+ if _is_user_code(fn_path):
142
+ hop_key = (fn_path, frame.f_lineno)
143
+
144
+ # Store metadata for potential fallback
145
+ endpoint_metadata["filename"] = fn_path
146
+ endpoint_metadata["line"] = frame.f_lineno
147
+ endpoint_metadata["name"] = fn_name
148
+
149
+ # Pre-register endpoint if not already registered
150
+ endpoint_id = _ENDPOINT_REGISTRY.get(hop_key)
151
+ if endpoint_id is None:
152
+ if SF_DEBUG:
153
+ # Debug: Check if fast network hop is available
154
+ from ...fast_network_hop import _NETWORKHOP_FAST_OK, _FAST_NETWORKHOP_READY
155
+ print(
156
+ f"[[async_websocket_consumer]] Before register: _NETWORKHOP_FAST_OK={_NETWORKHOP_FAST_OK}, "
157
+ f"_FAST_NETWORKHOP_READY={_FAST_NETWORKHOP_READY}",
158
+ log=False,
159
+ )
160
+
161
+ endpoint_id = register_endpoint(
162
+ line=str(frame.f_lineno),
163
+ column="0",
164
+ name=fn_name,
165
+ entrypoint=fn_path,
166
+ route=None
167
+ )
168
+ if SF_DEBUG:
169
+ print(
170
+ f"[[async_websocket_consumer]] register_endpoint returned: {endpoint_id}",
171
+ log=False,
172
+ )
173
+
174
+ if endpoint_id >= 0:
175
+ _ENDPOINT_REGISTRY[hop_key] = endpoint_id
176
+ if SF_DEBUG:
177
+ print(
178
+ f"[[async_websocket_consumer]] Registered endpoint: {fn_name} @ "
179
+ f"{fn_path}:{frame.f_lineno} (id={endpoint_id})",
180
+ log=False,
181
+ )
182
+
183
+ if SF_DEBUG:
184
+ print(
185
+ f"[[async_websocket_consumer]] Captured endpoint: {fn_name} "
186
+ f"({fn_path}:{frame.f_lineno}) endpoint_id={endpoint_id}",
187
+ log=False,
188
+ )
189
+
190
+ sys.setprofile(None)
191
+ return None
192
+ return tracer
193
+
194
+ sys.setprofile(tracer)
195
+
196
+ # Track if we've emitted for this connection
197
+ hop_emitted = False
198
+
199
+ # Emit NetworkHop function - called when websocket_connect completes
200
+ def emit_network_hop_sync():
201
+ """Emit NetworkHop after websocket_connect handler runs."""
202
+ nonlocal hop_emitted
203
+ if hop_emitted:
204
+ return
205
+ hop_emitted = True
206
+
207
+ if endpoint_id is not None and endpoint_id >= 0:
208
+ # Fast path with C extension
209
+ try:
210
+ _, session_id = get_or_set_sf_trace_id()
211
+
212
+ # Extract raw path and query string from scope for C to parse
213
+ raw_path = scope.get("path", None) # e.g., "/ws/chat"
214
+ raw_query = scope.get("query_string", b"") # e.g., b"room=123"
215
+
216
+ fast_send_network_hop_fast(
217
+ session_id=session_id,
218
+ endpoint_id=endpoint_id,
219
+ raw_path=raw_path,
220
+ raw_query_string=raw_query,
221
+ request_headers=req_headers,
222
+ request_body=None, # WebSocket has no body
223
+ response_headers=None,
224
+ response_body=None,
225
+ )
226
+ if SF_DEBUG:
227
+ print(
228
+ f"[[async_websocket_consumer]] Emitted network hop (fast path): endpoint_id={endpoint_id}",
229
+ log=False,
230
+ )
231
+ except Exception as e:
232
+ if SF_DEBUG:
233
+ print(f"[[async_websocket_consumer]] Failed to emit (fast path): {e}", log=False)
234
+ elif endpoint_metadata:
235
+ # Fallback path without C extension
236
+ try:
237
+ _, session_id = get_or_set_sf_trace_id()
238
+ if SF_DEBUG:
239
+ print(
240
+ f"[[async_websocket_consumer]] Using fallback: {endpoint_metadata['name']} @ "
241
+ f"{endpoint_metadata['filename']}:{endpoint_metadata['line']}",
242
+ log=False,
243
+ )
244
+ fast_send_network_hop(
245
+ session_id=session_id,
246
+ line=str(endpoint_metadata["line"]),
247
+ column="0",
248
+ name=endpoint_metadata["name"],
249
+ entrypoint=endpoint_metadata["filename"],
250
+ )
251
+ if SF_DEBUG:
252
+ print(
253
+ f"[[async_websocket_consumer]] Emitted network hop (fallback): "
254
+ f"{endpoint_metadata['name']}",
255
+ log=False,
256
+ )
257
+ except Exception as e:
258
+ if SF_DEBUG:
259
+ print(f"[[async_websocket_consumer]] Failed to emit (fallback): {e}", log=False)
260
+
261
+ # Capture response headers and body
262
+ resp_headers = None
263
+ resp_body_parts = []
264
+ resp_body_size = 0
265
+
266
+ # Wrap send to capture response data AND emit after websocket.accept
267
+ async def wrapped_send(message):
268
+ nonlocal resp_headers, resp_body_size
269
+
270
+ # Emit NetworkHop after WebSocket is accepted
271
+ if message["type"] == "websocket.accept":
272
+ if SF_DEBUG:
273
+ print(f"[[async_websocket_consumer]] WebSocket accepted, emitting NetworkHop", log=False)
274
+ emit_network_hop_sync()
275
+
276
+ # Capture response headers
277
+ if message["type"] == "http.response.start" and SF_NETWORKHOP_CAPTURE_RESPONSE_HEADERS:
278
+ try:
279
+ headers = message.get("headers", [])
280
+ resp_headers = {
281
+ name.decode("utf-8"): val.decode("utf-8")
282
+ for name, val in headers
283
+ }
284
+ if SF_DEBUG:
285
+ print(f"[[async_websocket_consumer]] Captured response headers: {len(resp_headers)} headers", log=False)
286
+ except Exception as e:
287
+ if SF_DEBUG:
288
+ print(f"[[async_websocket_consumer]] Failed to capture response headers: {e}", log=False)
289
+
290
+ # Capture response body
291
+ if message["type"] == "http.response.body" and SF_NETWORKHOP_CAPTURE_RESPONSE_BODY:
292
+ try:
293
+ body_part = message.get("body", b"")
294
+ if body_part and resp_body_size < _RESPONSE_LIMIT_BYTES:
295
+ remaining = _RESPONSE_LIMIT_BYTES - resp_body_size
296
+ resp_body_parts.append(body_part[:remaining])
297
+ resp_body_size += len(body_part)
298
+ except Exception as e:
299
+ if SF_DEBUG:
300
+ print(f"[[async_websocket_consumer]] Failed to capture response body chunk: {e}", log=False)
301
+
302
+ await send(message)
303
+
304
+ # — Call through to original (handles connect, receive, disconnect) —
305
+ try:
306
+ await orig_call(self, scope, receive, wrapped_send)
307
+ except Exception as exc:
308
+ custom_excepthook(type(exc), exc, exc.__traceback__)
309
+ raise
310
+ finally:
311
+ sys.setprofile(None)
312
+
313
+ # Apply the patch
314
+ AsyncConsumer.__call__ = custom_call
315
+
316
+ if PRINT_CONFIGURATION_STATUSES:
317
+ print("AsyncConsumer.__call__ patched successfully", log=False)