whatap-python 1.7.9__tar.gz → 1.8.1__tar.gz
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 whatap-python might be problematic. Click here for more details.
- {whatap_python-1.7.9 → whatap_python-1.8.1}/PKG-INFO +5 -3
- {whatap_python-1.7.9 → whatap_python-1.8.1}/setup.py +1 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/README.rst +1 -1
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/agent/darwin/amd64/whatap_python +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/agent/darwin/arm64/whatap_python +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/agent/linux/amd64/whatap_python +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/agent/linux/arm64/whatap_python +0 -0
- whatap_python-1.8.1/whatap/build.py +4 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/conf/configuration.py +1 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/net/packet_type_enum.py +1 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/trace/mod/application_fastapi.py +46 -22
- whatap_python-1.8.1/whatap/trace/mod/application_starlette.py +125 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/trace/trace_import.py +5 -3
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/trace/trace_module_definition.py +3 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap_python.egg-info/PKG-INFO +5 -3
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap_python.egg-info/SOURCES.txt +1 -0
- whatap_python-1.7.9/whatap/build.py +0 -4
- {whatap_python-1.7.9 → whatap_python-1.8.1}/README.md +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/setup.cfg +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/LICENSE +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/__init__.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/__main__.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/bootstrap/__init__.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/bootstrap/sitecustomize.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/conf/__init__.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/conf/configure.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/conf/license.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/control/__init__.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/counter/__init__.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/counter/counter_manager.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/counter/tasks/__init__.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/counter/tasks/openfiledescriptor.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/io/__init__.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/io/data_inputx.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/io/data_outputx.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/net/__init__.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/net/async_sender.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/net/packet_enum.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/net/param_def.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/net/stackhelper.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/net/udp_session.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/net/udp_thread.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/pack/__init__.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/pack/logSinkPack.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/pack/pack.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/pack/pack_enum.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/pack/tagCountPack.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/scripts/__init__.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/trace/__init__.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/trace/mod/__init__.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/trace/mod/amqp_kombu.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/trace/mod/amqp_pika.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/trace/mod/application_bottle.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/trace/mod/application_celery.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/trace/mod/application_cherrypy.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/trace/mod/application_django.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/trace/mod/application_django_asgi.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/trace/mod/application_django_py3.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/trace/mod/application_flask.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/trace/mod/application_frappe.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/trace/mod/application_graphql.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/trace/mod/application_nameko.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/trace/mod/application_tornado.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/trace/mod/application_wsgi.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/trace/mod/database_cxoracle.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/trace/mod/database_mongo.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/trace/mod/database_mysql.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/trace/mod/database_postgresql.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/trace/mod/database_redis.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/trace/mod/database_toolkit.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/trace/mod/email_smtp.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/trace/mod/httpc_django.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/trace/mod/httpc_httplib.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/trace/mod/httpc_requests.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/trace/mod/httpc_urllib3.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/trace/mod/logging.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/trace/mod/plugin.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/trace/simple_trace_context.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/trace/trace_context.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/trace/trace_context_manager.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/util/__init__.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/util/bit_util.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/util/cardinality/__init__.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/util/cardinality/hyperloglog.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/util/cardinality/murmurhash.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/util/cardinality/registerset.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/util/compare_util.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/util/date_util.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/util/debug_util.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/util/escape_literal_sql.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/util/hash_util.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/util/hexa32.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/util/int_set.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/util/ip_util.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/util/keygen.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/util/linked_list.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/util/linked_map.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/util/metering_util.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/util/request_double_queue.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/util/request_queue.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/util/string_util.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/util/throttle_util.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/util/userid_util.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/value/__init__.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/value/blob_value.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/value/boolean_value.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/value/decimal_value.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/value/double_summary.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/value/double_value.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/value/float_array.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/value/float_value.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/value/int_array.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/value/ip4_value.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/value/list_value.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/value/long_array.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/value/long_summary.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/value/map_value.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/value/null_value.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/value/number_value.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/value/summary_value.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/value/text_array.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/value/text_hash_value.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/value/text_value.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/value/value.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/value/value_enum.py +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap/whatap.conf +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap_python.egg-info/dependency_links.txt +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap_python.egg-info/entry_points.txt +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap_python.egg-info/not-zip-safe +0 -0
- {whatap_python-1.7.9 → whatap_python-1.8.1}/whatap_python.egg-info/top_level.txt +0 -0
|
@@ -1,16 +1,18 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: whatap-python
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.8.1
|
|
4
4
|
Summary: Monitoring and Profiling Service
|
|
5
5
|
Home-page: https://www.whatap.io
|
|
6
6
|
Author: whatap
|
|
7
7
|
Author-email: admin@whatap.io
|
|
8
8
|
License: Whatap License
|
|
9
|
+
Requires-Python: >=3.7
|
|
9
10
|
Dynamic: author
|
|
10
11
|
Dynamic: author-email
|
|
11
12
|
Dynamic: description
|
|
12
13
|
Dynamic: home-page
|
|
13
14
|
Dynamic: license
|
|
15
|
+
Dynamic: requires-python
|
|
14
16
|
Dynamic: summary
|
|
15
17
|
|
|
16
18
|
|
|
@@ -23,7 +25,7 @@ WhaTap_ for python
|
|
|
23
25
|
|
|
24
26
|
- Whatap allows for application performance monitoring.
|
|
25
27
|
- Support: WSGI server application & Batch job & Specific method profiling.
|
|
26
|
-
- Python version :
|
|
28
|
+
- Python version : 3.7+
|
|
27
29
|
|
|
28
30
|
Installation
|
|
29
31
|
------------
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -28,6 +28,23 @@ _RESPONSE='response'
|
|
|
28
28
|
_REMOTE_ADDR='remoteAddr'
|
|
29
29
|
_COOKIE='cookie'
|
|
30
30
|
|
|
31
|
+
async def sse_body_wrapper(original_iterator, ctx,environ, response):
|
|
32
|
+
try:
|
|
33
|
+
async for chunk in original_iterator:
|
|
34
|
+
yield chunk
|
|
35
|
+
except Exception as e:
|
|
36
|
+
interceptor_step_error(e)
|
|
37
|
+
raise
|
|
38
|
+
finally:
|
|
39
|
+
if ctx:
|
|
40
|
+
if conf.profile_http_header_enabled:
|
|
41
|
+
sendHeaders(ctx, environ)
|
|
42
|
+
if response and conf.trace_user_enabled:
|
|
43
|
+
if not conf.trace_user_using_ip:
|
|
44
|
+
setUserId(environ, response, ctx._rawuserid)
|
|
45
|
+
end_interceptor(ctx=ctx)
|
|
46
|
+
|
|
47
|
+
|
|
31
48
|
def getUserId(headers, defValue):
|
|
32
49
|
try:
|
|
33
50
|
if conf.user_header_ticket:
|
|
@@ -36,7 +53,7 @@ def getUserId(headers, defValue):
|
|
|
36
53
|
return hash_util.hashFromString(ticket), ticket
|
|
37
54
|
return 0,""
|
|
38
55
|
cookie = headers.get("cookie")
|
|
39
|
-
|
|
56
|
+
|
|
40
57
|
if cookie:
|
|
41
58
|
if len(cookie) >= conf.trace_user_cookie_limit :
|
|
42
59
|
return defValue
|
|
@@ -74,12 +91,12 @@ def sendHeaders(ctx, environ):
|
|
|
74
91
|
for key, value in environ.items():
|
|
75
92
|
keys.append(key)
|
|
76
93
|
keys.sort()
|
|
77
|
-
|
|
94
|
+
|
|
78
95
|
text = ''
|
|
79
96
|
for key in keys:
|
|
80
97
|
text += '{}={}\n'.format(key,
|
|
81
98
|
environ[key])
|
|
82
|
-
|
|
99
|
+
|
|
83
100
|
datas = ['HTTP-HEADERS', 'HTTP-HEADERS', text]
|
|
84
101
|
ctx.start_time = DateUtil.nowSystem()
|
|
85
102
|
async_sender.send_packet(PacketTypeEnum.TX_MSG, ctx, datas)
|
|
@@ -88,7 +105,7 @@ def setUserId(environ, res, cookieValue):
|
|
|
88
105
|
try:
|
|
89
106
|
if not conf.user_header_ticket:
|
|
90
107
|
cookie = environ.get(_COOKIE)
|
|
91
|
-
|
|
108
|
+
|
|
92
109
|
if not cookie or cookie.find(userid_util.WHATAP_R) < 0 or cookie.find(cookieValue) < 0:
|
|
93
110
|
res.set_cookie(key=userid_util.WHATAP_R, value=cookieValue, \
|
|
94
111
|
max_age=bit_util.INT_MAX_VALUE, path="/", \
|
|
@@ -118,7 +135,7 @@ def interceptor_error_log(trxid, e, fn, args, kwargs):
|
|
|
118
135
|
lastlineno = lineno
|
|
119
136
|
lastf_globals = fr.f_globals
|
|
120
137
|
|
|
121
|
-
fields = {'errorClass': errorClass,
|
|
138
|
+
fields = {'errorClass': errorClass,
|
|
122
139
|
'args': str(inspect.getcallargs(fn, *args, **kwargs))}
|
|
123
140
|
if lastfilename and lastlineno:
|
|
124
141
|
fields['filename'] = lastfilename
|
|
@@ -133,7 +150,7 @@ def interceptor_error_log(trxid, e, fn, args, kwargs):
|
|
|
133
150
|
error += ''.join([indicator, l.lstrip()])
|
|
134
151
|
else:
|
|
135
152
|
error += l
|
|
136
|
-
|
|
153
|
+
|
|
137
154
|
p = logSinkPack.getLogSinkPack(
|
|
138
155
|
t = DateUtil.now(),
|
|
139
156
|
category = "UnhandledException",
|
|
@@ -146,7 +163,7 @@ def interceptor_error_log(trxid, e, fn, args, kwargs):
|
|
|
146
163
|
bout = whatapio.DataOutputX()
|
|
147
164
|
bout.writePack(p, None)
|
|
148
165
|
packbytes = bout.toByteArray()
|
|
149
|
-
|
|
166
|
+
|
|
150
167
|
async_sender.send_relaypack(packbytes)
|
|
151
168
|
|
|
152
169
|
def interceptor(fn, dependant, *args, **kwargs):
|
|
@@ -158,7 +175,7 @@ def interceptor(fn, dependant, *args, **kwargs):
|
|
|
158
175
|
environ = whatap_dict.get('headers')
|
|
159
176
|
ctx.host = environ.get('host')
|
|
160
177
|
ctx.service_name = dependant.path
|
|
161
|
-
|
|
178
|
+
|
|
162
179
|
ctx.remoteIp = getRemoteAddr(environ, whatap_dict)
|
|
163
180
|
|
|
164
181
|
ctx.userAgentString = environ.get('user_agent')
|
|
@@ -172,7 +189,7 @@ def interceptor(fn, dependant, *args, **kwargs):
|
|
|
172
189
|
|
|
173
190
|
mstt = environ.get('{}'.format(
|
|
174
191
|
conf._trace_mtrace_caller_key), '')
|
|
175
|
-
|
|
192
|
+
|
|
176
193
|
if mstt:
|
|
177
194
|
ctx.setTransfer(mstt)
|
|
178
195
|
if conf.stat_mtrace_enabled:
|
|
@@ -188,7 +205,7 @@ def interceptor(fn, dependant, *args, **kwargs):
|
|
|
188
205
|
ctx.setTxid(myid)
|
|
189
206
|
caller_poid = environ.get('{}'.format(
|
|
190
207
|
conf._trace_mtrace_caller_poid_key), '')
|
|
191
|
-
|
|
208
|
+
|
|
192
209
|
if caller_poid:
|
|
193
210
|
ctx.mcaller_poid = caller_poid
|
|
194
211
|
|
|
@@ -200,7 +217,7 @@ def interceptor(fn, dependant, *args, **kwargs):
|
|
|
200
217
|
pass
|
|
201
218
|
|
|
202
219
|
start_interceptor(ctx)
|
|
203
|
-
|
|
220
|
+
|
|
204
221
|
try:
|
|
205
222
|
callback = fn(*args, **kwargs)
|
|
206
223
|
ctx = TraceContextManager.getLocalContext()
|
|
@@ -219,7 +236,7 @@ def interceptor(fn, dependant, *args, **kwargs):
|
|
|
219
236
|
if hasattr(callback, 'reason_phrase'):
|
|
220
237
|
errors.insert(0, callback.reason_phrase)
|
|
221
238
|
interceptor_error(status_code, errors)
|
|
222
|
-
|
|
239
|
+
|
|
223
240
|
return callback
|
|
224
241
|
except Exception as e:
|
|
225
242
|
interceptor_step_error(e)
|
|
@@ -230,7 +247,7 @@ def interceptor(fn, dependant, *args, **kwargs):
|
|
|
230
247
|
if conf.profile_http_header_enabled:
|
|
231
248
|
sendHeaders(ctx, environ)
|
|
232
249
|
response = whatap_dict.get(_RESPONSE)
|
|
233
|
-
|
|
250
|
+
|
|
234
251
|
if response and conf.trace_user_enabled:
|
|
235
252
|
if not conf.trace_user_using_ip:
|
|
236
253
|
setUserId(environ, response, ctx._rawuserid )
|
|
@@ -241,11 +258,11 @@ def interceptor(fn, dependant, *args, **kwargs):
|
|
|
241
258
|
async def interceptor_async(fn, dependant, *args, **kwargs):
|
|
242
259
|
if not hasattr(dependant, _WHATAP_DICT):
|
|
243
260
|
return await fn(*args, **kwargs)
|
|
244
|
-
|
|
261
|
+
|
|
245
262
|
ctx = TraceContextManager.getLocalContext()
|
|
246
|
-
|
|
263
|
+
|
|
247
264
|
ctx.service_name = dependant.path
|
|
248
|
-
|
|
265
|
+
|
|
249
266
|
whatap_dict = getattr(dependant, _WHATAP_DICT)
|
|
250
267
|
environ = whatap_dict.get('headers')
|
|
251
268
|
ctx.host = environ.get('host')
|
|
@@ -262,7 +279,7 @@ async def interceptor_async(fn, dependant, *args, **kwargs):
|
|
|
262
279
|
|
|
263
280
|
mstt = environ.get('{}'.format(
|
|
264
281
|
conf._trace_mtrace_caller_key), '')
|
|
265
|
-
|
|
282
|
+
|
|
266
283
|
if mstt:
|
|
267
284
|
ctx.setTransfer(mstt)
|
|
268
285
|
if conf.stat_mtrace_enabled:
|
|
@@ -278,7 +295,7 @@ async def interceptor_async(fn, dependant, *args, **kwargs):
|
|
|
278
295
|
ctx.setTxid(myid)
|
|
279
296
|
caller_poid = environ.get('{}'.format(
|
|
280
297
|
conf._trace_mtrace_caller_poid_key), '')
|
|
281
|
-
|
|
298
|
+
|
|
282
299
|
if caller_poid:
|
|
283
300
|
ctx.mcaller_poid = caller_poid
|
|
284
301
|
|
|
@@ -288,12 +305,19 @@ async def interceptor_async(fn, dependant, *args, **kwargs):
|
|
|
288
305
|
return await fn(*args, **kwargs)
|
|
289
306
|
except Exception as e:
|
|
290
307
|
pass
|
|
291
|
-
|
|
308
|
+
|
|
292
309
|
start_interceptor(ctx)
|
|
293
|
-
|
|
310
|
+
callback = None
|
|
311
|
+
|
|
294
312
|
try:
|
|
295
313
|
callback = await fn(*args, **kwargs)
|
|
314
|
+
from fastapi.responses import StreamingResponse
|
|
296
315
|
ctx = TraceContextManager.getLocalContext()
|
|
316
|
+
|
|
317
|
+
if isinstance(callback, StreamingResponse) and hasattr(callback, "body_iterator"):
|
|
318
|
+
original_iter = callback.body_iterator
|
|
319
|
+
callback.body_iterator = sse_body_wrapper(original_iter, ctx, environ,whatap_dict.get(_RESPONSE))
|
|
320
|
+
|
|
297
321
|
if ctx:
|
|
298
322
|
query_string = "&".join([str(query) for query in dependant.query_params])
|
|
299
323
|
if query_string:
|
|
@@ -309,7 +333,7 @@ async def interceptor_async(fn, dependant, *args, **kwargs):
|
|
|
309
333
|
if hasattr(callback, 'reason_phrase'):
|
|
310
334
|
errors.insert(0, callback.reason_phrase)
|
|
311
335
|
interceptor_error(status_code, errors)
|
|
312
|
-
|
|
336
|
+
|
|
313
337
|
return callback
|
|
314
338
|
except Exception as e:
|
|
315
339
|
interceptor_step_error(e)
|
|
@@ -317,7 +341,7 @@ async def interceptor_async(fn, dependant, *args, **kwargs):
|
|
|
317
341
|
raise e
|
|
318
342
|
finally:
|
|
319
343
|
ctx = TraceContextManager.getLocalContext()
|
|
320
|
-
if ctx:
|
|
344
|
+
if ctx and not isinstance(callback, StreamingResponse):
|
|
321
345
|
if conf.profile_http_header_enabled:
|
|
322
346
|
sendHeaders(ctx, environ)
|
|
323
347
|
response = whatap_dict.get(_RESPONSE)
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import whatap.net.async_sender as async_sender
|
|
2
|
+
from whatap.trace.trace_context import TraceContext
|
|
3
|
+
from whatap.trace.trace_context_manager import TraceContextManager
|
|
4
|
+
from whatap.net.packet_type_enum import PacketTypeEnum
|
|
5
|
+
from whatap.util.date_util import DateUtil
|
|
6
|
+
from whatap.util.userid_util import UseridUtil as userid_util
|
|
7
|
+
from whatap.trace.mod.application_wsgi import interceptor_step_error, \
|
|
8
|
+
start_interceptor,end_interceptor
|
|
9
|
+
from whatap.conf.configure import Configure as conf
|
|
10
|
+
from typing import Any
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def intercept_websocket(web_socket, data: str):
|
|
15
|
+
try:
|
|
16
|
+
ctx = TraceContext()
|
|
17
|
+
|
|
18
|
+
scope = web_socket.scope
|
|
19
|
+
headers = dict(scope.get("headers", [])) # headers는 리스트(tuple) 형태
|
|
20
|
+
query_string = scope.get("query_string", b'').decode()
|
|
21
|
+
client = scope.get("client", ("0.0.0.0", 0))
|
|
22
|
+
|
|
23
|
+
# 기본 ctx 설정
|
|
24
|
+
ctx.service_name = scope.get("path", "WebSocket")
|
|
25
|
+
if query_string:
|
|
26
|
+
ctx.service_name += f"?{query_string}"
|
|
27
|
+
ctx.http_method = "WEBSOCKET"
|
|
28
|
+
ctx.remoteIp = client[0]
|
|
29
|
+
ctx.port = client[1]
|
|
30
|
+
|
|
31
|
+
# User-Agent, Referer 추출 (바이트를 디코딩)
|
|
32
|
+
ctx.userAgentString = headers.get(b'user-agent', b'').decode()
|
|
33
|
+
ctx.referer = headers.get(b'referer', b'').decode()
|
|
34
|
+
|
|
35
|
+
# userid 관련
|
|
36
|
+
if conf.trace_user_enabled:
|
|
37
|
+
if conf.trace_user_using_ip:
|
|
38
|
+
ctx.userid = ctx.remoteIp
|
|
39
|
+
else:
|
|
40
|
+
ctx.userid, ctx._rawuserid = userid_util.getUserId([scope], ctx.remoteIp)
|
|
41
|
+
|
|
42
|
+
# 트랜잭션 전파 관련
|
|
43
|
+
mstt = headers.get(f"HTTP_{conf._trace_mtrace_caller_key}".encode(), b'').decode()
|
|
44
|
+
if mstt:
|
|
45
|
+
ctx.setTransfer(mstt)
|
|
46
|
+
if conf.stat_mtrace_enabled:
|
|
47
|
+
val = headers.get(f"HTTP_{conf._trace_mtrace_info_key}".encode(), b'').decode()
|
|
48
|
+
if val:
|
|
49
|
+
ctx.setTransferInfo(val)
|
|
50
|
+
txid = headers.get(f"HTTP_{conf._trace_mtrace_callee_key}".encode(), b'').decode()
|
|
51
|
+
if txid:
|
|
52
|
+
ctx.setTxid(txid)
|
|
53
|
+
|
|
54
|
+
poid = headers.get(f"HTTP_{conf._trace_mtrace_caller_poid_key}".encode(), b'').decode()
|
|
55
|
+
if poid:
|
|
56
|
+
ctx.mcaller_poid = poid
|
|
57
|
+
|
|
58
|
+
start_interceptor(ctx)
|
|
59
|
+
|
|
60
|
+
start_time = DateUtil.nowSystem()
|
|
61
|
+
ctx.start_time = start_time
|
|
62
|
+
ctx.error = 0
|
|
63
|
+
ctx.elapsed = 0
|
|
64
|
+
|
|
65
|
+
datas = [ctx.remoteIp, ctx.port, ctx.elapsed, ctx.error]
|
|
66
|
+
async_sender.send_packet(PacketTypeEnum.TX_WEB_SOCKET, ctx, datas)
|
|
67
|
+
|
|
68
|
+
except Exception as e:
|
|
69
|
+
interceptor_step_error(e)
|
|
70
|
+
finally:
|
|
71
|
+
end_interceptor(ctx=ctx)
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def instrument_starlette_websocket(module):
|
|
75
|
+
|
|
76
|
+
if not conf.trace_websocket_enabled:
|
|
77
|
+
return
|
|
78
|
+
|
|
79
|
+
OriginalWebSocket = module.WebSocket
|
|
80
|
+
if getattr(OriginalWebSocket, "_whatap_patched", False):
|
|
81
|
+
return
|
|
82
|
+
|
|
83
|
+
#original_accept = OriginalWebSocket.accept
|
|
84
|
+
original_send_text = OriginalWebSocket.send_text
|
|
85
|
+
original_send_bytes = OriginalWebSocket.send_bytes
|
|
86
|
+
original_send_json = OriginalWebSocket.send_json
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
# # 연결 시점도 래핑은 하지만, APM 인터셉트는 하지 않음
|
|
90
|
+
# async def wrapped_accept(self, *args, **kwargs):
|
|
91
|
+
# try:
|
|
92
|
+
# pass
|
|
93
|
+
# except Exception as e:
|
|
94
|
+
# interceptor_step_error(e)
|
|
95
|
+
# return await original_accept(self, *args, **kwargs)
|
|
96
|
+
|
|
97
|
+
async def wrapped_send_text(self, data: str):
|
|
98
|
+
try:
|
|
99
|
+
intercept_websocket(self, data)
|
|
100
|
+
except Exception as e:
|
|
101
|
+
interceptor_step_error(e)
|
|
102
|
+
return await original_send_text(self, data)
|
|
103
|
+
|
|
104
|
+
async def wrapped_send_bytes(self, data: bytes):
|
|
105
|
+
try:
|
|
106
|
+
intercept_websocket(self, None)
|
|
107
|
+
except Exception as e:
|
|
108
|
+
interceptor_step_error(e)
|
|
109
|
+
return await original_send_bytes(self, data)
|
|
110
|
+
|
|
111
|
+
async def wrapped_send_json(self, data: Any):
|
|
112
|
+
try:
|
|
113
|
+
intercept_websocket(self, None)
|
|
114
|
+
except Exception as e:
|
|
115
|
+
interceptor_step_error(e)
|
|
116
|
+
return await original_send_json(self, data)
|
|
117
|
+
|
|
118
|
+
#OriginalWebSocket.accept = wrapped_accept
|
|
119
|
+
OriginalWebSocket.send_text = wrapped_send_text
|
|
120
|
+
OriginalWebSocket.send_bytes = wrapped_send_bytes
|
|
121
|
+
OriginalWebSocket.send_json = wrapped_send_json
|
|
122
|
+
OriginalWebSocket._whatap_patched = True
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
|
|
@@ -2,6 +2,7 @@ import sys
|
|
|
2
2
|
|
|
3
3
|
try:
|
|
4
4
|
from importlib.util import find_spec
|
|
5
|
+
from importlib.abc import MetaPathFinder
|
|
5
6
|
except ImportError:
|
|
6
7
|
find_spec = None
|
|
7
8
|
|
|
@@ -53,11 +54,11 @@ class _ImportHookChainedLoader(object):
|
|
|
53
54
|
return load_module(module, fullname)
|
|
54
55
|
|
|
55
56
|
|
|
56
|
-
class ImportFinder(
|
|
57
|
+
class ImportFinder(MetaPathFinder):
|
|
57
58
|
def __init__(self):
|
|
58
59
|
self._hooks = {}
|
|
59
60
|
|
|
60
|
-
def
|
|
61
|
+
def find_spec(self, fullname, path=None, target=None):
|
|
61
62
|
if fullname not in IMPORT_HOOKS \
|
|
62
63
|
or fullname.startswith('whatap') \
|
|
63
64
|
or fullname.startswith('pip'):
|
|
@@ -78,7 +79,8 @@ class ImportFinder(object):
|
|
|
78
79
|
if find_spec:
|
|
79
80
|
spec = find_spec(fullname, path)
|
|
80
81
|
if spec and spec.loader:
|
|
81
|
-
|
|
82
|
+
spec.loader = _ImportHookChainedLoader(spec.loader)
|
|
83
|
+
return spec
|
|
82
84
|
else:
|
|
83
85
|
__import__(fullname)
|
|
84
86
|
return _ImportHookLoader()
|
|
@@ -38,6 +38,9 @@ DEFINITION = {
|
|
|
38
38
|
('sqlalchemy.engine.create', 'instrument_sqlalchemy_engine_basic'),
|
|
39
39
|
('sqlalchemy.engine', 'instrument_sqlalchemy_engine_basic'),
|
|
40
40
|
],
|
|
41
|
+
'application_starlette' : [
|
|
42
|
+
('starlette.websockets' , 'instrument_starlette_websocket'),
|
|
43
|
+
],
|
|
41
44
|
'application_wsgi': [
|
|
42
45
|
('', ''),
|
|
43
46
|
],
|
|
@@ -1,16 +1,18 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: whatap-python
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.8.1
|
|
4
4
|
Summary: Monitoring and Profiling Service
|
|
5
5
|
Home-page: https://www.whatap.io
|
|
6
6
|
Author: whatap
|
|
7
7
|
Author-email: admin@whatap.io
|
|
8
8
|
License: Whatap License
|
|
9
|
+
Requires-Python: >=3.7
|
|
9
10
|
Dynamic: author
|
|
10
11
|
Dynamic: author-email
|
|
11
12
|
Dynamic: description
|
|
12
13
|
Dynamic: home-page
|
|
13
14
|
Dynamic: license
|
|
15
|
+
Dynamic: requires-python
|
|
14
16
|
Dynamic: summary
|
|
15
17
|
|
|
16
18
|
|
|
@@ -23,7 +25,7 @@ WhaTap_ for python
|
|
|
23
25
|
|
|
24
26
|
- Whatap allows for application performance monitoring.
|
|
25
27
|
- Support: WSGI server application & Batch job & Specific method profiling.
|
|
26
|
-
- Python version :
|
|
28
|
+
- Python version : 3.7+
|
|
27
29
|
|
|
28
30
|
Installation
|
|
29
31
|
------------
|
|
@@ -59,6 +59,7 @@ whatap/trace/mod/application_flask.py
|
|
|
59
59
|
whatap/trace/mod/application_frappe.py
|
|
60
60
|
whatap/trace/mod/application_graphql.py
|
|
61
61
|
whatap/trace/mod/application_nameko.py
|
|
62
|
+
whatap/trace/mod/application_starlette.py
|
|
62
63
|
whatap/trace/mod/application_tornado.py
|
|
63
64
|
whatap/trace/mod/application_wsgi.py
|
|
64
65
|
whatap/trace/mod/database_cxoracle.py
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|