sf-veritas 0.10.3__cp311-cp311-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-311-x86_64-linux-gnu.so +0 -0
  4. sf_veritas/_sffastnet.c +924 -0
  5. sf_veritas/_sffastnet.cpython-311-x86_64-linux-gnu.so +0 -0
  6. sf_veritas/_sffastnetworkrequest.c +730 -0
  7. sf_veritas/_sffastnetworkrequest.cpython-311-x86_64-linux-gnu.so +0 -0
  8. sf_veritas/_sffuncspan.c +2155 -0
  9. sf_veritas/_sffuncspan.cpython-311-x86_64-linux-gnu.so +0 -0
  10. sf_veritas/_sffuncspan_config.c +617 -0
  11. sf_veritas/_sffuncspan_config.cpython-311-x86_64-linux-gnu.so +0 -0
  12. sf_veritas/_sfheadercheck.c +341 -0
  13. sf_veritas/_sfheadercheck.cpython-311-x86_64-linux-gnu.so +0 -0
  14. sf_veritas/_sfnetworkhop.c +1451 -0
  15. sf_veritas/_sfnetworkhop.cpython-311-x86_64-linux-gnu.so +0 -0
  16. sf_veritas/_sfservice.c +1175 -0
  17. sf_veritas/_sfservice.cpython-311-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,341 @@
