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.
- sf_veritas/__init__.py +20 -0
- sf_veritas/_sffastlog.c +889 -0
- sf_veritas/_sffastlog.cpython-311-x86_64-linux-gnu.so +0 -0
- sf_veritas/_sffastnet.c +924 -0
- sf_veritas/_sffastnet.cpython-311-x86_64-linux-gnu.so +0 -0
- sf_veritas/_sffastnetworkrequest.c +730 -0
- sf_veritas/_sffastnetworkrequest.cpython-311-x86_64-linux-gnu.so +0 -0
- sf_veritas/_sffuncspan.c +2155 -0
- sf_veritas/_sffuncspan.cpython-311-x86_64-linux-gnu.so +0 -0
- sf_veritas/_sffuncspan_config.c +617 -0
- sf_veritas/_sffuncspan_config.cpython-311-x86_64-linux-gnu.so +0 -0
- sf_veritas/_sfheadercheck.c +341 -0
- sf_veritas/_sfheadercheck.cpython-311-x86_64-linux-gnu.so +0 -0
- sf_veritas/_sfnetworkhop.c +1451 -0
- sf_veritas/_sfnetworkhop.cpython-311-x86_64-linux-gnu.so +0 -0
- sf_veritas/_sfservice.c +1175 -0
- sf_veritas/_sfservice.cpython-311-x86_64-linux-gnu.so +0 -0
- sf_veritas/_sfteepreload.c +5167 -0
- sf_veritas/app_config.py +49 -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 +129 -0
- sf_veritas/custom_output_wrapper.py +144 -0
- sf_veritas/custom_print.py +146 -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 +556 -0
- sf_veritas/function_span_profiler.py +1174 -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 +497 -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/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 +76 -0
- sf_veritas/patches/network_libraries/aiohttp.py +281 -0
- sf_veritas/patches/network_libraries/curl_cffi.py +363 -0
- sf_veritas/patches/network_libraries/http_client.py +419 -0
- sf_veritas/patches/network_libraries/httpcore.py +515 -0
- sf_veritas/patches/network_libraries/httplib2.py +204 -0
- sf_veritas/patches/network_libraries/httpx.py +515 -0
- sf_veritas/patches/network_libraries/niquests.py +211 -0
- sf_veritas/patches/network_libraries/pycurl.py +385 -0
- sf_veritas/patches/network_libraries/requests.py +633 -0
- sf_veritas/patches/network_libraries/tornado.py +341 -0
- sf_veritas/patches/network_libraries/treq.py +270 -0
- sf_veritas/patches/network_libraries/urllib_request.py +468 -0
- sf_veritas/patches/network_libraries/utils.py +398 -0
- sf_veritas/patches/os.py +17 -0
- sf_veritas/patches/threading.py +218 -0
- sf_veritas/patches/web_frameworks/__init__.py +54 -0
- sf_veritas/patches/web_frameworks/aiohttp.py +793 -0
- sf_veritas/patches/web_frameworks/async_websocket_consumer.py +317 -0
- sf_veritas/patches/web_frameworks/blacksheep.py +527 -0
- sf_veritas/patches/web_frameworks/bottle.py +502 -0
- sf_veritas/patches/web_frameworks/cherrypy.py +678 -0
- sf_veritas/patches/web_frameworks/cors_utils.py +122 -0
- sf_veritas/patches/web_frameworks/django.py +944 -0
- sf_veritas/patches/web_frameworks/eve.py +395 -0
- sf_veritas/patches/web_frameworks/falcon.py +926 -0
- sf_veritas/patches/web_frameworks/fastapi.py +724 -0
- sf_veritas/patches/web_frameworks/flask.py +520 -0
- sf_veritas/patches/web_frameworks/klein.py +501 -0
- sf_veritas/patches/web_frameworks/litestar.py +551 -0
- sf_veritas/patches/web_frameworks/pyramid.py +428 -0
- sf_veritas/patches/web_frameworks/quart.py +824 -0
- sf_veritas/patches/web_frameworks/robyn.py +697 -0
- sf_veritas/patches/web_frameworks/sanic.py +857 -0
- sf_veritas/patches/web_frameworks/starlette.py +723 -0
- sf_veritas/patches/web_frameworks/strawberry.py +813 -0
- sf_veritas/patches/web_frameworks/tornado.py +481 -0
- sf_veritas/patches/web_frameworks/utils.py +91 -0
- sf_veritas/print_override.py +13 -0
- sf_veritas/regular_data_transmitter.py +409 -0
- sf_veritas/request_interceptor.py +401 -0
- sf_veritas/request_utils.py +550 -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 +970 -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 +1580 -0
- sf_veritas/utils.py +39 -0
- sf_veritas-0.10.3.dist-info/METADATA +97 -0
- sf_veritas-0.10.3.dist-info/RECORD +132 -0
- sf_veritas-0.10.3.dist-info/WHEEL +5 -0
- sf_veritas-0.10.3.dist-info/entry_points.txt +2 -0
- sf_veritas-0.10.3.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,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
|
+
}
|
|
Binary file
|