viztracer 1.1.0__cp314-cp314-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.
Potentially problematic release.
This version of viztracer might be problematic. Click here for more details.
- viztracer/__init__.py +19 -0
- viztracer/__main__.py +8 -0
- viztracer/attach.py +67 -0
- viztracer/attach_process/LICENSE +203 -0
- viztracer/attach_process/__init__.py +0 -0
- viztracer/attach_process/add_code_to_python_process.py +582 -0
- viztracer/attach_process/attach_x86.dll +0 -0
- viztracer/attach_process/inject_dll_amd64.exe +0 -0
- viztracer/attach_process/linux_and_mac/lldb_prepare.py +54 -0
- viztracer/attach_process/run_code_on_dllmain_amd64.dll +0 -0
- viztracer/attach_process/run_code_on_dllmain_x86.dll +0 -0
- viztracer/cellmagic.py +70 -0
- viztracer/code_monkey.py +353 -0
- viztracer/decorator.py +164 -0
- viztracer/event_base.py +81 -0
- viztracer/functree.py +135 -0
- viztracer/html/flamegraph.html +34 -0
- viztracer/html/trace_viewer_embedder.html +203 -0
- viztracer/html/trace_viewer_full.html +10207 -0
- viztracer/main.py +699 -0
- viztracer/modules/eventnode.c +172 -0
- viztracer/modules/eventnode.h +73 -0
- viztracer/modules/pythoncapi_compat.h +1726 -0
- viztracer/modules/quicktime.c +177 -0
- viztracer/modules/quicktime.h +104 -0
- viztracer/modules/snaptrace.c +2205 -0
- viztracer/modules/snaptrace.h +134 -0
- viztracer/modules/snaptrace_member.c +483 -0
- viztracer/modules/util.c +45 -0
- viztracer/modules/util.h +22 -0
- viztracer/modules/vcompressor/vc_dump.c +1131 -0
- viztracer/modules/vcompressor/vc_dump.h +49 -0
- viztracer/modules/vcompressor/vcompressor.c +396 -0
- viztracer/modules/vcompressor/vcompressor.h +15 -0
- viztracer/patch.py +307 -0
- viztracer/report_builder.py +311 -0
- viztracer/snaptrace.cp314-win32.pyd +0 -0
- viztracer/snaptrace.pyi +77 -0
- viztracer/util.py +196 -0
- viztracer/vcompressor.cp314-win32.pyd +0 -0
- viztracer/vcompressor.pyi +10 -0
- viztracer/viewer.py +528 -0
- viztracer/vizcounter.py +20 -0
- viztracer/vizevent.py +31 -0
- viztracer/vizlogging.py +20 -0
- viztracer/vizobject.py +28 -0
- viztracer/vizplugin.py +143 -0
- viztracer/viztracer.py +472 -0
- viztracer/web_dist/LICENSE +189 -0
- viztracer/web_dist/index.html +127 -0
- viztracer/web_dist/service_worker.js +279 -0
- viztracer/web_dist/trace_processor +300 -0
- viztracer/web_dist/v52.0-6b9586def/assets/MaterialSymbolsOutlined.woff2 +0 -0
- viztracer/web_dist/v52.0-6b9586def/assets/Roboto-100.woff2 +0 -0
- viztracer/web_dist/v52.0-6b9586def/assets/Roboto-300.woff2 +0 -0
- viztracer/web_dist/v52.0-6b9586def/assets/Roboto-400.woff2 +0 -0
- viztracer/web_dist/v52.0-6b9586def/assets/Roboto-500.woff2 +0 -0
- viztracer/web_dist/v52.0-6b9586def/assets/RobotoCondensed-Light.woff2 +0 -0
- viztracer/web_dist/v52.0-6b9586def/assets/RobotoCondensed-Regular.woff2 +0 -0
- viztracer/web_dist/v52.0-6b9586def/assets/RobotoMono-Regular.woff2 +0 -0
- viztracer/web_dist/v52.0-6b9586def/assets/brand.png +0 -0
- viztracer/web_dist/v52.0-6b9586def/assets/catapult_trace_viewer.html +3946 -0
- viztracer/web_dist/v52.0-6b9586def/assets/catapult_trace_viewer.js +7539 -0
- viztracer/web_dist/v52.0-6b9586def/assets/favicon.png +0 -0
- viztracer/web_dist/v52.0-6b9586def/assets/logo-128.png +0 -0
- viztracer/web_dist/v52.0-6b9586def/assets/logo-3d.png +0 -0
- viztracer/web_dist/v52.0-6b9586def/assets/rec_atrace.png +0 -0
- viztracer/web_dist/v52.0-6b9586def/assets/rec_battery_counters.png +0 -0
- viztracer/web_dist/v52.0-6b9586def/assets/rec_board_voltage.png +0 -0
- viztracer/web_dist/v52.0-6b9586def/assets/rec_cpu_coarse.png +0 -0
- viztracer/web_dist/v52.0-6b9586def/assets/rec_cpu_fine.png +0 -0
- viztracer/web_dist/v52.0-6b9586def/assets/rec_cpu_freq.png +0 -0
- viztracer/web_dist/v52.0-6b9586def/assets/rec_cpu_voltage.png +0 -0
- viztracer/web_dist/v52.0-6b9586def/assets/rec_frame_timeline.png +0 -0
- viztracer/web_dist/v52.0-6b9586def/assets/rec_ftrace.png +0 -0
- viztracer/web_dist/v52.0-6b9586def/assets/rec_gpu_mem_total.png +0 -0
- viztracer/web_dist/v52.0-6b9586def/assets/rec_java_heap_dump.png +0 -0
- viztracer/web_dist/v52.0-6b9586def/assets/rec_lmk.png +0 -0
- viztracer/web_dist/v52.0-6b9586def/assets/rec_logcat.png +0 -0
- viztracer/web_dist/v52.0-6b9586def/assets/rec_long_trace.png +0 -0
- viztracer/web_dist/v52.0-6b9586def/assets/rec_mem_hifreq.png +0 -0
- viztracer/web_dist/v52.0-6b9586def/assets/rec_meminfo.png +0 -0
- viztracer/web_dist/v52.0-6b9586def/assets/rec_native_heap_profiler.png +0 -0
- viztracer/web_dist/v52.0-6b9586def/assets/rec_one_shot.png +0 -0
- viztracer/web_dist/v52.0-6b9586def/assets/rec_profiling.png +0 -0
- viztracer/web_dist/v52.0-6b9586def/assets/rec_ps_stats.png +0 -0
- viztracer/web_dist/v52.0-6b9586def/assets/rec_ring_buf.png +0 -0
- viztracer/web_dist/v52.0-6b9586def/assets/rec_syscalls.png +0 -0
- viztracer/web_dist/v52.0-6b9586def/assets/rec_vmstat.png +0 -0
- viztracer/web_dist/v52.0-6b9586def/assets/scheduling_latency.png +0 -0
- viztracer/web_dist/v52.0-6b9586def/assets/vscode-icon.png +0 -0
- viztracer/web_dist/v52.0-6b9586def/engine_bundle.js +3 -0
- viztracer/web_dist/v52.0-6b9586def/frontend_bundle.js +5495 -0
- viztracer/web_dist/v52.0-6b9586def/index.html +127 -0
- viztracer/web_dist/v52.0-6b9586def/manifest.json +52 -0
- viztracer/web_dist/v52.0-6b9586def/perfetto.css +5737 -0
- viztracer/web_dist/v52.0-6b9586def/stdlib_docs.json +1 -0
- viztracer/web_dist/v52.0-6b9586def/trace_config_utils.wasm +0 -0
- viztracer/web_dist/v52.0-6b9586def/trace_processor.wasm +0 -0
- viztracer/web_dist/v52.0-6b9586def/trace_processor_memory64.wasm +0 -0
- viztracer/web_dist/v52.0-6b9586def/traceconv.wasm +0 -0
- viztracer/web_dist/v52.0-6b9586def/traceconv_bundle.js +2 -0
- viztracer-1.1.0.dist-info/METADATA +316 -0
- viztracer-1.1.0.dist-info/RECORD +109 -0
- viztracer-1.1.0.dist-info/WHEEL +5 -0
- viztracer-1.1.0.dist-info/entry_points.txt +3 -0
- viztracer-1.1.0.dist-info/licenses/LICENSE +222 -0
- viztracer-1.1.0.dist-info/licenses/NOTICE.txt +27 -0
- viztracer-1.1.0.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
|
+
};
|
viztracer/modules/util.c
ADDED
|
@@ -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
|
+
}
|
viztracer/modules/util.h
ADDED
|
@@ -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
|