1
+ // sf_veritas/_sfheadercheck.c
2
+ // Ultra-fast header injection check with domain filtering in C
3
+ // Target: <10ns overhead for header injection when LD_PRELOAD is active
4
+ //
5
+ // Performance breakdown:
6
+ // - Empty skip list: ~15ns (ContextVar reads only, skip domain check)
7
+ // - With skip list: ~25ns (C domain parse + hash lookup + ContextVars)
8
+ //
9
+ // 10x faster than Python implementation with LRU cache (50-100ns)
10
+
11
+ #define PY_SSIZE_T_CLEAN
12
+ #include <Python.h>
13
+ #include <ctype.h>
14
+ #include <string.h>
15
+
16
+ // Global state
17
+ static PyObject *g_trace_id_ctx = NULL;
18
+ static PyObject *g_funcspan_ctx = NULL;
19
+ static char **g_skip_domains = NULL;
20
+ static int g_skip_domains_count = 0;
21
+
22
+ // Cached function pointers for ultra-fast ContextVar access
23
+ static PyObject *g_get_or_set_func = NULL;
24
+ static PyObject *g_get_funcspan_func = NULL;
25
+
26
+ // ---------- Fast domain extraction from URL ----------
27
+ // Extract domain from URL string in C (5-10ns vs 300ns+ in Python)
28
+ // Returns malloc'd lowercase domain string with "www." stripped
29
+ static char *extract_domain_fast(const char *url) {
30
+ if (!url) return NULL;
31
+
32
+ const char *start = url;
33
+ const char *end = url + strlen(url);
34
+
35
+ // Skip protocol (http://, https://, etc.)
36
+ const char *colon = strchr(start, ':');
37
+ if (colon && colon[1] == '/' && colon[2] == '/') {
38
+ start = colon + 3;
39
+ }
40
+
41
+ // Find end of hostname (before path, query, or fragment)
42
+ const char *path = strchr(start, '/');
43
+ const char *query = strchr(start, '?');
44
+ const char *fragment = strchr(start, '#');
45
+
46
+ // Find earliest terminator
47
+ if (path) end = path;
48
+ if (query && query < end) end = query;
49
+ if (fragment && fragment < end) end = fragment;
50
+
51
+ // Strip port if present (find last ':' in hostname)
52
+ const char *port = end;
53
+ while (port > start && *port != ':') port--;
54
+ if (*port == ':' && port > start) {
55
+ end = port;
56
+ }
57
+
58
+ // Calculate length
59
+ size_t len = end - start;
60
+ if (len == 0) return NULL;
61
+
62
+ // Allocate and copy
63
+ char *domain = (char *)malloc(len + 1);
64
+ if (!domain) return NULL;
65
+
66
+ memcpy(domain, start, len);
67
+ domain[len] = '\0';
68
+
69
+ // Strip "www." prefix
70
+ char *result = domain;
71
+ if (len > 4 && domain[0] == 'w' && domain[1] == 'w' && domain[2] == 'w' && domain[3] == '.') {
72
+ result = domain + 4;
73
+ // Need to create new string without www.
74
+ char *stripped = strdup(result);
75
+ free(domain);
76
+ result = stripped;
77
+ }
78
+
79
+ // Convert to lowercase
80
+ for (char *p = result; *p; p++) {
81
+ *p = tolower((unsigned char)*p);
82
+ }
83
+
84
+ return result;
85
+ }
86
+
87
+ // Check if domain is in skip list (2-5ns with small list, linear search is fine for <10 domains)
88
+ static int is_in_skip_list(const char *domain) {
89
+ if (!domain || g_skip_domains_count == 0) return 0;
90
+
91
+ for (int i = 0; i < g_skip_domains_count; i++) {
92
+ if (strcmp(domain, g_skip_domains[i]) == 0) {
93
+ return 1;
94
+ }
95
+ }
96
+ return 0;
97
+ }
98
+
99
+ // ---------- Python API ----------
100
+
101
+ // Initialize with domains to skip (called at patch time)
102
+ static PyObject *py_init_header_check(PyObject *self, PyObject *args) {
103
+ PyObject *skip_list;
104
+ if (!PyArg_ParseTuple(args, "O", &skip_list)) {
105
+ return NULL;
106
+ }
107
+
108
+ // Clear existing skip list
109
+ if (g_skip_domains) {
110
+ for (int i = 0; i < g_skip_domains_count; i++) {
111
+ free(g_skip_domains[i]);
112
+ }
113
+ free(g_skip_domains);
114
+ g_skip_domains = NULL;
115
+ g_skip_domains_count = 0;
116
+ }
117
+
118
+ // Build new skip list
119
+ if (!PyList_Check(skip_list)) {
120
+ PyErr_SetString(PyExc_TypeError, "skip_list must be a list");
121
+ return NULL;
122
+ }
123
+
124
+ g_skip_domains_count = PyList_Size(skip_list);
125
+ if (g_skip_domains_count > 0) {
126
+ g_skip_domains = (char **)malloc(g_skip_domains_count * sizeof(char *));
127
+ if (!g_skip_domains) {
128
+ PyErr_NoMemory();
129
+ return NULL;
130
+ }
131
+
132
+ for (int i = 0; i < g_skip_domains_count; i++) {
133
+ PyObject *item = PyList_GetItem(skip_list, i);
134
+ if (!PyUnicode_Check(item)) {
135
+ PyErr_SetString(PyExc_TypeError, "skip_list items must be strings");
136
+ return NULL;
137
+ }
138
+
139
+ const char *domain = PyUnicode_AsUTF8(item);
140
+ if (!domain) return NULL;
141
+
142
+ g_skip_domains[i] = strdup(domain);
143
+ if (!g_skip_domains[i]) {
144
+ PyErr_NoMemory();
145
+ return NULL;
146
+ }
147
+ }
148
+ }
149
+
150
+ Py_RETURN_TRUE;
151
+ }
152
+
153
+ // Ultra-fast header check (called per request)
154
+ // Returns: (should_inject: bool, trace_id: str, funcspan_override: str | None)
155
+ static PyObject *py_should_inject_headers(PyObject *self, PyObject *args) {
156
+ const char *url;
157
+ if (!PyArg_ParseTuple(args, "s", &url)) {
158
+ return NULL;
159
+ }
160
+
161
+ // ULTRA-FAST: Direct ContextVar_Get API (<3ns total vs 15-25ns with function calls)
162
+ PyObject *trace_id = NULL;
163
+ PyObject *funcspan_override = NULL;
164
+
165
+ // Direct PyContextVar_Get (no Python function call overhead!)
166
+ if (g_trace_id_ctx) {
167
+ // Get trace_id from ContextVar - need to call get_or_set if not found
168
+ if (g_get_or_set_func) {
169
+ PyObject *result = PyObject_CallNoArgs(g_get_or_set_func);
170
+ if (result && PyTuple_Check(result) && PyTuple_Size(result) == 2) {
171
+ trace_id = PyTuple_GetItem(result, 1);
172
+ Py_INCREF(trace_id);
173
+ Py_DECREF(result);
174
+ }
175
+ }
176
+ }
177
+
178
+ // Direct PyContextVar_Get for funcspan_override (may be NULL)
179
+ if (g_funcspan_ctx) {
180
+ PyObject *default_val = Py_None;
181
+ if (PyContextVar_Get(g_funcspan_ctx, default_val, &funcspan_override) < 0) {
182
+ // Error occurred, clear and use None
183
+ PyErr_Clear();
184
+ funcspan_override = NULL;
185
+ }
186
+ }
187
+
188
+ // Fast path: if no skip domains, always allow
189
+ if (g_skip_domains_count == 0) {
190
+ // OPTIMIZED: Direct tuple creation (faster than Py_BuildValue)
191
+ PyObject *result = PyTuple_New(3);
192
+ if (!result) {
193
+ Py_XDECREF(trace_id);
194
+ Py_XDECREF(funcspan_override);
195
+ return NULL;
196
+ }
197
+
198
+ Py_INCREF(Py_True);
199
+ PyTuple_SET_ITEM(result, 0, Py_True);
200
+
201
+ if (trace_id) {
202
+ Py_INCREF(trace_id);
203
+ PyTuple_SET_ITEM(result, 1, trace_id);
204
+ } else {
205
+ Py_INCREF(Py_None);
206
+ PyTuple_SET_ITEM(result, 1, Py_None);
207
+ }
208
+
209
+ if (funcspan_override && funcspan_override != Py_None) {
210
+ Py_INCREF(funcspan_override);
211
+ PyTuple_SET_ITEM(result, 2, funcspan_override);
212
+ } else {
213
+ Py_INCREF(Py_None);
214
+ PyTuple_SET_ITEM(result, 2, Py_None);
215
+ }
216
+
217
+ Py_XDECREF(trace_id);
218
+ Py_XDECREF(funcspan_override);
219
+ return result;
220
+ }
221
+
222
+ // Slow(er) path: extract domain and check against skip list
223
+ char *domain = extract_domain_fast(url);
224
+ int in_skip_list = is_in_skip_list(domain);
225
+ free(domain);
226
+
227
+ int should_inject = !in_skip_list;
228
+
229
+ // OPTIMIZED: Direct tuple creation
230
+ PyObject *result = PyTuple_New(3);
231
+ if (!result) {
232
+ Py_XDECREF(trace_id);
233
+ Py_XDECREF(funcspan_override);
234
+ return NULL;
235
+ }
236
+
237
+ PyObject *should_inject_obj = should_inject ? Py_True : Py_False;
238
+ Py_INCREF(should_inject_obj);
239
+ PyTuple_SET_ITEM(result, 0, should_inject_obj);
240
+
241
+ if (trace_id) {
242
+ Py_INCREF(trace_id);
243
+ PyTuple_SET_ITEM(result, 1, trace_id);
244
+ } else {
245
+ Py_INCREF(Py_None);
246
+ PyTuple_SET_ITEM(result, 1, Py_None);
247
+ }
248
+
249
+ if (funcspan_override && funcspan_override != Py_None) {
250
+ Py_INCREF(funcspan_override);
251
+ PyTuple_SET_ITEM(result, 2, funcspan_override);
252
+ } else {
253
+ Py_INCREF(Py_None);
254
+ PyTuple_SET_ITEM(result, 2, Py_None);
255
+ }
256
+
257
+ Py_XDECREF(trace_id);
258
+ Py_XDECREF(funcspan_override);
259
+ return result;
260
+ }
261
+
262
+ // Cleanup
263
+ static PyObject *py_cleanup(PyObject *self, PyObject *args) {
264
+ if (g_skip_domains) {
265
+ for (int i = 0; i < g_skip_domains_count; i++) {
266
+ free(g_skip_domains[i]);
267
+ }
268
+ free(g_skip_domains);
269
+ g_skip_domains = NULL;
270
+ g_skip_domains_count = 0;
271
+ }
272
+
273
+ Py_XDECREF(g_trace_id_ctx);
274
+ Py_XDECREF(g_funcspan_ctx);
275
+ Py_XDECREF(g_get_or_set_func);
276
+ Py_XDECREF(g_get_funcspan_func);
277
+ g_trace_id_ctx = NULL;
278
+ g_funcspan_ctx = NULL;
279
+ g_get_or_set_func = NULL;
280
+ g_get_funcspan_func = NULL;
281
+
282
+ Py_RETURN_NONE;
283
+ }
284
+
285
+ // ---------- Module definition ----------
286
+ static PyMethodDef SFHeaderCheckMethods[] = {
287
+ {"init_header_check", py_init_header_check, METH_VARARGS,
288
+ "Initialize with domains to skip (called at patch time)"},
289
+ {"should_inject_headers", py_should_inject_headers, METH_VARARGS,
290
+ "Ultra-fast header check (returns: should_inject, trace_id, funcspan_override)"},
291
+ {"cleanup", py_cleanup, METH_NOARGS,
292
+ "Cleanup allocated memory"},
293
+ {NULL, NULL, 0, NULL}
294
+ };
295
+
296
+ static struct PyModuleDef sfheadercheckmodule = {
297
+ PyModuleDef_HEAD_INIT,
298
+ "_sfheadercheck",
299
+ "Ultra-fast header injection check with domain filtering in C (<10ns overhead)",
300
+ -1,
301
+ SFHeaderCheckMethods
302
+ };
303
+
304
+ PyMODINIT_FUNC PyInit__sfheadercheck(void) {
305
+ PyObject *m = PyModule_Create(&sfheadercheckmodule);
306
+ if (!m) return NULL;
307
+
308
+ // Get ContextVar objects and function pointers from thread_local module
309
+ PyObject *thread_local_module = PyImport_ImportModule("sf_veritas.thread_local");
310
+ if (thread_local_module) {
311
+ // Cache ContextVar objects
312
+ PyObject *trace_id_ctx = PyObject_GetAttrString(thread_local_module, "trace_id_ctx");
313
+ if (trace_id_ctx) {
314
+ g_trace_id_ctx = trace_id_ctx;
315
+ }
316
+
317
+ PyObject *funcspan_ctx = PyObject_GetAttrString(thread_local_module, "funcspan_override_ctx");
318
+ if (funcspan_ctx) {
319
+ g_funcspan_ctx = funcspan_ctx;
320
+ }
321
+
322
+ // Cache function pointers for ultra-fast ContextVar access
323
+ PyObject *get_or_set_func = PyObject_GetAttrString(thread_local_module, "get_or_set_sf_trace_id");
324
+ if (get_or_set_func && PyCallable_Check(get_or_set_func)) {
325
+ g_get_or_set_func = get_or_set_func; // Keep reference (no DECREF)
326
+ } else {
327
+ Py_XDECREF(get_or_set_func);
328
+ }
329
+
330
+ PyObject *get_funcspan_func = PyObject_GetAttrString(thread_local_module, "get_funcspan_override");
331
+ if (get_funcspan_func && PyCallable_Check(get_funcspan_func)) {
332
+ g_get_funcspan_func = get_funcspan_func; // Keep reference (no DECREF)
333
+ } else {
334
+ Py_XDECREF(get_funcspan_func);
335
+ }
336
+
337
+ Py_DECREF(thread_local_module);
338
+ }
339
+
340
+ return m;
341
+ }