viztracer 1.1.1__cp313-cp313-win32.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 (109) hide show
  1. viztracer/__init__.py +19 -0
  2. viztracer/__main__.py +8 -0
  3. viztracer/attach.py +67 -0
  4. viztracer/attach_process/LICENSE +203 -0
  5. viztracer/attach_process/__init__.py +0 -0
  6. viztracer/attach_process/add_code_to_python_process.py +582 -0
  7. viztracer/attach_process/attach_x86.dll +0 -0
  8. viztracer/attach_process/inject_dll_amd64.exe +0 -0
  9. viztracer/attach_process/linux_and_mac/lldb_prepare.py +54 -0
  10. viztracer/attach_process/run_code_on_dllmain_amd64.dll +0 -0
  11. viztracer/attach_process/run_code_on_dllmain_x86.dll +0 -0
  12. viztracer/cellmagic.py +70 -0
  13. viztracer/code_monkey.py +353 -0
  14. viztracer/decorator.py +164 -0
  15. viztracer/event_base.py +81 -0
  16. viztracer/functree.py +135 -0
  17. viztracer/html/flamegraph.html +34 -0
  18. viztracer/html/trace_viewer_embedder.html +203 -0
  19. viztracer/html/trace_viewer_full.html +10207 -0
  20. viztracer/main.py +701 -0
  21. viztracer/modules/eventnode.c +188 -0
  22. viztracer/modules/eventnode.h +73 -0
  23. viztracer/modules/pythoncapi_compat.h +1726 -0
  24. viztracer/modules/quicktime.c +177 -0
  25. viztracer/modules/quicktime.h +104 -0
  26. viztracer/modules/snaptrace.c +2207 -0
  27. viztracer/modules/snaptrace.h +134 -0
  28. viztracer/modules/snaptrace_member.c +483 -0
  29. viztracer/modules/util.c +45 -0
  30. viztracer/modules/util.h +22 -0
  31. viztracer/modules/vcompressor/vc_dump.c +1131 -0
  32. viztracer/modules/vcompressor/vc_dump.h +49 -0
  33. viztracer/modules/vcompressor/vcompressor.c +396 -0
  34. viztracer/modules/vcompressor/vcompressor.h +15 -0
  35. viztracer/patch.py +317 -0
  36. viztracer/report_builder.py +311 -0
  37. viztracer/snaptrace.cp313-win32.pyd +0 -0
  38. viztracer/snaptrace.pyi +77 -0
  39. viztracer/util.py +196 -0
  40. viztracer/vcompressor.cp313-win32.pyd +0 -0
  41. viztracer/vcompressor.pyi +10 -0
  42. viztracer/viewer.py +529 -0
  43. viztracer/vizcounter.py +20 -0
  44. viztracer/vizevent.py +31 -0
  45. viztracer/vizlogging.py +20 -0
  46. viztracer/vizobject.py +28 -0
  47. viztracer/vizplugin.py +143 -0
  48. viztracer/viztracer.py +472 -0
  49. viztracer/web_dist/LICENSE +189 -0
  50. viztracer/web_dist/index.html +127 -0
  51. viztracer/web_dist/service_worker.js +279 -0
  52. viztracer/web_dist/trace_processor +300 -0
  53. viztracer/web_dist/v52.0-6b9586def/assets/MaterialSymbolsOutlined.woff2 +0 -0
  54. viztracer/web_dist/v52.0-6b9586def/assets/Roboto-100.woff2 +0 -0
  55. viztracer/web_dist/v52.0-6b9586def/assets/Roboto-300.woff2 +0 -0
  56. viztracer/web_dist/v52.0-6b9586def/assets/Roboto-400.woff2 +0 -0
  57. viztracer/web_dist/v52.0-6b9586def/assets/Roboto-500.woff2 +0 -0
  58. viztracer/web_dist/v52.0-6b9586def/assets/RobotoCondensed-Light.woff2 +0 -0
  59. viztracer/web_dist/v52.0-6b9586def/assets/RobotoCondensed-Regular.woff2 +0 -0
  60. viztracer/web_dist/v52.0-6b9586def/assets/RobotoMono-Regular.woff2 +0 -0
  61. viztracer/web_dist/v52.0-6b9586def/assets/brand.png +0 -0
  62. viztracer/web_dist/v52.0-6b9586def/assets/catapult_trace_viewer.html +3946 -0
  63. viztracer/web_dist/v52.0-6b9586def/assets/catapult_trace_viewer.js +7539 -0
  64. viztracer/web_dist/v52.0-6b9586def/assets/favicon.png +0 -0
  65. viztracer/web_dist/v52.0-6b9586def/assets/logo-128.png +0 -0
  66. viztracer/web_dist/v52.0-6b9586def/assets/logo-3d.png +0 -0
  67. viztracer/web_dist/v52.0-6b9586def/assets/rec_atrace.png +0 -0
  68. viztracer/web_dist/v52.0-6b9586def/assets/rec_battery_counters.png +0 -0
  69. viztracer/web_dist/v52.0-6b9586def/assets/rec_board_voltage.png +0 -0
  70. viztracer/web_dist/v52.0-6b9586def/assets/rec_cpu_coarse.png +0 -0
  71. viztracer/web_dist/v52.0-6b9586def/assets/rec_cpu_fine.png +0 -0
  72. viztracer/web_dist/v52.0-6b9586def/assets/rec_cpu_freq.png +0 -0
  73. viztracer/web_dist/v52.0-6b9586def/assets/rec_cpu_voltage.png +0 -0
  74. viztracer/web_dist/v52.0-6b9586def/assets/rec_frame_timeline.png +0 -0
  75. viztracer/web_dist/v52.0-6b9586def/assets/rec_ftrace.png +0 -0
  76. viztracer/web_dist/v52.0-6b9586def/assets/rec_gpu_mem_total.png +0 -0
  77. viztracer/web_dist/v52.0-6b9586def/assets/rec_java_heap_dump.png +0 -0
  78. viztracer/web_dist/v52.0-6b9586def/assets/rec_lmk.png +0 -0
  79. viztracer/web_dist/v52.0-6b9586def/assets/rec_logcat.png +0 -0
  80. viztracer/web_dist/v52.0-6b9586def/assets/rec_long_trace.png +0 -0
  81. viztracer/web_dist/v52.0-6b9586def/assets/rec_mem_hifreq.png +0 -0
  82. viztracer/web_dist/v52.0-6b9586def/assets/rec_meminfo.png +0 -0
  83. viztracer/web_dist/v52.0-6b9586def/assets/rec_native_heap_profiler.png +0 -0
  84. viztracer/web_dist/v52.0-6b9586def/assets/rec_one_shot.png +0 -0
  85. viztracer/web_dist/v52.0-6b9586def/assets/rec_profiling.png +0 -0
  86. viztracer/web_dist/v52.0-6b9586def/assets/rec_ps_stats.png +0 -0
  87. viztracer/web_dist/v52.0-6b9586def/assets/rec_ring_buf.png +0 -0
  88. viztracer/web_dist/v52.0-6b9586def/assets/rec_syscalls.png +0 -0
  89. viztracer/web_dist/v52.0-6b9586def/assets/rec_vmstat.png +0 -0
  90. viztracer/web_dist/v52.0-6b9586def/assets/scheduling_latency.png +0 -0
  91. viztracer/web_dist/v52.0-6b9586def/assets/vscode-icon.png +0 -0
  92. viztracer/web_dist/v52.0-6b9586def/engine_bundle.js +3 -0
  93. viztracer/web_dist/v52.0-6b9586def/frontend_bundle.js +5495 -0
  94. viztracer/web_dist/v52.0-6b9586def/index.html +127 -0
  95. viztracer/web_dist/v52.0-6b9586def/manifest.json +52 -0
  96. viztracer/web_dist/v52.0-6b9586def/perfetto.css +5737 -0
  97. viztracer/web_dist/v52.0-6b9586def/stdlib_docs.json +1 -0
  98. viztracer/web_dist/v52.0-6b9586def/trace_config_utils.wasm +0 -0
  99. viztracer/web_dist/v52.0-6b9586def/trace_processor.wasm +0 -0
  100. viztracer/web_dist/v52.0-6b9586def/trace_processor_memory64.wasm +0 -0
  101. viztracer/web_dist/v52.0-6b9586def/traceconv.wasm +0 -0
  102. viztracer/web_dist/v52.0-6b9586def/traceconv_bundle.js +2 -0
  103. viztracer-1.1.1.dist-info/METADATA +326 -0
  104. viztracer-1.1.1.dist-info/RECORD +109 -0
  105. viztracer-1.1.1.dist-info/WHEEL +5 -0
  106. viztracer-1.1.1.dist-info/entry_points.txt +3 -0
  107. viztracer-1.1.1.dist-info/licenses/LICENSE +222 -0
  108. viztracer-1.1.1.dist-info/licenses/NOTICE.txt +27 -0
  109. viztracer-1.1.1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,134 @@
