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.
Files changed (141) hide show
  1. sf_veritas/__init__.py +46 -0
  2. sf_veritas/_auto_preload.py +73 -0
  3. sf_veritas/_sfconfig.c +162 -0
  4. sf_veritas/_sfconfig.cpython-314-x86_64-linux-gnu.so +0 -0
  5. sf_veritas/_sfcrashhandler.c +267 -0
  6. sf_veritas/_sfcrashhandler.cpython-314-x86_64-linux-gnu.so +0 -0
  7. sf_veritas/_sffastlog.c +953 -0
  8. sf_veritas/_sffastlog.cpython-314-x86_64-linux-gnu.so +0 -0
  9. sf_veritas/_sffastnet.c +994 -0
  10. sf_veritas/_sffastnet.cpython-314-x86_64-linux-gnu.so +0 -0
  11. sf_veritas/_sffastnetworkrequest.c +727 -0
  12. sf_veritas/_sffastnetworkrequest.cpython-314-x86_64-linux-gnu.so +0 -0
  13. sf_veritas/_sffuncspan.c +2791 -0
  14. sf_veritas/_sffuncspan.cpython-314-x86_64-linux-gnu.so +0 -0
  15. sf_veritas/_sffuncspan_config.c +730 -0
  16. sf_veritas/_sffuncspan_config.cpython-314-x86_64-linux-gnu.so +0 -0
  17. sf_veritas/_sfheadercheck.c +341 -0
  18. sf_veritas/_sfheadercheck.cpython-314-x86_64-linux-gnu.so +0 -0
  19. sf_veritas/_sfnetworkhop.c +1454 -0
  20. sf_veritas/_sfnetworkhop.cpython-314-x86_64-linux-gnu.so +0 -0
  21. sf_veritas/_sfservice.c +1223 -0
  22. sf_veritas/_sfservice.cpython-314-x86_64-linux-gnu.so +0 -0
  23. sf_veritas/_sfteepreload.c +6227 -0
  24. sf_veritas/app_config.py +57 -0
  25. sf_veritas/cli.py +336 -0
  26. sf_veritas/constants.py +10 -0
  27. sf_veritas/custom_excepthook.py +304 -0
  28. sf_veritas/custom_log_handler.py +146 -0
  29. sf_veritas/custom_output_wrapper.py +153 -0
  30. sf_veritas/custom_print.py +153 -0
  31. sf_veritas/django_app.py +5 -0
  32. sf_veritas/env_vars.py +186 -0
  33. sf_veritas/exception_handling_middleware.py +18 -0
  34. sf_veritas/exception_metaclass.py +69 -0
  35. sf_veritas/fast_frame_info.py +116 -0
  36. sf_veritas/fast_network_hop.py +293 -0
  37. sf_veritas/frame_tools.py +112 -0
  38. sf_veritas/funcspan_config_loader.py +693 -0
  39. sf_veritas/function_span_profiler.py +1313 -0
  40. sf_veritas/get_preload_path.py +34 -0
  41. sf_veritas/import_hook.py +62 -0
  42. sf_veritas/infra_details/__init__.py +3 -0
  43. sf_veritas/infra_details/get_infra_details.py +24 -0
  44. sf_veritas/infra_details/kubernetes/__init__.py +3 -0
  45. sf_veritas/infra_details/kubernetes/get_cluster_name.py +147 -0
  46. sf_veritas/infra_details/kubernetes/get_details.py +7 -0
  47. sf_veritas/infra_details/running_on/__init__.py +17 -0
  48. sf_veritas/infra_details/running_on/kubernetes.py +11 -0
  49. sf_veritas/interceptors.py +543 -0
  50. sf_veritas/libsfnettee.so +0 -0
  51. sf_veritas/local_env_detect.py +118 -0
  52. sf_veritas/package_metadata.py +6 -0
  53. sf_veritas/patches/__init__.py +0 -0
  54. sf_veritas/patches/_patch_tracker.py +74 -0
  55. sf_veritas/patches/concurrent_futures.py +19 -0
  56. sf_veritas/patches/constants.py +1 -0
  57. sf_veritas/patches/exceptions.py +82 -0
  58. sf_veritas/patches/multiprocessing.py +32 -0
  59. sf_veritas/patches/network_libraries/__init__.py +99 -0
  60. sf_veritas/patches/network_libraries/aiohttp.py +294 -0
  61. sf_veritas/patches/network_libraries/curl_cffi.py +363 -0
  62. sf_veritas/patches/network_libraries/http_client.py +670 -0
  63. sf_veritas/patches/network_libraries/httpcore.py +580 -0
  64. sf_veritas/patches/network_libraries/httplib2.py +315 -0
  65. sf_veritas/patches/network_libraries/httpx.py +557 -0
  66. sf_veritas/patches/network_libraries/niquests.py +218 -0
  67. sf_veritas/patches/network_libraries/pycurl.py +399 -0
  68. sf_veritas/patches/network_libraries/requests.py +595 -0
  69. sf_veritas/patches/network_libraries/ssl_socket.py +822 -0
  70. sf_veritas/patches/network_libraries/tornado.py +360 -0
  71. sf_veritas/patches/network_libraries/treq.py +270 -0
  72. sf_veritas/patches/network_libraries/urllib_request.py +483 -0
  73. sf_veritas/patches/network_libraries/utils.py +598 -0
  74. sf_veritas/patches/os.py +17 -0
  75. sf_veritas/patches/threading.py +231 -0
  76. sf_veritas/patches/web_frameworks/__init__.py +54 -0
  77. sf_veritas/patches/web_frameworks/aiohttp.py +798 -0
  78. sf_veritas/patches/web_frameworks/async_websocket_consumer.py +337 -0
  79. sf_veritas/patches/web_frameworks/blacksheep.py +532 -0
  80. sf_veritas/patches/web_frameworks/bottle.py +513 -0
  81. sf_veritas/patches/web_frameworks/cherrypy.py +683 -0
  82. sf_veritas/patches/web_frameworks/cors_utils.py +122 -0
  83. sf_veritas/patches/web_frameworks/django.py +963 -0
  84. sf_veritas/patches/web_frameworks/eve.py +401 -0
  85. sf_veritas/patches/web_frameworks/falcon.py +931 -0
  86. sf_veritas/patches/web_frameworks/fastapi.py +738 -0
  87. sf_veritas/patches/web_frameworks/flask.py +526 -0
  88. sf_veritas/patches/web_frameworks/klein.py +501 -0
  89. sf_veritas/patches/web_frameworks/litestar.py +616 -0
  90. sf_veritas/patches/web_frameworks/pyramid.py +440 -0
  91. sf_veritas/patches/web_frameworks/quart.py +841 -0
  92. sf_veritas/patches/web_frameworks/robyn.py +708 -0
  93. sf_veritas/patches/web_frameworks/sanic.py +874 -0
  94. sf_veritas/patches/web_frameworks/starlette.py +742 -0
  95. sf_veritas/patches/web_frameworks/strawberry.py +1446 -0
  96. sf_veritas/patches/web_frameworks/tornado.py +485 -0
  97. sf_veritas/patches/web_frameworks/utils.py +170 -0
  98. sf_veritas/print_override.py +13 -0
  99. sf_veritas/regular_data_transmitter.py +444 -0
  100. sf_veritas/request_interceptor.py +401 -0
  101. sf_veritas/request_utils.py +550 -0
  102. sf_veritas/segfault_handler.py +116 -0
  103. sf_veritas/server_status.py +1 -0
  104. sf_veritas/shutdown_flag.py +11 -0
  105. sf_veritas/subprocess_startup.py +3 -0
  106. sf_veritas/test_cli.py +145 -0
  107. sf_veritas/thread_local.py +1319 -0
  108. sf_veritas/timeutil.py +114 -0
  109. sf_veritas/transmit_exception_to_sailfish.py +28 -0
  110. sf_veritas/transmitter.py +132 -0
  111. sf_veritas/types.py +47 -0
  112. sf_veritas/unified_interceptor.py +1678 -0
  113. sf_veritas/utils.py +39 -0
  114. sf_veritas-0.11.10.dist-info/METADATA +97 -0
  115. sf_veritas-0.11.10.dist-info/RECORD +141 -0
  116. sf_veritas-0.11.10.dist-info/WHEEL +5 -0
  117. sf_veritas-0.11.10.dist-info/entry_points.txt +2 -0
  118. sf_veritas-0.11.10.dist-info/top_level.txt +1 -0
  119. sf_veritas.libs/libbrotlicommon-6ce2a53c.so.1.0.6 +0 -0
  120. sf_veritas.libs/libbrotlidec-811d1be3.so.1.0.6 +0 -0
  121. sf_veritas.libs/libcom_err-730ca923.so.2.1 +0 -0
  122. sf_veritas.libs/libcrypt-52aca757.so.1.1.0 +0 -0
  123. sf_veritas.libs/libcrypto-bdaed0ea.so.1.1.1k +0 -0
  124. sf_veritas.libs/libcurl-eaa3cf66.so.4.5.0 +0 -0
  125. sf_veritas.libs/libgssapi_krb5-323bbd21.so.2.2 +0 -0
  126. sf_veritas.libs/libidn2-2f4a5893.so.0.3.6 +0 -0
  127. sf_veritas.libs/libk5crypto-9a74ff38.so.3.1 +0 -0
  128. sf_veritas.libs/libkeyutils-2777d33d.so.1.6 +0 -0
  129. sf_veritas.libs/libkrb5-a55300e8.so.3.3 +0 -0
  130. sf_veritas.libs/libkrb5support-e6594cfc.so.0.1 +0 -0
  131. sf_veritas.libs/liblber-2-d20824ef.4.so.2.10.9 +0 -0
  132. sf_veritas.libs/libldap-2-cea2a960.4.so.2.10.9 +0 -0
  133. sf_veritas.libs/libnghttp2-39367a22.so.14.17.0 +0 -0
  134. sf_veritas.libs/libpcre2-8-516f4c9d.so.0.7.1 +0 -0
  135. sf_veritas.libs/libpsl-99becdd3.so.5.3.1 +0 -0
  136. sf_veritas.libs/libsasl2-7de4d792.so.3.0.0 +0 -0
  137. sf_veritas.libs/libselinux-d0805dcb.so.1 +0 -0
  138. sf_veritas.libs/libssh-c11d285b.so.4.8.7 +0 -0
  139. sf_veritas.libs/libssl-60250281.so.1.1.1k +0 -0
  140. sf_veritas.libs/libunistring-05abdd40.so.2.1.0 +0 -0
  141. sf_veritas.libs/libuuid-95b83d40.so.1.3.0 +0 -0
