whatap-python 1.8.5__tar.gz → 1.8.7__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.8.5 → whatap_python-1.8.7}/PKG-INFO +1 -1
- {whatap_python-1.8.5 → whatap_python-1.8.7}/setup.py +1 -1
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/__init__.py +29 -11
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/agent/darwin/amd64/whatap_python +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/agent/darwin/arm64/whatap_python +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/agent/linux/amd64/whatap_python +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/agent/linux/arm64/whatap_python +0 -0
- whatap_python-1.8.7/whatap/build.py +4 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/conf/configuration.py +5 -0
- whatap_python-1.8.7/whatap/counter/__init__.py +9 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/scripts/__init__.py +5 -1
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/trace/mod/application_wsgi.py +24 -7
- whatap_python-1.8.7/whatap/trace/mod/database_neo4j.py +126 -0
- whatap_python-1.8.7/whatap/trace/mod/standalone_multiple.py +278 -0
- whatap_python-1.8.7/whatap/trace/mod/standalone_single.py +123 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/trace/trace_module_definition.py +7 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap_python.egg-info/PKG-INFO +1 -1
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap_python.egg-info/SOURCES.txt +3 -0
- whatap_python-1.8.5/whatap/build.py +0 -4
- whatap_python-1.8.5/whatap/counter/__init__.py +0 -6
- {whatap_python-1.8.5 → whatap_python-1.8.7}/README.md +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/setup.cfg +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/LICENSE +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/README.rst +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/__main__.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/bootstrap/__init__.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/bootstrap/sitecustomize.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/conf/__init__.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/conf/configure.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/conf/license.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/control/__init__.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/counter/counter_manager.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/counter/tasks/__init__.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/counter/tasks/openfiledescriptor.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/io/__init__.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/io/data_inputx.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/io/data_outputx.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/net/__init__.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/net/async_sender.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/net/packet_enum.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/net/packet_type_enum.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/net/param_def.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/net/stackhelper.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/net/udp_session.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/net/udp_thread.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/pack/__init__.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/pack/logSinkPack.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/pack/pack.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/pack/pack_enum.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/pack/tagCountPack.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/trace/__init__.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/trace/mod/__init__.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/trace/mod/amqp_kombu.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/trace/mod/amqp_pika.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/trace/mod/application_bottle.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/trace/mod/application_celery.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/trace/mod/application_cherrypy.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/trace/mod/application_django.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/trace/mod/application_django_asgi.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/trace/mod/application_django_py3.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/trace/mod/application_fastapi.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/trace/mod/application_flask.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/trace/mod/application_frappe.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/trace/mod/application_graphql.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/trace/mod/application_nameko.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/trace/mod/application_odoo.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/trace/mod/application_starlette.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/trace/mod/application_tornado.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/trace/mod/database_cxoracle.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/trace/mod/database_mongo.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/trace/mod/database_mysql.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/trace/mod/database_postgresql.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/trace/mod/database_redis.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/trace/mod/database_toolkit.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/trace/mod/email_smtp.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/trace/mod/httpc_django.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/trace/mod/httpc_httplib.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/trace/mod/httpc_requests.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/trace/mod/httpc_urllib3.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/trace/mod/logging.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/trace/mod/plugin.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/trace/simple_trace_context.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/trace/trace_context.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/trace/trace_context_manager.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/trace/trace_import.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/util/__init__.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/util/bit_util.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/util/cardinality/__init__.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/util/cardinality/hyperloglog.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/util/cardinality/murmurhash.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/util/cardinality/registerset.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/util/compare_util.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/util/date_util.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/util/debug_util.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/util/escape_literal_sql.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/util/hash_util.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/util/hexa32.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/util/int_set.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/util/ip_util.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/util/keygen.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/util/linked_list.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/util/linked_map.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/util/metering_util.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/util/request_double_queue.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/util/request_queue.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/util/string_util.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/util/throttle_util.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/util/userid_util.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/value/__init__.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/value/blob_value.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/value/boolean_value.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/value/decimal_value.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/value/double_summary.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/value/double_value.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/value/float_array.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/value/float_value.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/value/int_array.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/value/ip4_value.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/value/list_value.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/value/long_array.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/value/long_summary.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/value/map_value.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/value/null_value.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/value/number_value.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/value/summary_value.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/value/text_array.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/value/text_hash_value.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/value/text_value.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/value/value.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/value/value_enum.py +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap/whatap.conf +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap_python.egg-info/dependency_links.txt +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap_python.egg-info/entry_points.txt +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap_python.egg-info/not-zip-safe +0 -0
- {whatap_python-1.8.5 → whatap_python-1.8.7}/whatap_python.egg-info/top_level.txt +0 -0
|
@@ -18,7 +18,7 @@ setup(name=build.name,
|
|
|
18
18
|
author_email='admin@whatap.io',
|
|
19
19
|
license='Whatap License',
|
|
20
20
|
url='https://www.whatap.io',
|
|
21
|
-
packages=find_packages(),
|
|
21
|
+
packages=find_packages(exclude=('sample','sample.*')),
|
|
22
22
|
package_data={
|
|
23
23
|
'whatap': ['LICENSE', '*.rst', '*.conf', '*.json', 'agent/*/*/whatap_python']
|
|
24
24
|
},
|
|
@@ -48,33 +48,41 @@ LOG_FILE_NAME = 'whatap-hook.log'
|
|
|
48
48
|
|
|
49
49
|
isFrappeCommands = "get-frappe-commands" in sys.argv if hasattr(sys, "argv") else False
|
|
50
50
|
|
|
51
|
-
def
|
|
52
|
-
ignore_whatap_stdout = 'false'
|
|
51
|
+
def preview_whatap_conf(option_name:str):
|
|
53
52
|
home = os.environ.get('WHATAP_HOME', '.')
|
|
54
53
|
whatap_config = os.path.join(home, 'whatap.conf')
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
"""
|
|
57
|
+
현재 preview_whatap_conf 를 사용중인 옵션
|
|
58
|
+
- ignore_whatap_stdout (False)
|
|
59
|
+
- standalone_enabled (False)
|
|
60
|
+
- open_file_descriptor_enabled (False)
|
|
61
|
+
"""
|
|
62
|
+
value = 'false'
|
|
55
63
|
try:
|
|
56
64
|
with open(whatap_config) as f:
|
|
57
65
|
for raw in f:
|
|
58
66
|
line = raw.strip()
|
|
59
67
|
if not line or line.startswith('#'):
|
|
60
68
|
continue
|
|
61
|
-
if line.startswith(
|
|
69
|
+
if line.startswith(option_name):
|
|
62
70
|
parts = line.split('=', 1)
|
|
63
71
|
if len(parts) == 2:
|
|
64
|
-
|
|
72
|
+
value = parts[1].strip()
|
|
65
73
|
break
|
|
66
|
-
return
|
|
74
|
+
return value
|
|
67
75
|
|
|
68
76
|
except FileNotFoundError:
|
|
69
|
-
return
|
|
77
|
+
return value
|
|
70
78
|
|
|
71
79
|
except Exception as e:
|
|
72
80
|
print(f'WHATAP: config parse error ({e!r})')
|
|
73
|
-
return
|
|
81
|
+
return value
|
|
74
82
|
|
|
75
83
|
|
|
76
84
|
|
|
77
|
-
ignore_whatap_stdout =
|
|
85
|
+
ignore_whatap_stdout = preview_whatap_conf("ignore_whatap_stdout")
|
|
78
86
|
|
|
79
87
|
|
|
80
88
|
|
|
@@ -329,6 +337,14 @@ def hooks(home):
|
|
|
329
337
|
'trace',
|
|
330
338
|
'mod',
|
|
331
339
|
key)}
|
|
340
|
+
|
|
341
|
+
if conf.standalone_enabled:
|
|
342
|
+
if conf.standalone_type == 'multiple-transaction':
|
|
343
|
+
from whatap.trace.mod.standalone_multiple import instrument_standalone_multiple
|
|
344
|
+
instrument_standalone_multiple()
|
|
345
|
+
else:
|
|
346
|
+
from whatap.trace.mod.standalone_single import instrument_standalone_single
|
|
347
|
+
instrument_standalone_single()
|
|
332
348
|
|
|
333
349
|
except Exception as e:
|
|
334
350
|
logging.debug(e, extra={'id': 'PLUGIN ERROR'})
|
|
@@ -354,9 +370,11 @@ def agent():
|
|
|
354
370
|
if write_file(home, home.lower(), whatap_home):
|
|
355
371
|
os.environ['WHATAP_HOME'] = whatap_home
|
|
356
372
|
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
373
|
+
whatap_code_start = preview_whatap_conf("whatap_code_start")
|
|
374
|
+
if whatap_code_start == 'true':
|
|
375
|
+
t = threading.Thread(target=go)
|
|
376
|
+
t.setDaemon(True)
|
|
377
|
+
t.start()
|
|
360
378
|
config(home)
|
|
361
379
|
|
|
362
380
|
ARCH = {
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
Configuration = {
|
|
2
2
|
"dev": False,
|
|
3
|
+
"whatap_code_start": False,
|
|
3
4
|
"ignore_whatap_stdout" : False,
|
|
4
5
|
"net_udp_port": "6600",
|
|
5
6
|
"web_static_content_extensions": "js, htm, html, gif, png, jpg, css, swf, ico",
|
|
@@ -50,6 +51,10 @@ Configuration = {
|
|
|
50
51
|
"stat_error_max_count": 1000,
|
|
51
52
|
"stat_useragent_max_count": 500,
|
|
52
53
|
|
|
54
|
+
"standalone_enabled" : False,
|
|
55
|
+
"standalone_type" : "single-transaction",
|
|
56
|
+
"standalone_transaction_patterns" : "",
|
|
57
|
+
|
|
53
58
|
"user_header_ticket_enabled": False,
|
|
54
59
|
"user_header_ticket":"",
|
|
55
60
|
"trace_user_cookie_limit":2048,
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
from .counter_manager import CounterMgr # CounterMgr 클래스 import
|
|
2
|
+
from whatap import preview_whatap_conf
|
|
3
|
+
|
|
4
|
+
open_file_descriptor_enabled = preview_whatap_conf("open_file_descriptor_enabled")
|
|
5
|
+
|
|
6
|
+
if open_file_descriptor_enabled != 'false':
|
|
7
|
+
mgr = CounterMgr()
|
|
8
|
+
mgr.setDaemon(True)
|
|
9
|
+
mgr.start()
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import os
|
|
2
2
|
import re
|
|
3
|
+
import time
|
|
3
4
|
from functools import wraps
|
|
4
5
|
|
|
5
6
|
import sys, threading
|
|
6
7
|
|
|
7
8
|
from whatap import check_whatap_home, ROOT_DIR, init_config, update_config, \
|
|
8
|
-
batch_agent, AGENT_NAME, go, configPort
|
|
9
|
+
batch_agent, AGENT_NAME, go, configPort, preview_whatap_conf
|
|
9
10
|
|
|
10
11
|
|
|
11
12
|
def whatap_command(func):
|
|
@@ -73,6 +74,9 @@ def start_agent():
|
|
|
73
74
|
|
|
74
75
|
try:
|
|
75
76
|
go(opts={'whatap.port': str(port)})
|
|
77
|
+
standalone_enabled = preview_whatap_conf("standalone_enabled")
|
|
78
|
+
if standalone_enabled == 'true':
|
|
79
|
+
time.sleep(1)
|
|
76
80
|
except Exception as e:
|
|
77
81
|
print('WHATAP: AGENT ERROR: {}'.format(e))
|
|
78
82
|
print('WHATAP: continue to start user application')
|
|
@@ -444,22 +444,39 @@ def addQuoteList(arg_list):
|
|
|
444
444
|
|
|
445
445
|
return tuple(quoted_list)
|
|
446
446
|
|
|
447
|
+
def neo4jQuery(query,paremeter):
|
|
448
|
+
transformed_query = query
|
|
449
|
+
|
|
450
|
+
for key, value in paremeter.items():
|
|
451
|
+
placeholder = f"${key}"
|
|
452
|
+
replacement = f"'{str(value)}'"
|
|
453
|
+
transformed_query = transformed_query.replace(placeholder, replacement)
|
|
454
|
+
|
|
455
|
+
return transformed_query
|
|
447
456
|
|
|
448
457
|
def interceptor_db_execute(fn, db_info, *args, **kwargs):
|
|
449
458
|
ctx = TraceContextManager.getLocalContext()
|
|
450
459
|
# sendDebugProfile(ctx, 'interceptor_db_execute step -1')
|
|
451
460
|
self = args[0]
|
|
461
|
+
db_type = db_info.get('type')
|
|
452
462
|
query = None
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
query = args[1] % addQuoteDict(args[2])
|
|
456
|
-
except Exception as e:
|
|
457
|
-
pass
|
|
458
|
-
if len(args) > 2 and type(args[2]) in (list, tuple) and args[2]:
|
|
463
|
+
|
|
464
|
+
if db_type == "neo4j":
|
|
459
465
|
try:
|
|
460
|
-
query = args[1]
|
|
466
|
+
query = neo4jQuery(args[1], kwargs)
|
|
461
467
|
except Exception as e:
|
|
462
468
|
pass
|
|
469
|
+
else:
|
|
470
|
+
if len(args) > 2 and type(args[2]) == dict and args[2]:
|
|
471
|
+
try:
|
|
472
|
+
query = args[1] % addQuoteDict(args[2])
|
|
473
|
+
except Exception as e:
|
|
474
|
+
pass
|
|
475
|
+
if len(args) > 2 and type(args[2]) in (list, tuple) and args[2]:
|
|
476
|
+
try:
|
|
477
|
+
query = args[1] % addQuoteList(args[2])
|
|
478
|
+
except Exception as e:
|
|
479
|
+
pass
|
|
463
480
|
try:
|
|
464
481
|
if not query:
|
|
465
482
|
query = args[1].decode()
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
from whatap.trace import get_dict
|
|
2
|
+
from whatap.trace.mod.application_wsgi import (
|
|
3
|
+
trace_handler,
|
|
4
|
+
interceptor_db_con,
|
|
5
|
+
interceptor_db_execute,
|
|
6
|
+
interceptor_db_close
|
|
7
|
+
)
|
|
8
|
+
db_info = {}
|
|
9
|
+
|
|
10
|
+
def get_db_info(session):
|
|
11
|
+
db_info = {'type' : 'neo4j'}
|
|
12
|
+
|
|
13
|
+
pool = getattr(session, '_pool', None)
|
|
14
|
+
|
|
15
|
+
host = None
|
|
16
|
+
port = None
|
|
17
|
+
user = None
|
|
18
|
+
db_name = None
|
|
19
|
+
|
|
20
|
+
try:
|
|
21
|
+
if pool:
|
|
22
|
+
addr = getattr(pool, 'address', getattr(pool, '_address', None))
|
|
23
|
+
if addr:
|
|
24
|
+
host, port = addr[0], addr[1]
|
|
25
|
+
except Exception:
|
|
26
|
+
pass
|
|
27
|
+
db_info["host"] = f"{host}:{port}"
|
|
28
|
+
|
|
29
|
+
try:
|
|
30
|
+
if pool:
|
|
31
|
+
auth_token = pool.get_auth()
|
|
32
|
+
if auth_token:
|
|
33
|
+
user = getattr(auth_token, 'principal', None)
|
|
34
|
+
except Exception as e:
|
|
35
|
+
pass
|
|
36
|
+
|
|
37
|
+
if user == None:
|
|
38
|
+
db_info["user"] = "neo4j"
|
|
39
|
+
else:
|
|
40
|
+
db_info["user"] = user
|
|
41
|
+
|
|
42
|
+
try:
|
|
43
|
+
session_config = getattr(session, '_config', None)
|
|
44
|
+
if session_config:
|
|
45
|
+
db_name = getattr(session_config, 'database', None)
|
|
46
|
+
except Exception:
|
|
47
|
+
pass
|
|
48
|
+
|
|
49
|
+
if db_name == None:
|
|
50
|
+
db_info["dbname"] = "default"
|
|
51
|
+
else:
|
|
52
|
+
db_info["dbname"] = db_name
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
return db_info
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def instrument_neo4j(module):
|
|
62
|
+
orig = module.Session.run
|
|
63
|
+
|
|
64
|
+
def wrapper(fn):
|
|
65
|
+
@trace_handler(fn)
|
|
66
|
+
def trace(session, *args, **kwargs):
|
|
67
|
+
db_info = get_db_info(session)
|
|
68
|
+
try:
|
|
69
|
+
setattr(session, 'rowcount', -1)
|
|
70
|
+
except Exception as e:
|
|
71
|
+
raise e
|
|
72
|
+
callback = interceptor_db_execute(fn, db_info, session, *args, **kwargs)
|
|
73
|
+
|
|
74
|
+
return callback
|
|
75
|
+
return trace
|
|
76
|
+
|
|
77
|
+
module.Session.run = wrapper(orig)
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
orig = module.Session.close
|
|
83
|
+
|
|
84
|
+
def wrapper(fn):
|
|
85
|
+
@trace_handler(fn)
|
|
86
|
+
def trace(session, *args, **kwargs):
|
|
87
|
+
callback = interceptor_db_close(fn, session ,*args, **kwargs)
|
|
88
|
+
return callback
|
|
89
|
+
return trace
|
|
90
|
+
|
|
91
|
+
module.Session.close = wrapper(orig)
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def wrapper(fn):
|
|
98
|
+
@trace_handler(fn)
|
|
99
|
+
def trace(tx, *args, **kwargs):
|
|
100
|
+
session = None
|
|
101
|
+
try:
|
|
102
|
+
session = tx._on_closed.__self__
|
|
103
|
+
except AttributeError:
|
|
104
|
+
return fn(tx, *args, **kwargs)
|
|
105
|
+
|
|
106
|
+
db_info = get_db_info(session)
|
|
107
|
+
try:
|
|
108
|
+
setattr(tx, 'rowcount', -1)
|
|
109
|
+
except Exception:
|
|
110
|
+
pass
|
|
111
|
+
callback = interceptor_db_execute(fn, db_info, tx, *args, **kwargs)
|
|
112
|
+
return callback
|
|
113
|
+
|
|
114
|
+
return trace
|
|
115
|
+
|
|
116
|
+
tx_classes_to_patch = ['Transaction', 'ManagedTransaction', 'BoltTransaction']
|
|
117
|
+
|
|
118
|
+
for class_name in tx_classes_to_patch:
|
|
119
|
+
if hasattr(module, class_name):
|
|
120
|
+
TxClass = getattr(module, class_name)
|
|
121
|
+
if hasattr(TxClass, 'run'):
|
|
122
|
+
original_run = getattr(TxClass, 'run')
|
|
123
|
+
setattr(TxClass, 'run', wrapper(original_run))
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
|
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
import atexit
|
|
3
|
+
import time
|
|
4
|
+
import traceback
|
|
5
|
+
|
|
6
|
+
import whatap.net.async_sender as async_sender
|
|
7
|
+
|
|
8
|
+
from functools import wraps
|
|
9
|
+
|
|
10
|
+
from whatap.conf.configure import Configure as conf
|
|
11
|
+
from whatap.util.date_util import DateUtil
|
|
12
|
+
from whatap.trace.trace_context import TraceContext
|
|
13
|
+
from whatap.trace.trace_context_manager import TraceContextManager
|
|
14
|
+
from whatap.net.packet_type_enum import PacketTypeEnum
|
|
15
|
+
from whatap.trace.mod.application_wsgi import trace_handler
|
|
16
|
+
from whatap import logging
|
|
17
|
+
|
|
18
|
+
def trace_handler(fn, start=False, preload=None):
|
|
19
|
+
def handler(func):
|
|
20
|
+
@wraps(func)
|
|
21
|
+
def wrapper(*args, **kwargs):
|
|
22
|
+
if preload:
|
|
23
|
+
preload(*args, **kwargs)
|
|
24
|
+
|
|
25
|
+
ctx = TraceContextManager.getLocalContext()
|
|
26
|
+
if not start and not ctx:
|
|
27
|
+
return fn(*args, **kwargs)
|
|
28
|
+
try:
|
|
29
|
+
callback = func(*args, **kwargs)
|
|
30
|
+
except Exception as e:
|
|
31
|
+
if ctx and ctx.error_step == e:
|
|
32
|
+
ctx.error_step = None
|
|
33
|
+
raise e
|
|
34
|
+
raise
|
|
35
|
+
else:
|
|
36
|
+
if ctx and ctx.error_step:
|
|
37
|
+
e = ctx.error_step
|
|
38
|
+
ctx.error_step = None
|
|
39
|
+
raise e
|
|
40
|
+
return callback
|
|
41
|
+
|
|
42
|
+
return wrapper
|
|
43
|
+
|
|
44
|
+
return handler
|
|
45
|
+
|
|
46
|
+
def load_transaction_patterns():
|
|
47
|
+
raw = conf.standalone_transaction_patterns
|
|
48
|
+
patterns = set(entry.strip() for entry in raw.split(",") if entry.strip())
|
|
49
|
+
|
|
50
|
+
return patterns
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def shutdown_agent():
|
|
54
|
+
|
|
55
|
+
start_time = time.time()
|
|
56
|
+
|
|
57
|
+
while not async_sender.q.empty():
|
|
58
|
+
if time.time() - start_time > 3.0:
|
|
59
|
+
break
|
|
60
|
+
time.sleep(0.1)
|
|
61
|
+
|
|
62
|
+
if async_sender.q.empty():
|
|
63
|
+
return
|
|
64
|
+
else:
|
|
65
|
+
remaining_items = async_sender.q.qsize()
|
|
66
|
+
|
|
67
|
+
def end_interceptor(ctx):
|
|
68
|
+
if not ctx:
|
|
69
|
+
return
|
|
70
|
+
|
|
71
|
+
if conf.dev:
|
|
72
|
+
logging.debug(f'end transaction id(seq): {ctx.id}', extra={'id': 'WA112'})
|
|
73
|
+
print(f'end transaction id(seq): {ctx.id}', dict(extra={'id': 'WA112'}))
|
|
74
|
+
|
|
75
|
+
start_time = DateUtil.nowSystem()
|
|
76
|
+
ctx.start_time = start_time
|
|
77
|
+
|
|
78
|
+
datas = [ctx.host, ctx.service_name, ctx.mtid, ctx.mdepth, ctx.mcaller_txid,
|
|
79
|
+
ctx.mcaller_pcode, ctx.mcaller_spec, str(ctx.mcaller_url_hash), ctx.mcaller_poid, ctx.status]
|
|
80
|
+
|
|
81
|
+
ctx.elapsed = DateUtil.nowSystem() - start_time
|
|
82
|
+
|
|
83
|
+
async_sender.send_packet(PacketTypeEnum.TX_END, ctx, datas)
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def start_interceptor(ctx):
|
|
87
|
+
if conf.dev:
|
|
88
|
+
logging.debug(f'start transaction id(seq): {ctx.id}', extra={'id': 'WA111'})
|
|
89
|
+
print(f'start transaction id(seq): {ctx.id}', dict(extra={'id': 'WA111'}))
|
|
90
|
+
|
|
91
|
+
start_time = DateUtil.nowSystem()
|
|
92
|
+
ctx.start_time = start_time
|
|
93
|
+
|
|
94
|
+
datas = [ctx.host, ctx.service_name, ctx.remoteIp, ctx.userAgentString,
|
|
95
|
+
ctx.referer, ctx.userid, ctx.isStaticContents, ctx.http_method]
|
|
96
|
+
|
|
97
|
+
async_sender.send_packet(PacketTypeEnum.TX_START, ctx, datas)
|
|
98
|
+
|
|
99
|
+
def error_interceptor(error_msg,error_type,ctx):
|
|
100
|
+
if not ctx:
|
|
101
|
+
ctx = TraceContextManager.getLocalContext()
|
|
102
|
+
if not ctx:
|
|
103
|
+
return
|
|
104
|
+
if not ctx.error:
|
|
105
|
+
ctx.error = 1
|
|
106
|
+
|
|
107
|
+
error = ''
|
|
108
|
+
errors = []
|
|
109
|
+
errors.append(error_type)
|
|
110
|
+
errors.append(error_msg)
|
|
111
|
+
|
|
112
|
+
frame = sys._current_frames().get(ctx.thread.ident)
|
|
113
|
+
if not frame:
|
|
114
|
+
return
|
|
115
|
+
|
|
116
|
+
for stack in traceback.extract_stack(frame):
|
|
117
|
+
line = stack[0]
|
|
118
|
+
line_num = stack[1]
|
|
119
|
+
method_name = stack[2]
|
|
120
|
+
|
|
121
|
+
if line.find('/whatap/trace') > -1 or line.find(
|
|
122
|
+
'/threading.py') > -1:
|
|
123
|
+
continue
|
|
124
|
+
error += '{} ({}:{})\n'.format(method_name, line, line_num)
|
|
125
|
+
|
|
126
|
+
errors.append(error)
|
|
127
|
+
|
|
128
|
+
async_sender.send_packet(PacketTypeEnum.TX_ERROR, ctx, errors)
|
|
129
|
+
|
|
130
|
+
if conf.profile_exception_stack:
|
|
131
|
+
desc = '\n'.join(errors)
|
|
132
|
+
datas = [' ', ' ', desc]
|
|
133
|
+
ctx.start_time = DateUtil.nowSystem()
|
|
134
|
+
async_sender.send_packet(PacketTypeEnum.TX_MSG, ctx, datas)
|
|
135
|
+
|
|
136
|
+
def instrument_standalone_multiple():
|
|
137
|
+
atexit.register(shutdown_agent)
|
|
138
|
+
|
|
139
|
+
patterns = load_transaction_patterns()
|
|
140
|
+
targets_to_patch = {tuple(entry.split(":", 1)) for entry in patterns}
|
|
141
|
+
|
|
142
|
+
tracked_methods = set()
|
|
143
|
+
tracked_funcs = set()
|
|
144
|
+
modules = set()
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
for entry in patterns:
|
|
148
|
+
mod, target = entry.split(":", 1)
|
|
149
|
+
if "." in target:
|
|
150
|
+
cls, mtd = target.split(".", 1)
|
|
151
|
+
tracked_methods.add((mod, cls, mtd))
|
|
152
|
+
else:
|
|
153
|
+
func = target
|
|
154
|
+
tracked_funcs.add((mod, func))
|
|
155
|
+
|
|
156
|
+
modules.add(mod)
|
|
157
|
+
|
|
158
|
+
def wrapper(fn, module_name, target_name):
|
|
159
|
+
@trace_handler(fn, start=True)
|
|
160
|
+
def trace(*args, **kwargs):
|
|
161
|
+
prev_ctx = TraceContextManager.getLocalContext()
|
|
162
|
+
ctx = TraceContext()
|
|
163
|
+
ctx.service_name = f"{module_name}:{target_name}"
|
|
164
|
+
start_interceptor(ctx)
|
|
165
|
+
try:
|
|
166
|
+
callback = fn(*args, **kwargs)
|
|
167
|
+
return callback
|
|
168
|
+
except Exception as e:
|
|
169
|
+
error_msg = str(e)
|
|
170
|
+
error_type = e.__class__.__name__
|
|
171
|
+
error_interceptor(error_msg,error_type,ctx)
|
|
172
|
+
raise e
|
|
173
|
+
finally:
|
|
174
|
+
end_interceptor(ctx)
|
|
175
|
+
TraceContextManager.setLocalContext(prev_ctx)
|
|
176
|
+
|
|
177
|
+
return trace
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
patching_queue = []
|
|
182
|
+
sys_trace_current_service_name = None
|
|
183
|
+
|
|
184
|
+
def trace_and_patch_profiler(frame, event, arg):
|
|
185
|
+
global sys_trace_current_service_name
|
|
186
|
+
|
|
187
|
+
if not targets_to_patch and not patching_queue:
|
|
188
|
+
pass
|
|
189
|
+
|
|
190
|
+
module_name = frame.f_globals.get("__name__")
|
|
191
|
+
if module_name not in (modules) or event not in ("call", "return","exception"):
|
|
192
|
+
return trace_and_patch_profiler
|
|
193
|
+
|
|
194
|
+
fn_name = frame.f_code.co_name
|
|
195
|
+
is_method = "self" in frame.f_locals
|
|
196
|
+
|
|
197
|
+
is_target = False
|
|
198
|
+
full_target_name = fn_name
|
|
199
|
+
target_tuple = None
|
|
200
|
+
|
|
201
|
+
if is_method:
|
|
202
|
+
cls_name = type(frame.f_locals["self"]).__name__
|
|
203
|
+
full_target_name = f"{cls_name}.{fn_name}"
|
|
204
|
+
if (module_name, cls_name, fn_name) in tracked_methods:
|
|
205
|
+
is_target = True
|
|
206
|
+
target_tuple = (module_name, full_target_name)
|
|
207
|
+
else:
|
|
208
|
+
if (module_name, fn_name) in tracked_funcs:
|
|
209
|
+
is_target = True
|
|
210
|
+
target_tuple = (module_name, full_target_name)
|
|
211
|
+
|
|
212
|
+
if target_tuple in targets_to_patch:
|
|
213
|
+
if event == "call":
|
|
214
|
+
if not is_target:
|
|
215
|
+
return trace_and_patch_profiler
|
|
216
|
+
|
|
217
|
+
prev_ctx = TraceContextManager.getLocalContext()
|
|
218
|
+
if prev_ctx:
|
|
219
|
+
patching_queue.append(prev_ctx)
|
|
220
|
+
|
|
221
|
+
ctx = TraceContext()
|
|
222
|
+
ctx.service_name = f"{module_name}:{full_target_name}"
|
|
223
|
+
sys_trace_current_service_name = ctx.service_name
|
|
224
|
+
|
|
225
|
+
TraceContextManager.setLocalContext(ctx)
|
|
226
|
+
start_interceptor(ctx)
|
|
227
|
+
|
|
228
|
+
try:
|
|
229
|
+
module_obj = sys.modules[module_name]
|
|
230
|
+
if is_method:
|
|
231
|
+
cls_name, mtd_name = target_tuple[1].split('.', 1)
|
|
232
|
+
cls_obj = getattr(module_obj, cls_name)
|
|
233
|
+
fn = getattr(cls_obj, mtd_name)
|
|
234
|
+
wrapped_fn = wrapper(fn, module_name, target_tuple[1])
|
|
235
|
+
setattr(cls_obj, mtd_name, wrapped_fn)
|
|
236
|
+
else:
|
|
237
|
+
func_name = target_tuple[1]
|
|
238
|
+
fn = getattr(module_obj, func_name)
|
|
239
|
+
wrapped_fn = wrapper(fn, module_name, func_name)
|
|
240
|
+
setattr(module_obj, func_name, wrapped_fn)
|
|
241
|
+
|
|
242
|
+
targets_to_patch.remove(target_tuple)
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
except (AttributeError, KeyError) as e:
|
|
247
|
+
if target_tuple in targets_to_patch:
|
|
248
|
+
targets_to_patch.remove(target_tuple)
|
|
249
|
+
|
|
250
|
+
if event == "return":
|
|
251
|
+
ctx = TraceContextManager.getLocalContext()
|
|
252
|
+
if ctx and sys_trace_current_service_name == f"{module_name}:{full_target_name}":
|
|
253
|
+
end_interceptor(ctx)
|
|
254
|
+
if patching_queue:
|
|
255
|
+
prev_ctx = patching_queue.pop()
|
|
256
|
+
TraceContextManager.setLocalContext(prev_ctx)
|
|
257
|
+
sys_trace_current_service_name = prev_ctx.service_name
|
|
258
|
+
else:
|
|
259
|
+
if not(targets_to_patch):
|
|
260
|
+
sys.settrace(None)
|
|
261
|
+
|
|
262
|
+
if event == "exception":
|
|
263
|
+
ctx = TraceContextManager.getLocalContext()
|
|
264
|
+
if ctx and sys_trace_current_service_name == f"{module_name}:{full_target_name}":
|
|
265
|
+
exc_type, exc_value , tb = arg
|
|
266
|
+
error_interceptor(exc_value,exc_type,ctx)
|
|
267
|
+
end_interceptor(ctx)
|
|
268
|
+
if patching_queue:
|
|
269
|
+
prev_ctx = patching_queue.pop()
|
|
270
|
+
TraceContextManager.setLocalContext(prev_ctx)
|
|
271
|
+
sys_trace_current_service_name = prev_ctx.service_name
|
|
272
|
+
else:
|
|
273
|
+
if not (targets_to_patch):
|
|
274
|
+
sys.settrace(None)
|
|
275
|
+
|
|
276
|
+
return trace_and_patch_profiler
|
|
277
|
+
|
|
278
|
+
sys.settrace(trace_and_patch_profiler)
|