1
+ // Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0
2
+ // For details: https://github.com/gaogaotiantian/viztracer/blob/master/NOTICE.txt
3
+
4
+ #ifndef __SNAPTRACE_H__
5
+ #define __SNAPTRACE_H__
6
+
7
+ #include <Python.h>
8
+ #include <frameobject.h>
9
+ #if _WIN32
10
+ #include <windows.h>
11
+ #else
12
+ #include <pthread.h>
13
+ #endif
14
+
15
+ #ifdef Py_GIL_DISABLED
16
+ // The free threading implementation of SNAPTRACE_THREAD_PROTECT_START/END uses
17
+ // a per-tracer mutex. The mutex is acquired in SNAPTRACE_THREAD_PROTECT_START
18
+ // and released in SNAPTRACE_THREAD_PROTECT_END.
19
+ // NOTE: these macros delimit a C scope so any variables accessed after
20
+ // a SNAPTRACE_THREAD_PROTECT_END need to be declared before
21
+ // SNAPTRACE_THREAD_PROTECT_START.
22
+ #define SNAPTRACE_THREAD_PROTECT_START(self) Py_BEGIN_CRITICAL_SECTION(self)
23
+ #define SNAPTRACE_THREAD_PROTECT_END(self) Py_END_CRITICAL_SECTION()
24
+ #else
25
+ // The default implementation is a no-op.
26
+ #define SNAPTRACE_THREAD_PROTECT_START(self)
27
+ #define SNAPTRACE_THREAD_PROTECT_END(self)
28
+ #endif
29
+
30
+ #ifndef Py_MONITORING_H
31
+ // monitoring.h is only available after 3.13, this is a fix
32
+ // to support the following events on 3.12
33
+ #define PY_MONITORING_EVENT_PY_START 0
34
+ #define PY_MONITORING_EVENT_PY_RESUME 1
35
+ #define PY_MONITORING_EVENT_PY_RETURN 2
36
+ #define PY_MONITORING_EVENT_PY_YIELD 3
37
+ #define PY_MONITORING_EVENT_CALL 4
38
+ #define PY_MONITORING_EVENT_LINE 5
39
+ #define PY_MONITORING_EVENT_INSTRUCTION 6
40
+ #define PY_MONITORING_EVENT_JUMP 7
41
+ #define PY_MONITORING_EVENT_BRANCH 8
42
+ #define PY_MONITORING_EVENT_STOP_ITERATION 9
43
+ #define PY_MONITORING_EVENT_RAISE 10
44
+ #define PY_MONITORING_EVENT_EXCEPTION_HANDLED 11
45
+ #define PY_MONITORING_EVENT_PY_UNWIND 12
46
+ #define PY_MONITORING_EVENT_PY_THROW 13
47
+ #define PY_MONITORING_EVENT_RERAISE 14
48
+ #define PY_MONITORING_EVENT_C_RETURN 15
49
+ #define PY_MONITORING_EVENT_C_RAISE 16
50
+ #endif
51
+
52
+
53
+ #define SNAPTRACE_MAX_STACK_DEPTH (1 << 0)
54
+ #define SNAPTRACE_INCLUDE_FILES (1 << 1)
55
+ #define SNAPTRACE_EXCLUDE_FILES (1 << 2)
56
+ #define SNAPTRACE_IGNORE_C_FUNCTION (1 << 3)
57
+ #define SNAPTRACE_LOG_RETURN_VALUE (1 << 4)
58
+ #define SNAPTRACE_LOG_FUNCTION_ARGS (1 << 6)
59
+ #define SNAPTRACE_IGNORE_FROZEN (1 << 7)
60
+ #define SNAPTRACE_LOG_ASYNC (1 << 8)
61
+ #define SNAPTRACE_TRACE_SELF (1 << 9)
62
+
63
+ #define SET_FLAG(reg, flag) ((reg) |= (flag))
64
+ #define UNSET_FLAG(reg, flag) ((reg) &= (~(flag)))
65
+
66
+ #define CHECK_FLAG(reg, flag) (((reg) & (flag)) != 0)
67
+
68
+ #define SNAPTRACE_TOOL_ID 2
69
+
70
+ struct FunctionNode {
71
+ struct FunctionNode* next;
72
+ struct FunctionNode* prev;
73
+ int64_t ts;
74
+ PyObject* args;
75
+ // PyCodeObject* for Python function, PyCFunctionObject* for C function
76
+ PyObject* func;
77
+ };
78
+
79
+ struct ThreadInfo {
80
+ int paused;
81
+ int curr_stack_depth;
82
+ int ignore_stack_depth;
83
+ unsigned long tid;
84
+ struct FunctionNode* stack_top;
85
+ PyObject* curr_task;
86
+ PyFrameObject* curr_task_frame;
87
+ struct MetadataNode* metadata_node;
88
+ };
89
+
90
+ struct MetadataNode {
91
+ struct MetadataNode* next;
92
+ unsigned long tid;
93
+ PyObject* name;
94
+ struct ThreadInfo* thread_info;
95
+ };
96
+
97
+ typedef struct {
98
+ PyObject_HEAD
99
+ #if _WIN32
100
+ DWORD dwTlsIndex;
101
+ #else
102
+ pthread_key_t thread_key;
103
+ #endif
104
+ int collecting;
105
+ // When we do fork_save(), we want to keep the pid. This is a
106
+ // mechanism for child process to keep the parent's pid. If
107
+ // this value is 0, then the program gets pid before parsing,
108
+ // otherwise it uses this pid
109
+ long fix_pid;
110
+ unsigned long total_entries;
111
+ unsigned int check_flags;
112
+ int verbose;
113
+ char* lib_file_path;
114
+ int max_stack_depth;
115
+ PyObject* process_name;
116
+ PyObject* include_files;
117
+ PyObject* exclude_files;
118
+ PyObject* log_func_repr;
119
+ double min_duration;
120
+ struct EventNode* buffer;
121
+ long buffer_size;
122
+ long buffer_head_idx;
123
+ long buffer_tail_idx;
124
+ int64_t sync_marker;
125
+ struct MetadataNode* metadata_head;
126
+ } TracerObject;
127
+
128
+ extern PyObject* threading_module;
129
+ extern PyObject* multiprocessing_module;
130
+ extern PyObject* json_module;
131
+ extern PyObject* asyncio_module;
132
+ extern PyObject* asyncio_tasks_module;
133
+
134
+ #endif
@@ -0,0 +1,483 @@
1
+ // Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0
2
+ // For details: https://github.com/gaogaotiantian/viztracer/blob/master/NOTICE.txt
3
+
4
+ #include "pythoncapi_compat.h"
5
+ #include "snaptrace.h"
6
+
7
+ extern PyObject* asyncio_module;
8
+ extern PyObject* asyncio_tasks_module;
9
+ extern PyObject* curr_task_getters[2];
10
+
11
+ // ================================================================
12
+ // Tracer members
13
+ // ================================================================
14
+
15
+ static int
16
+ Tracer_max_stack_depth_setter(TracerObject* self, PyObject* value, void* closure)
17
+ {
18
+ if (value == NULL) {
19
+ PyErr_SetString(PyExc_AttributeError, "Cannot delete the attribute");
20
+ return -1;
21
+ }
22
+
23
+ if (!PyLong_Check(value)) {
24
+ PyErr_SetString(PyExc_TypeError, "max_stack_depth must be an integer");
25
+ return -1;
26
+ }
27
+
28
+ self->max_stack_depth = PyLong_AsLong(value);
29
+
30
+ if (self->max_stack_depth >= 0) {
31
+ SET_FLAG(self->check_flags, SNAPTRACE_MAX_STACK_DEPTH);
32
+ } else {
33
+ UNSET_FLAG(self->check_flags, SNAPTRACE_MAX_STACK_DEPTH);
34
+ }
35
+ return 0;
36
+ }
37
+
38
+ static PyObject*
39
+ Tracer_max_stack_depth_getter(TracerObject* self, void* closure)
40
+ {
41
+ return PyLong_FromLong(self->max_stack_depth);
42
+ }
43
+
44
+ static int
45
+ Tracer_include_files_setter(TracerObject* self, PyObject* value, void* closure)
46
+ {
47
+ if (value == NULL) {
48
+ PyErr_SetString(PyExc_AttributeError, "Cannot delete the attribute");
49
+ return -1;
50
+ }
51
+
52
+ if (!PyList_Check(value) && value != Py_None) {
53
+ PyErr_SetString(PyExc_TypeError, "include_files must be a list or None");
54
+ return -1;
55
+ }
56
+
57
+ Py_XDECREF(self->include_files);
58
+ if (value == Py_None || PyList_Size(value) == 0) {
59
+ self->include_files = NULL;
60
+ UNSET_FLAG(self->check_flags, SNAPTRACE_INCLUDE_FILES);
61
+ } else {
62
+ self->include_files = Py_NewRef(value);
63
+ SET_FLAG(self->check_flags, SNAPTRACE_INCLUDE_FILES);
64
+ }
65
+ return 0;
66
+ }
67
+
68
+ static PyObject*
69
+ Tracer_include_files_getter(TracerObject* self, void* closure)
70
+ {
71
+ if (self->include_files) {
72
+ return Py_NewRef(self->include_files);
73
+ } else {
74
+ Py_RETURN_NONE;
75
+ }
76
+ }
77
+
78
+ static int
79
+ Tracer_exclude_files_setter(TracerObject* self, PyObject* value, void* closure)
80
+ {
81
+ if (value == NULL) {
82
+ PyErr_SetString(PyExc_AttributeError, "Cannot delete the attribute");
83
+ return -1;
84
+ }
85
+
86
+ if (!PyList_Check(value) && value != Py_None) {
87
+ PyErr_SetString(PyExc_TypeError, "exclude_files must be a list or None");
88
+ return -1;
89
+ }
90
+
91
+ Py_XDECREF(self->exclude_files);
92
+ if (value == Py_None || PyList_Size(value) == 0) {
93
+ self->exclude_files = NULL;
94
+ UNSET_FLAG(self->check_flags, SNAPTRACE_EXCLUDE_FILES);
95
+ } else {
96
+ self->exclude_files = Py_NewRef(value);
97
+ SET_FLAG(self->check_flags, SNAPTRACE_EXCLUDE_FILES);
98
+ }
99
+ return 0;
100
+ }
101
+
102
+ static PyObject*
103
+ Tracer_exclude_files_getter(TracerObject* self, void* closure)
104
+ {
105
+ if (self->exclude_files) {
106
+ return Py_NewRef(self->exclude_files);
107
+ } else {
108
+ Py_RETURN_NONE;
109
+ }
110
+ }
111
+
112
+ static int
113
+ Tracer_ignore_c_function_setter(TracerObject* self, PyObject* value, void* closure)
114
+ {
115
+ if (value == NULL) {
116
+ PyErr_SetString(PyExc_AttributeError, "Cannot delete the attribute");
117
+ return -1;
118
+ }
119
+
120
+ if (!PyBool_Check(value)) {
121
+ PyErr_SetString(PyExc_TypeError, "ignore_c_function must be a boolean");
122
+ return -1;
123
+ }
124
+
125
+ if (value == Py_True) {
126
+ SET_FLAG(self->check_flags, SNAPTRACE_IGNORE_C_FUNCTION);
127
+ } else {
128
+ UNSET_FLAG(self->check_flags, SNAPTRACE_IGNORE_C_FUNCTION);
129
+ }
130
+ return 0;
131
+ }
132
+
133
+ static PyObject*
134
+ Tracer_ignore_c_function_getter(TracerObject* self, void* closure)
135
+ {
136
+ if (CHECK_FLAG(self->check_flags, SNAPTRACE_IGNORE_C_FUNCTION)) {
137
+ Py_RETURN_TRUE;
138
+ } else {
139
+ Py_RETURN_FALSE;
140
+ }
141
+ }
142
+
143
+ static int
144
+ Tracer_ignore_frozen_setter(TracerObject* self, PyObject* value, void* closure)
145
+ {
146
+ if (value == NULL) {
147
+ PyErr_SetString(PyExc_AttributeError, "Cannot delete the attribute");
148
+ return -1;
149
+ }
150
+
151
+ if (!PyBool_Check(value)) {
152
+ PyErr_SetString(PyExc_TypeError, "ignore_frozen must be a boolean");
153
+ return -1;
154
+ }
155
+
156
+ if (value == Py_True) {
157
+ SET_FLAG(self->check_flags, SNAPTRACE_IGNORE_FROZEN);
158
+ } else {
159
+ UNSET_FLAG(self->check_flags, SNAPTRACE_IGNORE_FROZEN);
160
+ }
161
+ return 0;
162
+ }
163
+
164
+ static PyObject*
165
+ Tracer_ignore_frozen_getter(TracerObject* self, void* closure)
166
+ {
167
+ if (CHECK_FLAG(self->check_flags, SNAPTRACE_IGNORE_FROZEN)) {
168
+ Py_RETURN_TRUE;
169
+ } else {
170
+ Py_RETURN_FALSE;
171
+ }
172
+ }
173
+
174
+ static int
175
+ Tracer_verbose_setter(TracerObject* self, PyObject* value, void* closure)
176
+ {
177
+ if (value == NULL) {
178
+ PyErr_SetString(PyExc_AttributeError, "Cannot delete the attribute");
179
+ return -1;
180
+ }
181
+
182
+ if (!PyLong_Check(value)) {
183
+ PyErr_SetString(PyExc_TypeError, "verbose must be an integer");
184
+ return -1;
185
+ }
186
+
187
+ self->verbose = PyLong_AsLong(value);
188
+ return 0;
189
+ }
190
+
191
+ static PyObject*
192
+ Tracer_verbose_getter(TracerObject* self, void* closure)
193
+ {
194
+ return PyLong_FromLong(self->verbose);
195
+ }
196
+
197
+ static int
198
+ Tracer_lib_file_path_setter(TracerObject* self, PyObject* value, void* closure)
199
+ {
200
+ if (value == NULL) {
201
+ PyErr_SetString(PyExc_AttributeError, "Cannot delete the attribute");
202
+ return -1;
203
+ }
204
+
205
+ if (!PyUnicode_Check(value)) {
206
+ PyErr_SetString(PyExc_TypeError, "lib_file_path must be a string");
207
+ return -1;
208
+ }
209
+
210
+ // Obviously we need to copy the string here or it would fail on
211
+ // MacOS + python3.8
212
+ // The documentation did not say whether the value persists on "s"
213
+ // so we should copy it anyway.
214
+
215
+ const char* lib_file_path = PyUnicode_AsUTF8(value);
216
+
217
+ if (self->lib_file_path) {
218
+ PyMem_FREE(self->lib_file_path);
219
+ }
220
+ self->lib_file_path = PyMem_Calloc((strlen(lib_file_path) + 1), sizeof(char));
221
+ if (!self->lib_file_path) {
222
+ PyErr_NoMemory();
223
+ return -1;
224
+ }
225
+ strcpy(self->lib_file_path, lib_file_path);
226
+
227
+ return 0;
228
+ }
229
+
230
+ static PyObject*
231
+ Tracer_lib_file_path_getter(TracerObject* self, void* closure)
232
+ {
233
+ return PyUnicode_FromString(self->lib_file_path);
234
+ }
235
+
236
+ static int
237
+ Tracer_process_name_setter(TracerObject* self, PyObject* value, void* closure)
238
+ {
239
+ if (value == NULL) {
240
+ PyErr_SetString(PyExc_AttributeError, "Cannot delete the attribute");
241
+ return -1;
242
+ }
243
+
244
+ if (value == Py_None) {
245
+ Py_CLEAR(self->process_name);
246
+ return 0;
247
+ }
248
+
249
+ if (!PyUnicode_Check(value)) {
250
+ PyErr_SetString(PyExc_TypeError, "process_name must be a string");
251
+ return -1;
252
+ }
253
+
254
+ Py_INCREF(value);
255
+ Py_XSETREF(self->process_name, value);
256
+ return 0;
257
+ }
258
+
259
+ static PyObject*
260
+ Tracer_process_name_getter(TracerObject* self, void* closure)
261
+ {
262
+ if (self->process_name == NULL) {
263
+ Py_RETURN_NONE;
264
+ }
265
+ return Py_NewRef(self->process_name);
266
+ }
267
+
268
+ static int
269
+ Tracer_min_duration_setter(TracerObject* self, PyObject* value, void* closure)
270
+ {
271
+ if (value == NULL) {
272
+ PyErr_SetString(PyExc_AttributeError, "Cannot delete the attribute");
273
+ return -1;
274
+ }
275
+
276
+ if (PyFloat_Check(value)) {
277
+ self->min_duration = PyFloat_AsDouble(value);
278
+ } else if (PyLong_Check(value)) {
279
+ self->min_duration = PyLong_AsDouble(value);
280
+ } else {
281
+ PyErr_SetString(PyExc_TypeError, "min_duration must be a float or an integer");
282
+ return -1;
283
+ }
284
+
285
+ if (self->min_duration < 0) {
286
+ self->min_duration = 0;
287
+ }
288
+
289
+ // In Python code the default unit is us
290
+ // Convert to ns which is what c Code uses
291
+ self->min_duration *= 1000;
292
+
293
+ return 0;
294
+ }
295
+
296
+ static PyObject*
297
+ Tracer_min_duration_getter(TracerObject* self, void* closure)
298
+ {
299
+ return PyFloat_FromDouble(self->min_duration);
300
+ }
301
+
302
+ static int
303
+ Tracer_log_func_args_setter(TracerObject* self, PyObject* value, void* closure)
304
+ {
305
+ if (value == NULL) {
306
+ PyErr_SetString(PyExc_AttributeError, "Cannot delete the attribute");
307
+ return -1;
308
+ }
309
+
310
+ if (!PyBool_Check(value)) {
311
+ PyErr_SetString(PyExc_TypeError, "log_func_args must be a boolean");
312
+ return -1;
313
+ }
314
+
315
+ if (value == Py_True) {
316
+ SET_FLAG(self->check_flags, SNAPTRACE_LOG_FUNCTION_ARGS);
317
+ } else {
318
+ UNSET_FLAG(self->check_flags, SNAPTRACE_LOG_FUNCTION_ARGS);
319
+ }
320
+ return 0;
321
+ }
322
+
323
+ static PyObject*
324
+ Tracer_log_func_args_getter(TracerObject* self, void* closure)
325
+ {
326
+ if (CHECK_FLAG(self->check_flags, SNAPTRACE_LOG_FUNCTION_ARGS)) {
327
+ Py_RETURN_TRUE;
328
+ } else {
329
+ Py_RETURN_FALSE;
330
+ }
331
+ }
332
+
333
+ static int
334
+ Tracer_log_func_retval_setter(TracerObject* self, PyObject* value, void* closure)
335
+ {
336
+ if (value == NULL) {
337
+ PyErr_SetString(PyExc_AttributeError, "Cannot delete the attribute");
338
+ return -1;
339
+ }
340
+
341
+ if (!PyBool_Check(value)) {
342
+ PyErr_SetString(PyExc_TypeError, "log_func_retval must be a boolean");
343
+ return -1;
344
+ }
345
+
346
+ if (value == Py_True) {
347
+ SET_FLAG(self->check_flags, SNAPTRACE_LOG_RETURN_VALUE);
348
+ } else {
349
+ UNSET_FLAG(self->check_flags, SNAPTRACE_LOG_RETURN_VALUE);
350
+ }
351
+ return 0;
352
+ }
353
+
354
+ static PyObject*
355
+ Tracer_log_func_retval_getter(TracerObject* self, void* closure)
356
+ {
357
+ if (CHECK_FLAG(self->check_flags, SNAPTRACE_LOG_RETURN_VALUE)) {
358
+ Py_RETURN_TRUE;
359
+ } else {
360
+ Py_RETURN_FALSE;
361
+ }
362
+ }
363
+
364
+ static int
365
+ Tracer_log_async_setter(TracerObject* self, PyObject* value, void* closure)
366
+ {
367
+ if (value == NULL) {
368
+ PyErr_SetString(PyExc_AttributeError, "Cannot delete the attribute");
369
+ return -1;
370
+ }
371
+
372
+ if (!PyBool_Check(value)) {
373
+ PyErr_SetString(PyExc_TypeError, "log_async must be a boolean");
374
+ return -1;
375
+ }
376
+
377
+ if (value == Py_True) {
378
+ // Lazy import asyncio because it's slow
379
+ if (asyncio_module == NULL) {
380
+ asyncio_module = PyImport_ImportModule("asyncio");
381
+ asyncio_tasks_module = PyImport_AddModule("asyncio.tasks");
382
+ if (PyObject_HasAttrString(asyncio_tasks_module, "current_task")) {
383
+ curr_task_getters[0] = PyObject_GetAttrString(asyncio_tasks_module, "current_task");
384
+ }
385
+ }
386
+ SET_FLAG(self->check_flags, SNAPTRACE_LOG_ASYNC);
387
+ } else {
388
+ UNSET_FLAG(self->check_flags, SNAPTRACE_LOG_ASYNC);
389
+ }
390
+ return 0;
391
+ }
392
+
393
+ static PyObject*
394
+ Tracer_log_async_getter(TracerObject* self, void* closure)
395
+ {
396
+ if (CHECK_FLAG(self->check_flags, SNAPTRACE_LOG_ASYNC)) {
397
+ Py_RETURN_TRUE;
398
+ } else {
399
+ Py_RETURN_FALSE;
400
+ }
401
+ }
402
+
403
+ static int
404
+ Tracer_trace_self_setter(TracerObject* self, PyObject* value, void* closure)
405
+ {
406
+ if (value == NULL) {
407
+ PyErr_SetString(PyExc_AttributeError, "Cannot delete the attribute");
408
+ return -1;
409
+ }
410
+
411
+ if (!PyBool_Check(value)) {
412
+ PyErr_SetString(PyExc_TypeError, "trace_self must be a boolean");
413
+ return -1;
414
+ }
415
+
416
+ if (value == Py_True) {
417
+ SET_FLAG(self->check_flags, SNAPTRACE_TRACE_SELF);
418
+ } else {
419
+ UNSET_FLAG(self->check_flags, SNAPTRACE_TRACE_SELF);
420
+ }
421
+ return 0;
422
+ }
423
+
424
+ static PyObject*
425
+ Tracer_trace_self_getter(TracerObject* self, void* closure)
426
+ {
427
+ if (CHECK_FLAG(self->check_flags, SNAPTRACE_TRACE_SELF)) {
428
+ Py_RETURN_TRUE;
429
+ } else {
430
+ Py_RETURN_FALSE;
431
+ }
432
+ }
433
+
434
+ static int
435
+ Tracer_log_func_repr_setter(TracerObject* self, PyObject* value, void* closure)
436
+ {
437
+ if (value == NULL) {
438
+ PyErr_SetString(PyExc_AttributeError, "Cannot delete the attribute");
439
+ return -1;
440
+ }
441
+
442
+ if (value == Py_None) {
443
+ Py_CLEAR(self->log_func_repr);
444
+ return 0;
445
+ }
446
+
447
+ if (!PyCallable_Check(value)) {
448
+ PyErr_SetString(PyExc_TypeError, "log_func_repr must be a boolean");
449
+ return -1;
450
+ }
451
+
452
+ Py_INCREF(value);
453
+ Py_XSETREF(self->log_func_repr, value);
454
+
455
+ return 0;
456
+ }
457
+
458
+ static PyObject*
459
+ Tracer_log_func_repr_getter(TracerObject* self, void* closure)
460
+ {
461
+ if (self->log_func_repr == NULL) {
462
+ Py_RETURN_NONE;
463
+ }
464
+ return Py_NewRef(self->log_func_repr);
465
+ }
466
+
467
+ PyGetSetDef Tracer_getsetters[] = {
468
+ {"max_stack_depth", (getter)Tracer_max_stack_depth_getter, (setter)Tracer_max_stack_depth_setter, "max_stack_depth", NULL},
469
+ {"include_files", (getter)Tracer_include_files_getter, (setter)Tracer_include_files_setter, "include_files", NULL},
470
+ {"exclude_files", (getter)Tracer_exclude_files_getter, (setter)Tracer_exclude_files_setter, "exclude_files", NULL},
471
+ {"ignore_c_function", (getter)Tracer_ignore_c_function_getter, (setter)Tracer_ignore_c_function_setter, "ignore_c_function", NULL},
472
+ {"ignore_frozen", (getter)Tracer_ignore_frozen_getter, (setter)Tracer_ignore_frozen_setter, "ignore_frozen", NULL},
473
+ {"verbose", (getter)Tracer_verbose_getter, (setter)Tracer_verbose_setter, "verbose", NULL},
474
+ {"lib_file_path", (getter)Tracer_lib_file_path_getter, (setter)Tracer_lib_file_path_setter, "lib_file_path", NULL},
475
+ {"process_name", (getter)Tracer_process_name_getter, (setter)Tracer_process_name_setter, "process_name", NULL},
476
+ {"min_duration", (getter)Tracer_min_duration_getter, (setter)Tracer_min_duration_setter, "min_duration", NULL},
477
+ {"log_func_retval", (getter)Tracer_log_func_retval_getter, (setter)Tracer_log_func_retval_setter, "log_func_retval", NULL},
478
+ {"log_func_args", (getter)Tracer_log_func_args_getter, (setter)Tracer_log_func_args_setter, "log_func_args", NULL},
479
+ {"log_async", (getter)Tracer_log_async_getter, (setter)Tracer_log_async_setter, "log_async", NULL},
480
+ {"trace_self", (getter)Tracer_trace_self_getter, (setter)Tracer_trace_self_setter, "trace_self", NULL},
481
+ {"log_func_repr", (getter)Tracer_log_func_repr_getter, (setter)Tracer_log_func_repr_setter, "log_func_repr", NULL},
482
+ {NULL}
483
+ };
@@ -0,0 +1,45 @@
1
+ // Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0
2
+ // For details: https://github.com/gaogaotiantian/viztracer/blob/master/NOTICE.txt
3
+
4
+ #include <Python.h>
5
+ #include <time.h>
6
+ #include "snaptrace.h"
7
+
8
+
9
+ // Utility functions
10
+
11
+ void
12
+ Print_Py(PyObject* o)
13
+ {
14
+ PyObject* repr = PyObject_Repr(o);
15
+ printf("%s\n", PyUnicode_AsUTF8(repr));
16
+ Py_DECREF(repr);
17
+ }
18
+
19
+ void
20
+ fprintjson(FILE* fptr, PyObject* obj)
21
+ {
22
+ PyObject* json_dumps = PyObject_GetAttrString(json_module, "dumps");
23
+ PyObject* args_str = PyObject_CallOneArg(json_dumps, obj);
24
+ fprintf(fptr, "%s", PyUnicode_AsUTF8(args_str));
25
+ Py_DECREF(json_dumps);
26
+ Py_DECREF(args_str);
27
+ }
28
+
29
+ void
30
+ fprint_escape(FILE *fptr, const char *s)
31
+ {
32
+ while (*s != 0) {
33
+ switch (*s) {
34
+ case '\\': fputc('\\', fptr); fputc(*s, fptr); break;
35
+ case '"': fputc('\\', fptr); fputc(*s, fptr); break;
36
+ case '\b': fputc('\\', fptr); fputc('b', fptr); break;
37
+ case '\f': fputc('\\', fptr); fputc('f', fptr); break;
38
+ case '\n': fputc('\\', fptr); fputc('n', fptr); break;
39
+ case '\r': fputc('\\', fptr); fputc('r', fptr); break;
40
+ case '\t': fputc('\\', fptr); fputc('t', fptr); break;
41
+ default: fputc(*s, fptr);
42
+ }
43
+ s++;
44
+ }
45
+ }
@@ -0,0 +1,22 @@
1
+ // Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0
2
+ // For details: https://github.com/gaogaotiantian/viztracer/blob/master/NOTICE.txt
3
+
4
+
5
+ #ifndef __SNAPTRACE_UTIL_H__
6
+ #define __SNAPTRACE_UTIL_H__
7
+
8
+ #include <Python.h>
9
+ #include <string.h>
10
+
11
+ void Print_Py(PyObject* o);
12
+ void fprintjson(FILE* fptr, PyObject* obj);
13
+ void fprint_escape(FILE *fptr, const char *s);
14
+
15
+ // target and prefix has to be NULL-terminated
16
+ inline int startswith(const char* target, const char* prefix)
17
+ {
18
+ size_t len = strlen(prefix);
19
+ return strncmp(target, prefix, len) == 0;
20
+ }
21
+
22
+ #endif