@@ -0,0 +1,444 @@
1
+ import threading
2
+ from typing import Any, Dict, List, Optional
3
+
4
+ import requests
5
+
6
+ from . import app_config
7
+ from .env_vars import SF_DEBUG
8
+ from .package_metadata import PACKAGE_LIBRARY_TYPE, __version__
9
+ from .request_utils import non_blocking_post, non_blocking_post_with_response
10
+ from .thread_local import suppress_network_recording
11
+ from .timeutil import TimeSync
12
+
13
+ # Try to import C extension for fast path
14
+ try:
15
+ from . import _sfservice
16
+ _SFSERVICE_AVAILABLE = True
17
+ except Exception:
18
+ _sfservice = None
19
+ _SFSERVICE_AVAILABLE = False
20
+
21
+
22
+ class BaseTransmitter:
23
+ def __init__(self, api_key: str = None):
24
+ self.api_key = api_key or app_config._sailfish_api_key
25
+ self.endpoint = app_config._sailfish_graphql_endpoint
26
+ self.query_type = "mutation"
27
+ self.service_identifier = app_config._service_identifier
28
+ self.git_sha = app_config._git_sha
29
+
30
+ @property
31
+ def query_name(self) -> str:
32
+ return (
33
+ self.operation_name[0].lower() + self.operation_name[1:]
34
+ if self.operation_name
35
+ else ""
36
+ )
37
+
38
+ # TODO - Strip out everything EXCEPT for `reentrancyGuardPreactive`
39
+ def get_default_variables(self):
40
+ timestamp_ms = TimeSync.get_instance().get_utc_time_in_ms()
41
+ return {
42
+ "apiKey": self.api_key,
43
+ "serviceUuid": app_config._service_uuid,
44
+ "timestampMs": str(timestamp_ms),
45
+ }
46
+
47
+ def get_variables(
48
+ self,
49
+ additional_variables: Optional[Dict[str, Any]] = None,
50
+ ) -> Dict[str, Any]:
51
+ additional_variables = (
52
+ additional_variables if additional_variables is not None else {}
53
+ )
54
+ return {
55
+ **additional_variables,
56
+ **self.get_default_variables(),
57
+ }
58
+
59
+
60
+ class ServiceIdentifier(BaseTransmitter):
61
+ def __init__(self, api_key: str = app_config._sailfish_api_key):
62
+ super().__init__(api_key)
63
+ self.operation_name = "IdentifyServiceDetails"
64
+
65
+ def do_send(self, args) -> None:
66
+ # Service identification is now handled by _sfservice C extension in setup_interceptors()
67
+ # This method is kept as no-op for backward compatibility
68
+ return
69
+
70
+ def send(self):
71
+ """
72
+ Sends the service identification details as a GraphQL mutation.
73
+ This method overrides the `send` method from `DataTransmitter`.
74
+ """
75
+
76
+ query = f"""
77
+ {self.query_type} {self.operation_name}(
78
+ $apiKey: String!,
79
+ $timestampMs: String!,
80
+ $serviceUuid: String!,
81
+ $serviceIdentifier: String,
82
+ $serviceVersion: String,
83
+ $serviceAdditionalMetadata: JSON,
84
+ $library: String!,
85
+ $version: String!,
86
+ $infrastructureType: String,
87
+ $infrastructureDetails: JSON,
88
+ $setupInterceptorsFilePath: String,
89
+ $setupInterceptorsLineNumber: Int,
90
+ $gitSha: String
91
+ ) {{
92
+ {self.query_name}(
93
+ apiKey: $apiKey,
94
+ timestampMs: $timestampMs,
95
+ serviceUuid: $serviceUuid,
96
+ serviceIdentifier: $serviceIdentifier,
97
+ serviceVersion: $serviceVersion,
98
+ serviceAdditionalMetadata: $serviceAdditionalMetadata,
99
+ library: $library,
100
+ version: $version,
101
+ infrastructureType: $infrastructureType,
102
+ infrastructureDetails: $infrastructureDetails
103
+ setupInterceptorsFilePath: $setupInterceptorsFilePath,
104
+ setupInterceptorsLineNumber: $setupInterceptorsLineNumber
105
+ gitSha: $gitSha
106
+ )
107
+ }}
108
+ """
109
+
110
+ try:
111
+ if SF_DEBUG:
112
+ print(f"Sending query: {query}", log=False)
113
+
114
+ # Non-blocking POST request to send the GraphQL query
115
+ variables = self.get_variables(
116
+ {
117
+ "serviceIdentifier": app_config._service_identifier,
118
+ "gitSha": app_config._git_sha,
119
+ "serviceVersion": app_config._service_version,
120
+ "serviceAdditionalMetadata": app_config._service_additional_metadata,
121
+ "library": PACKAGE_LIBRARY_TYPE,
122
+ "version": __version__,
123
+ "infrastructureType": app_config._infra_details.system.value, # or whatever string you're passing
124
+ "infrastructureDetails": app_config._infra_details.details,
125
+ "setupInterceptorsFilePath": app_config._setup_interceptors_call_filename,
126
+ "setupInterceptorsLineNumber": app_config._setup_interceptors_call_lineno,
127
+ },
128
+ )
129
+
130
+ future = non_blocking_post_with_response(
131
+ self.endpoint, self.operation_name, query, variables
132
+ )
133
+ if future is None:
134
+ return
135
+ response = future.result()
136
+ if SF_DEBUG and response is None:
137
+ print(
138
+ f"IdentifyServiceDetails NOT sent successfully for service: UUID={app_config._service_uuid}",
139
+ log=False,
140
+ )
141
+ return
142
+ service_identification_received = response.get("data", {}).get(
143
+ self.query_name, False
144
+ )
145
+ app_config._service_identification_received = (
146
+ service_identification_received
147
+ )
148
+ if SF_DEBUG:
149
+ print(
150
+ f"IdentifyServiceDetails sent successfully for service: UUID={app_config._service_uuid}; service_identification_received={str(service_identification_received)}",
151
+ log=False,
152
+ )
153
+
154
+ except Exception as e:
155
+ # Log any exceptions that occur during sending
156
+ if SF_DEBUG:
157
+ print(f"Error occurred while sending service identification: {e}")
158
+
159
+
160
+ class DataTransmitter(BaseTransmitter):
161
+ def __init__(self, api_key: str = None):
162
+ self.api_key = api_key or app_config._sailfish_api_key
163
+ self.endpoint = app_config._sailfish_graphql_endpoint
164
+ self.operation_name: Optional[str] = ""
165
+ self.query_type = "mutation"
166
+ self.service_identifier = ServiceIdentifier()
167
+
168
+ def check_if_contents_should_be_ignored(
169
+ self, contents
170
+ ): # pylint: disable=unused-argument
171
+ return False
172
+
173
+ def _send_app_identifier(self) -> None:
174
+ return
175
+ if SF_DEBUG:
176
+ print(
177
+ "_send_app_identifier...SENDING DATA...args=",
178
+ set(),
179
+ log=False,
180
+ )
181
+ self.service_identifier.do_send(set())
182
+
183
+ def do_send(self, args) -> None:
184
+ self._send_app_identifier()
185
+ try:
186
+ self.send(*args)
187
+ except RuntimeError:
188
+ return
189
+
190
+ def send(self, contents, session_id: str):
191
+ if self.check_if_contents_should_be_ignored(contents):
192
+ return
193
+ query = f"""
194
+ {self.query_type} {self.operation_name}($apiKey: String!, $serviceUuid: String!, $contents: String!, $library: String!, $timestampMs: String!, $version: String!) {{
195
+ {self.query_name}(apiKey: $apiKey, serviceUuid: $serviceUuid, contents: $contents, library: $library, timestampMs: $timestampMs, version: $version)
196
+ }}
197
+ """
198
+
199
+ non_blocking_post(
200
+ self.endpoint,
201
+ self.operation_name,
202
+ query,
203
+ self.get_variables({"contents": contents}),
204
+ )
205
+
206
+
207
+ class DomainsToNotPassHeaderToTransmitter(DataTransmitter):
208
+ def __init__(self, api_key: str = app_config._sailfish_api_key):
209
+ super().__init__(api_key)
210
+ self.operation_name = "DomainsToNotPassHeaderTo"
211
+
212
+ def send(
213
+ self,
214
+ domains: List[str],
215
+ ):
216
+ # Fast path: Use C extension if available
217
+ if _SFSERVICE_AVAILABLE and _sfservice:
218
+ try:
219
+ _sfservice.domains(domains=domains)
220
+ return
221
+ except Exception:
222
+ # Fall through to Python implementation
223
+ pass
224
+
225
+ # Fallback: Use Python implementation
226
+ query = f"""
227
+ {self.query_type} {self.operation_name}(
228
+ $apiKey: String!,
229
+ $serviceUuid: String!,
230
+ $timestampMs: String!,
231
+ $domains: [String!]!,
232
+ $gitSha: String
233
+ ) {{
234
+ {self.query_name}(
235
+ apiKey: $apiKey,
236
+ serviceUuid: $serviceUuid,
237
+ timestampMs: $timestampMs,
238
+ domains: $domains,
239
+ gitSha: $gitSha
240
+ )
241
+ }}
242
+ """
243
+ variables = self.get_variables(
244
+ {
245
+ "domains": domains,
246
+ "gitSha": app_config._git_sha,
247
+ },
248
+ )
249
+
250
+ non_blocking_post(self.endpoint, self.operation_name, query, variables)
251
+
252
+
253
+ class UpdateServiceIdentifierMetadata(DataTransmitter):
254
+ def __init__(self, api_key: str = app_config._sailfish_api_key):
255
+ super().__init__(api_key)
256
+ self.operation_name = "UpdateServiceDetails"
257
+
258
+ def send(
259
+ self,
260
+ service_identifier: Optional[str] = None,
261
+ service_version: Optional[str] = None,
262
+ service_additional_metadata: Optional[Dict[str, Any]] = None,
263
+ git_sha: Optional[str] = None,
264
+ ):
265
+ """
266
+ Sends updateServiceDetails mutation to update service metadata.
267
+
268
+ Args:
269
+ service_identifier: Service identifier string
270
+ service_version: Service version string
271
+ service_additional_metadata: Dictionary of additional metadata
272
+ git_sha: Git SHA hash
273
+ """
274
+ # NOTE: C extension for update_service is not compatible with GraphQL schema
275
+ # The C implementation expects domains[] but schema expects service metadata
276
+ # Therefore, we always use Python implementation here
277
+
278
+ query = f"""
279
+ {self.query_type} {self.operation_name}(
280
+ $apiKey: String!,
281
+ $serviceUuid: String!,
282
+ $timestampMs: String!,
283
+ $serviceIdentifier: String,
284
+ $serviceVersion: String,
285
+ $serviceAdditionalMetadata: JSON,
286
+ $gitSha: String
287
+ ) {{
288
+ {self.query_name}(
289
+ apiKey: $apiKey,
290
+ serviceUuid: $serviceUuid,
291
+ timestampMs: $timestampMs,
292
+ serviceIdentifier: $serviceIdentifier,
293
+ serviceVersion: $serviceVersion,
294
+ serviceAdditionalMetadata: $serviceAdditionalMetadata,
295
+ gitSha: $gitSha
296
+ )
297
+ }}
298
+ """
299
+ variables = self.get_variables(
300
+ {
301
+ "serviceIdentifier": service_identifier,
302
+ "serviceVersion": service_version,
303
+ "serviceAdditionalMetadata": service_additional_metadata,
304
+ "gitSha": git_sha,
305
+ },
306
+ )
307
+
308
+ non_blocking_post(self.endpoint, self.operation_name, query, variables)
309
+
310
+
311
+ class NetworkHopsTransmitter(DataTransmitter):
312
+ """
313
+ A transmitter class responsible for sending network hop data as a GraphQL mutation.
314
+
315
+ This class extends `DataTransmitter` and sends `collectNetworkHops` mutation requests
316
+ to log network hop details for a given session.
317
+
318
+ Attributes:
319
+ operation_name (str): The GraphQL mutation name ("collectNetworkHops").
320
+
321
+ Methods:
322
+ send(session_id: str, line: str, column: str, name: str, entrypoint: str):
323
+ Sends a non-blocking GraphQL mutation request to log network hops.
324
+ """
325
+
326
+ def __init__(self, api_key: str = app_config._sailfish_api_key):
327
+ super().__init__(api_key)
328
+ self.operation_name = "collectNetworkHops"
329
+
330
+ def send(
331
+ self,
332
+ session_id: str,
333
+ line: str,
334
+ column: str,
335
+ name: str,
336
+ entrypoint: str,
337
+ ):
338
+ query = f"""
339
+ {self.query_type} {self.operation_name}(
340
+ $apiKey: String!,
341
+ $sessionId: String!,
342
+ $timestampMs: String!,
343
+ $line: String!,
344
+ $column: String!,
345
+ $name: String!,
346
+ $entrypoint: String!,
347
+ $serviceUuid: String
348
+ ) {{
349
+ {self.query_name}(
350
+ apiKey: $apiKey,
351
+ sessionId: $sessionId,
352
+ timestampMs: $timestampMs,
353
+ line: $line,
354
+ column: $column,
355
+ name: $name,
356
+ entrypoint: $entrypoint,
357
+ serviceUuid: $serviceUuid
358
+ )
359
+ }}
360
+ """
361
+
362
+ variables = self.get_variables(
363
+ {
364
+ "sessionId": session_id,
365
+ "line": line,
366
+ "column": column,
367
+ "name": name,
368
+ "entrypoint": entrypoint,
369
+ "serviceUuid": app_config._service_uuid,
370
+ }
371
+ )
372
+ if SF_DEBUG:
373
+ print("[[NetworkHopsTransmitter.send]] variables=", variables, log=False)
374
+ non_blocking_post(self.endpoint, self.operation_name, query, variables)
375
+
376
+
377
+ class NetworkRequestTransmitter(DataTransmitter):
378
+ def __init__(self, api_key: str = None):
379
+ super().__init__(api_key)
380
+ self.operation_name = "collectNetworkRequest"
381
+
382
+ def send(
383
+ self,
384
+ request_id: str,
385
+ page_visit_id: Optional[str],
386
+ recording_session_id: str,
387
+ service_uuid: str,
388
+ timestamp_start: int,
389
+ timestamp_end: int,
390
+ response_code: int,
391
+ success: bool,
392
+ error: Optional[str],
393
+ url: str,
394
+ method: str,
395
+ request_headers: Optional[Dict[str, Any]] = None,
396
+ response_headers: Optional[Dict[str, Any]] = None,
397
+ request_body: Optional[str] = None,
398
+ response_body: Optional[str] = None,
399
+ name: Optional[str] = None,
400
+ parent_session_id: Optional[str] = None,
401
+ ):
402
+ # build the mutation to match the new input type:
403
+ query = f"""
404
+ {self.query_type} {self.operation_name}($data: NetworkRequestInput!) {{
405
+ {self.query_name}(data: $data)
406
+ }}
407
+ """
408
+
409
+ # Build data dict with all fields
410
+ data = {
411
+ "apiKey": self.api_key,
412
+ "requestId": request_id,
413
+ "pageVisitId": page_visit_id,
414
+ "recordingSessionId": recording_session_id,
415
+ "serviceUuid": app_config._service_uuid,
416
+ "timestampStart": timestamp_start,
417
+ "timestampEnd": timestamp_end,
418
+ "responseCode": response_code,
419
+ "success": success,
420
+ "error": error,
421
+ "url": url,
422
+ "method": method,
423
+ }
424
+
425
+ # Add optional fields if provided
426
+ if request_headers is not None:
427
+ data["requestHeaders"] = request_headers
428
+ if response_headers is not None:
429
+ data["responseHeaders"] = response_headers
430
+ if request_body is not None:
431
+ data["requestBody"] = request_body
432
+ if response_body is not None:
433
+ data["responseBody"] = response_body
434
+ if name is not None:
435
+ data["name"] = name
436
+ if parent_session_id is not None:
437
+ data["parentSessionId"] = parent_session_id
438
+
439
+ variables = {"data": data}
440
+
441
+ if SF_DEBUG:
442
+ print(f"[NetworkRequestTransmitter] variables={variables}", log=False)
443
+
444
+ non_blocking_post(self.endpoint, self.operation_name, query, variables)