whatap-python 0.1.120__tar.gz → 0.3.35__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.
- whatap_python-0.3.35/PKG-INFO +143 -0
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/__init__.py +141 -42
- whatap_python-0.3.35/whatap/agent/darwin/amd64/whatap_python +0 -0
- whatap_python-0.3.35/whatap/agent/darwin/arm64/whatap_python +0 -0
- whatap_python-0.3.35/whatap/agent/linux/amd64/whatap_python +0 -0
- {whatap-python-0.1.120/whatap/agent/darwin/amd64 → whatap_python-0.3.35/whatap/agent/linux/arm64}/whatap_python +0 -0
- whatap_python-0.3.35/whatap/bootstrap/sitecustomize.py +19 -0
- whatap_python-0.3.35/whatap/build.py +4 -0
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/conf/configuration.py +9 -0
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/conf/configure.py +19 -2
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/io/data_outputx.py +4 -0
- whatap_python-0.3.35/whatap/net/async_sender.py +64 -0
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/net/packet_enum.py +1 -0
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/net/packet_type_enum.py +3 -0
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/net/param_def.py +1 -0
- whatap_python-0.3.35/whatap/net/stackhelper.py +86 -0
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/net/udp_session.py +90 -31
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/net/udp_thread.py +18 -2
- whatap_python-0.3.35/whatap/pack/logSinkPack.py +77 -0
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/pack/pack_enum.py +2 -0
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/scripts/__init__.py +9 -2
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/trace/mod/amqp_kombu.py +2 -2
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/trace/mod/amqp_pika.py +2 -2
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/trace/mod/application_django.py +67 -9
- whatap_python-0.3.35/whatap/trace/mod/application_django_py3.py +249 -0
- whatap_python-0.3.35/whatap/trace/mod/application_fastapi.py +420 -0
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/trace/mod/application_flask.py +3 -3
- whatap_python-0.3.35/whatap/trace/mod/application_frappe.py +222 -0
- whatap_python-0.3.35/whatap/trace/mod/application_graphql.py +141 -0
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/trace/mod/application_nameko.py +1 -1
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/trace/mod/application_wsgi.py +146 -91
- whatap_python-0.3.35/whatap/trace/mod/database_mongo.py +167 -0
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/trace/mod/database_mysql.py +5 -4
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/trace/mod/database_redis.py +5 -5
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/trace/mod/database_toolkit.py +98 -9
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/trace/mod/email_smtp.py +3 -3
- whatap_python-0.3.35/whatap/trace/mod/logging.py +117 -0
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/trace/mod/plugin.py +2 -2
- whatap_python-0.3.35/whatap/trace/simple_trace_context.py +9 -0
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/trace/trace_context.py +6 -2
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/trace/trace_context_manager.py +85 -22
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/trace/trace_import.py +17 -9
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/trace/trace_module_definition.py +25 -0
- whatap_python-0.3.35/whatap/util/debug_util.py +73 -0
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/util/ip_util.py +0 -1
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/util/linked_map.py +4 -25
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/util/throttle_util.py +3 -6
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/util/userid_util.py +6 -3
- whatap_python-0.3.35/whatap_python.egg-info/PKG-INFO +143 -0
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap_python.egg-info/SOURCES.txt +10 -0
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap_python.egg-info/entry_points.txt +0 -1
- whatap-python-0.1.120/PKG-INFO +0 -144
- whatap-python-0.1.120/whatap/agent/darwin/arm64/whatap_python +0 -0
- whatap-python-0.1.120/whatap/agent/linux/amd64/whatap_python +0 -0
- whatap-python-0.1.120/whatap/agent/linux/arm64/whatap_python +0 -0
- whatap-python-0.1.120/whatap/bootstrap/sitecustomize.py +0 -2
- whatap-python-0.1.120/whatap/build.py +0 -4
- whatap-python-0.1.120/whatap/util/debug_util.py +0 -29
- whatap-python-0.1.120/whatap_python.egg-info/PKG-INFO +0 -144
- {whatap-python-0.1.120 → whatap_python-0.3.35}/README.md +0 -0
- {whatap-python-0.1.120 → whatap_python-0.3.35}/setup.cfg +0 -0
- {whatap-python-0.1.120 → whatap_python-0.3.35}/setup.py +0 -0
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/LICENSE +0 -0
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/README.rst +0 -0
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/__main__.py +0 -0
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/bootstrap/__init__.py +0 -0
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/conf/__init__.py +0 -0
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/conf/license.py +0 -0
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/control/__init__.py +0 -0
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/io/__init__.py +0 -0
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/io/data_inputx.py +0 -0
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/net/__init__.py +0 -0
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/pack/__init__.py +0 -0
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/pack/pack.py +0 -0
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/trace/__init__.py +0 -0
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/trace/mod/__init__.py +0 -0
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/trace/mod/application_bottle.py +0 -0
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/trace/mod/application_celery.py +0 -0
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/trace/mod/application_cherrypy.py +0 -0
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/trace/mod/application_tornado.py +0 -0
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/trace/mod/database_postgresql.py +0 -0
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/trace/mod/httpc_django.py +0 -0
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/trace/mod/httpc_httplib.py +0 -0
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/trace/mod/httpc_requests.py +0 -0
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/trace/mod/httpc_urllib3.py +0 -0
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/util/__init__.py +0 -0
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/util/bit_util.py +0 -0
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/util/cardinality/__init__.py +0 -0
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/util/cardinality/hyperloglog.py +0 -0
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/util/cardinality/murmurhash.py +0 -0
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/util/cardinality/registerset.py +0 -0
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/util/compare_util.py +0 -0
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/util/date_util.py +0 -0
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/util/escape_literal_sql.py +0 -0
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/util/hash_util.py +0 -0
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/util/hexa32.py +0 -0
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/util/int_set.py +0 -0
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/util/keygen.py +0 -0
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/util/linked_list.py +0 -0
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/util/metering_util.py +0 -0
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/util/request_double_queue.py +0 -0
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/util/request_queue.py +0 -0
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/util/string_util.py +0 -0
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/value/__init__.py +0 -0
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/value/blob_value.py +0 -0
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/value/boolean_value.py +0 -0
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/value/decimal_value.py +0 -0
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/value/double_summary.py +0 -0
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/value/double_value.py +0 -0
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/value/float_array.py +0 -0
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/value/float_value.py +0 -0
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/value/int_array.py +0 -0
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/value/ip4_value.py +0 -0
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/value/list_value.py +0 -0
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/value/long_array.py +0 -0
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/value/long_summary.py +0 -0
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/value/map_value.py +0 -0
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/value/null_value.py +0 -0
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/value/number_value.py +0 -0
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/value/summary_value.py +0 -0
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/value/text_array.py +0 -0
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/value/text_hash_value.py +0 -0
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/value/text_value.py +0 -0
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/value/value.py +0 -0
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/value/value_enum.py +0 -0
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap/whatap.conf +0 -0
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap_python.egg-info/dependency_links.txt +0 -0
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap_python.egg-info/not-zip-safe +0 -0
- {whatap-python-0.1.120 → whatap_python-0.3.35}/whatap_python.egg-info/top_level.txt +0 -0
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: whatap-python
|
|
3
|
+
Version: 0.3.35
|
|
4
|
+
Summary: Monitoring and Profiling Service
|
|
5
|
+
Home-page: https://www.whatap.io
|
|
6
|
+
Author: whatap
|
|
7
|
+
Author-email: admin@whatap.io
|
|
8
|
+
License: Whatap License
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
.. image:: https://www.whatap.io/img/common/whatap_logo_re.svg
|
|
12
|
+
|
|
13
|
+
.. _WhaTap: https://www.whatap.io/
|
|
14
|
+
|
|
15
|
+
WhaTap_ for python
|
|
16
|
+
==================
|
|
17
|
+
|
|
18
|
+
- Whatap allows for application performance monitoring.
|
|
19
|
+
- Support: WSGI server application & Batch job & Specific method profiling.
|
|
20
|
+
- Python version : 2.7 + & 3.3+
|
|
21
|
+
|
|
22
|
+
Installation
|
|
23
|
+
------------
|
|
24
|
+
|
|
25
|
+
.. code:: bash
|
|
26
|
+
|
|
27
|
+
$ pip install whatap-python
|
|
28
|
+
|
|
29
|
+
Application Monitoring
|
|
30
|
+
----------------------
|
|
31
|
+
|
|
32
|
+
Supported web frameworks such as Django, Flask, Bottle, Cherrypy, Tornado and WSGI Server Application.
|
|
33
|
+
|
|
34
|
+
Configuration
|
|
35
|
+
~~~~~~~~~~~~~
|
|
36
|
+
|
|
37
|
+
.. code:: bash
|
|
38
|
+
|
|
39
|
+
$ export WHATAP_HOME=[PATH]
|
|
40
|
+
$ whatap-setting-config --host [HOST_ADDR]
|
|
41
|
+
--license [LICENSE_KEY]
|
|
42
|
+
--app_name [APPLICATION_NAME]
|
|
43
|
+
--app_process_name [APP_PROCESS_NAME]
|
|
44
|
+
|
|
45
|
+
Usage
|
|
46
|
+
~~~~~
|
|
47
|
+
|
|
48
|
+
.. code:: bash
|
|
49
|
+
|
|
50
|
+
$ whatap-start-agent [YOUR_APPLICATION_START_COMMAND]
|
|
51
|
+
|
|
52
|
+
...
|
|
53
|
+
|
|
54
|
+
Unsupported web frameworks WSGI
|
|
55
|
+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
56
|
+
|
|
57
|
+
If you want WSGI Application monitoring, include the @register_app decorator.
|
|
58
|
+
|
|
59
|
+
.. code:: python
|
|
60
|
+
|
|
61
|
+
import whatap
|
|
62
|
+
|
|
63
|
+
@whatap.register_app
|
|
64
|
+
def simple_app(environ, start_response):
|
|
65
|
+
"""Simplest possible application object"""
|
|
66
|
+
status = '200 OK'
|
|
67
|
+
response_headers = [('Content-type', 'text/plain')]
|
|
68
|
+
start_response(status, response_headers)
|
|
69
|
+
return ['Hello world!\n']
|
|
70
|
+
|
|
71
|
+
Method Profiling
|
|
72
|
+
~~~~~~~~~~~~~~~~
|
|
73
|
+
|
|
74
|
+
If you want method profiling, include the @method_profiling decorator.
|
|
75
|
+
|
|
76
|
+
.. code:: python
|
|
77
|
+
|
|
78
|
+
from whatap import method_profiling
|
|
79
|
+
|
|
80
|
+
@method_profiling
|
|
81
|
+
def db_connection():
|
|
82
|
+
db.connect('mysql:// ..')
|
|
83
|
+
|
|
84
|
+
@method_profiling
|
|
85
|
+
def query():
|
|
86
|
+
db.select('select * from ..')
|
|
87
|
+
|
|
88
|
+
....
|
|
89
|
+
|
|
90
|
+
Batch Monitoring
|
|
91
|
+
----------------
|
|
92
|
+
|
|
93
|
+
for Batch job.
|
|
94
|
+
|
|
95
|
+
Configuration
|
|
96
|
+
~~~~~~~~~~~~~
|
|
97
|
+
|
|
98
|
+
Set Environment valiable configuration.
|
|
99
|
+
|
|
100
|
+
.. code:: bash
|
|
101
|
+
|
|
102
|
+
$ export WHATAP_BATCH_HOME=[PATH]
|
|
103
|
+
$ cat >> $WHATAP_BATCH_HOME/whatap.conf << EOF
|
|
104
|
+
license=[LICENSE_KEY]
|
|
105
|
+
whatap.server.host=[HOST_ADDR]
|
|
106
|
+
|
|
107
|
+
app_name=batch
|
|
108
|
+
app_process_name=batch
|
|
109
|
+
EOF
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
Usage
|
|
113
|
+
~~~~~
|
|
114
|
+
|
|
115
|
+
Start bach agent.
|
|
116
|
+
|
|
117
|
+
.. code:: bash
|
|
118
|
+
|
|
119
|
+
$ whatap-start-batch
|
|
120
|
+
|
|
121
|
+
Example code
|
|
122
|
+
~~~~~~~~~~~~
|
|
123
|
+
|
|
124
|
+
.. code:: python
|
|
125
|
+
|
|
126
|
+
from whatap import method_profiling
|
|
127
|
+
|
|
128
|
+
class Command(BaseCommand):
|
|
129
|
+
|
|
130
|
+
@batch_profiling
|
|
131
|
+
def handle(self, *args, **options):
|
|
132
|
+
// batch code..
|
|
133
|
+
....
|
|
134
|
+
|
|
135
|
+
Restart
|
|
136
|
+
-------
|
|
137
|
+
|
|
138
|
+
Your Application restart.
|
|
139
|
+
|
|
140
|
+
Copyright
|
|
141
|
+
---------
|
|
142
|
+
|
|
143
|
+
Copyright (c) 2017 Whatap, Inc. All rights reserved.
|
|
@@ -39,12 +39,21 @@ class ContextFilter(logging_module.Filter):
|
|
|
39
39
|
record.id = ''
|
|
40
40
|
return True
|
|
41
41
|
|
|
42
|
+
|
|
42
43
|
|
|
43
44
|
from whatap.conf.configure import Configure as conf
|
|
44
|
-
|
|
45
45
|
CONFIG_FILE_NAME = 'whatap.conf'
|
|
46
46
|
LOG_FILE_NAME = 'whatap-hook.log'
|
|
47
47
|
|
|
48
|
+
isFrappeCommands = "get-frappe-commands" in sys.argv if hasattr(sys, "argv") else False
|
|
49
|
+
|
|
50
|
+
def whatap_print(*args):
|
|
51
|
+
if isFrappeCommands:
|
|
52
|
+
logging.info(*args)
|
|
53
|
+
else:
|
|
54
|
+
if len(args) > 0:
|
|
55
|
+
message = " ".join(args)
|
|
56
|
+
print(message)
|
|
48
57
|
|
|
49
58
|
class Logger(object):
|
|
50
59
|
def __init__(self):
|
|
@@ -62,8 +71,8 @@ class Logger(object):
|
|
|
62
71
|
os.mkdir(os.environ['WHATAP_LOGS'])
|
|
63
72
|
|
|
64
73
|
except Exception as e:
|
|
65
|
-
|
|
66
|
-
|
|
74
|
+
whatap_print('WHATAP: LOG FILE WRITE ERROR.')
|
|
75
|
+
whatap_print(
|
|
67
76
|
'WHATAP: Try to execute command. \n {}'.format(
|
|
68
77
|
'sudo mkdir -m 777 -p $WHATAP_HOME/logs`'))
|
|
69
78
|
|
|
@@ -86,7 +95,7 @@ class Logger(object):
|
|
|
86
95
|
|
|
87
96
|
self.logger.setLevel(logging_module.DEBUG)
|
|
88
97
|
except Exception as e:
|
|
89
|
-
|
|
98
|
+
whatap_print('WHATAP: LOGGING ERROR: {}'.format(e))
|
|
90
99
|
else:
|
|
91
100
|
self.print_whatap()
|
|
92
101
|
|
|
@@ -105,7 +114,7 @@ class Logger(object):
|
|
|
105
114
|
os.environ['WHATAP_CONFIG']))
|
|
106
115
|
str += '{0}: {1}\n\n'.format('Logs', os.environ['WHATAP_LOGS'])
|
|
107
116
|
|
|
108
|
-
|
|
117
|
+
whatap_print(str)
|
|
109
118
|
logging.debug(str)
|
|
110
119
|
|
|
111
120
|
|
|
@@ -113,7 +122,7 @@ def read_file(home, file_name):
|
|
|
113
122
|
data = ''
|
|
114
123
|
try:
|
|
115
124
|
f = open(os.path.join(os.environ.get(home), file_name), 'r+')
|
|
116
|
-
data = f.readline()
|
|
125
|
+
data = str(f.readline()).strip()
|
|
117
126
|
f.close()
|
|
118
127
|
finally:
|
|
119
128
|
return data
|
|
@@ -125,8 +134,8 @@ def write_file(home, file_name, value):
|
|
|
125
134
|
f.write(value)
|
|
126
135
|
f.close()
|
|
127
136
|
except Exception as e:
|
|
128
|
-
|
|
129
|
-
|
|
137
|
+
whatap_print('WHATAP: WHATAP HOME ERROR. (path: {})'.format(os.path.join(os.environ.get(home))))
|
|
138
|
+
whatap_print(
|
|
130
139
|
'WHATAP: Try to execute command. \n {}'.format(
|
|
131
140
|
'`sudo chmod -R 777 $WHATAP_HOME`'))
|
|
132
141
|
return False
|
|
@@ -137,7 +146,7 @@ def write_file(home, file_name, value):
|
|
|
137
146
|
def check_whatap_home(target='WHATAP_HOME'):
|
|
138
147
|
whatap_home = os.environ.get(target)
|
|
139
148
|
if not whatap_home:
|
|
140
|
-
|
|
149
|
+
whatap_print('WHATAP: ${} is empty'.format(target))
|
|
141
150
|
|
|
142
151
|
return whatap_home
|
|
143
152
|
|
|
@@ -150,10 +159,10 @@ def init_config(home):
|
|
|
150
159
|
whatap_home = os.getcwd()
|
|
151
160
|
os.environ[home] = whatap_home
|
|
152
161
|
|
|
153
|
-
|
|
154
|
-
|
|
162
|
+
whatap_print('WHATAP: WHATAP_HOME is empty')
|
|
163
|
+
whatap_print(
|
|
155
164
|
'WHATAP: WHATAP_HOME set default CURRENT_WORKING_DIRECTORY value')
|
|
156
|
-
|
|
165
|
+
whatap_print('CURRENT_WORKING_DIRECTORY is {}\n'.format(whatap_home))
|
|
157
166
|
|
|
158
167
|
if not write_file(home, home.lower(), whatap_home):
|
|
159
168
|
return False
|
|
@@ -172,8 +181,8 @@ def init_config(home):
|
|
|
172
181
|
with open(config_file, 'w+') as new_f:
|
|
173
182
|
new_f.write(content)
|
|
174
183
|
except Exception as e:
|
|
175
|
-
|
|
176
|
-
|
|
184
|
+
whatap_print('WHATAP: PERMISSION ERROR: {}'.format(e))
|
|
185
|
+
whatap_print(
|
|
177
186
|
'WHATAP: Try to execute command. \n {}'.format(
|
|
178
187
|
'`sudo chmod -R 777 $WHATAP_HOME`'))
|
|
179
188
|
return False
|
|
@@ -184,7 +193,6 @@ def init_config(home):
|
|
|
184
193
|
def update_config(home, opt_key, opt_value):
|
|
185
194
|
config_file = os.path.join(os.environ[home],
|
|
186
195
|
CONFIG_FILE_NAME)
|
|
187
|
-
|
|
188
196
|
try:
|
|
189
197
|
with open(config_file, 'r+') as f:
|
|
190
198
|
is_update = False
|
|
@@ -198,11 +206,11 @@ def update_config(home, opt_key, opt_value):
|
|
|
198
206
|
|
|
199
207
|
content += line
|
|
200
208
|
if not is_update:
|
|
201
|
-
content += '{0}={1}\n'.format(opt_key, opt_value)
|
|
209
|
+
content += '\n{0}={1}\n'.format(opt_key, opt_value)
|
|
202
210
|
open(config_file, 'w+').write(content)
|
|
203
211
|
|
|
204
212
|
except Exception as e:
|
|
205
|
-
|
|
213
|
+
whatap_print('WHATAP: OPTION ERROR: {}'.format(e))
|
|
206
214
|
|
|
207
215
|
|
|
208
216
|
def config(home):
|
|
@@ -241,9 +249,13 @@ def hooks(home):
|
|
|
241
249
|
logging.debug(e, extra={'id': 'MODULE ERROR'})
|
|
242
250
|
finally:
|
|
243
251
|
try:
|
|
252
|
+
if conf.trace_logging_enabled:
|
|
253
|
+
logging_module = sys.modules.get("logging")
|
|
254
|
+
from whatap.trace.mod.logging import instrument_logging
|
|
255
|
+
instrument_logging(logging_module)
|
|
256
|
+
|
|
244
257
|
if conf.hook_method_patterns:
|
|
245
258
|
from whatap.trace.mod.plugin import instrument_plugin
|
|
246
|
-
|
|
247
259
|
patterns = conf.hook_method_patterns.split(',')
|
|
248
260
|
for pattern in patterns:
|
|
249
261
|
pattern=pattern.strip()
|
|
@@ -281,10 +293,10 @@ def agent():
|
|
|
281
293
|
whatap_home = os.getcwd()
|
|
282
294
|
os.environ[home] = whatap_home
|
|
283
295
|
|
|
284
|
-
|
|
285
|
-
|
|
296
|
+
whatap_print('WHATAP: WHATAP_HOME is empty')
|
|
297
|
+
whatap_print(
|
|
286
298
|
'WHATAP: WHATAP_HOME set default CURRENT_WORKING_DIRECTORY value')
|
|
287
|
-
|
|
299
|
+
whatap_print('CURRENT_WORKING_DIRECTORY is {}\n'.format(whatap_home))
|
|
288
300
|
|
|
289
301
|
if write_file(home, home.lower(), whatap_home):
|
|
290
302
|
os.environ['WHATAP_HOME'] = whatap_home
|
|
@@ -300,13 +312,15 @@ ARCH = {
|
|
|
300
312
|
'x86_32': '386',
|
|
301
313
|
'ARM': 'arm',
|
|
302
314
|
'AArch64': 'arm64',
|
|
315
|
+
'arm64': 'arm64',
|
|
316
|
+
'aarch64': 'arm64'
|
|
303
317
|
}
|
|
304
318
|
|
|
305
319
|
AGENT_NAME = 'whatap_python'
|
|
306
320
|
|
|
307
321
|
|
|
308
322
|
|
|
309
|
-
def go(batch=False):
|
|
323
|
+
def go(batch=False, opts={}):
|
|
310
324
|
newenv=os.environ.copy()
|
|
311
325
|
newenv['WHATAP_VERSION'] = build.version
|
|
312
326
|
newenv['whatap.start'] = str(DateUtil.now())
|
|
@@ -317,6 +331,7 @@ def go(batch=False):
|
|
|
317
331
|
newenv['sys.version_info'] = str(sys.version_info)
|
|
318
332
|
newenv['sys.executable'] = sys.executable
|
|
319
333
|
newenv['sys.path'] = str(sys.path)
|
|
334
|
+
newenv.update(opts)
|
|
320
335
|
|
|
321
336
|
if not batch:
|
|
322
337
|
home = 'WHATAP_HOME'
|
|
@@ -331,11 +346,12 @@ def go(batch=False):
|
|
|
331
346
|
with open(cmdlinepath) as f:
|
|
332
347
|
content = f.read()
|
|
333
348
|
if content:
|
|
334
|
-
return content.
|
|
349
|
+
return content.strip()
|
|
335
350
|
return ''
|
|
336
351
|
pid = read_file(home, file_name)
|
|
337
|
-
if pid and 'whatap_python'
|
|
338
|
-
|
|
352
|
+
if pid and get_pname(pid).find('whatap_python') >= 0:
|
|
353
|
+
os.kill(int(pid), signal.SIGKILL)
|
|
354
|
+
|
|
339
355
|
try:
|
|
340
356
|
home_path= os.environ.get(home)
|
|
341
357
|
if os.path.exists(os.path.join(home_path, AGENT_NAME)):
|
|
@@ -344,28 +360,32 @@ def go(batch=False):
|
|
|
344
360
|
source_cwd = os.path.join(os.path.join(os.path.dirname(__file__), 'agent'), platform.system().lower(),
|
|
345
361
|
ARCH[platform.machine()])
|
|
346
362
|
|
|
347
|
-
|
|
348
363
|
os.symlink(os.path.join(source_cwd, AGENT_NAME),
|
|
349
364
|
os.path.join(home_path, AGENT_NAME))
|
|
350
365
|
|
|
366
|
+
sockfile_path = os.path.join(home_path, 'run')
|
|
367
|
+
if not os.path.exists(sockfile_path):
|
|
368
|
+
os.mkdir(sockfile_path)
|
|
351
369
|
newenv['whatap.enabled'] = 'True'
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
process = subprocess.Popen('./{0}'.format(AGENT_NAME),
|
|
355
|
-
cwd=home_path,env=newenv,
|
|
356
|
-
|
|
357
|
-
|
|
370
|
+
newenv['WHATAP_PID_FILE'] = file_name
|
|
371
|
+
newenv['PYTHON_PARENT_APP_PID'] = str(os.getpid())
|
|
372
|
+
process = subprocess.Popen(['./{0}'.format(AGENT_NAME), '-t', '3', '-d', '1'],
|
|
373
|
+
cwd=home_path,env=newenv, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
|
374
|
+
stdouts, errs = process.communicate()
|
|
375
|
+
whatap_print("executed golang module ", str(stdouts,"utf8"), str(errs, "utf8"))
|
|
358
376
|
except Exception as e:
|
|
359
|
-
|
|
377
|
+
import traceback
|
|
378
|
+
traceback.print_exc()
|
|
379
|
+
whatap_print('WHATAP: AGENT ERROR: {}'.format(e))
|
|
360
380
|
else:
|
|
361
|
-
|
|
381
|
+
whatap_print('WHATAP: AGENT UP! (process name: {})\n'.format(AGENT_NAME))
|
|
362
382
|
|
|
363
383
|
import signal
|
|
364
384
|
|
|
365
385
|
from whatap.trace.mod.application_wsgi import interceptor, start_interceptor, \
|
|
366
|
-
end_interceptor, trace_handler
|
|
367
|
-
|
|
368
|
-
from whatap.trace.trace_context import TraceContext
|
|
386
|
+
end_interceptor, trace_handler, interceptor_step_error
|
|
387
|
+
from whatap.trace.mod.application_fastapi import interceptor_error_log
|
|
388
|
+
from whatap.trace.trace_context import TraceContext, TraceContextManager
|
|
369
389
|
|
|
370
390
|
def register_app(fn):
|
|
371
391
|
@trace_handler(fn, True)
|
|
@@ -392,14 +412,18 @@ def method_profiling(fn):
|
|
|
392
412
|
try:
|
|
393
413
|
ctx = TraceContext()
|
|
394
414
|
ctx.service_name=fn.__name__
|
|
395
|
-
|
|
415
|
+
start_interceptor(ctx)
|
|
396
416
|
callback = fn(*args, **kwargs)
|
|
397
|
-
end_interceptor(thread_id= ctx.thread_id)
|
|
398
417
|
except Exception as e:
|
|
418
|
+
ctx = TraceContextManager.getLocalContext()
|
|
419
|
+
interceptor_step_error(e, ctx=ctx)
|
|
420
|
+
interceptor_error_log(ctx.id, e, fn, args, kwargs)
|
|
399
421
|
logging.debug('WHATAP(@method_profiling): ' + str(e),
|
|
400
422
|
extra={'id': 'WA776'}, exc_info=True)
|
|
401
423
|
finally:
|
|
402
|
-
|
|
424
|
+
ctx = TraceContextManager.getLocalContext()
|
|
425
|
+
end_interceptor(ctx=ctx)
|
|
426
|
+
return callback
|
|
403
427
|
|
|
404
428
|
if not os.environ.get('whatap.enabled'):
|
|
405
429
|
agent()
|
|
@@ -412,7 +436,7 @@ def batch_agent():
|
|
|
412
436
|
batch_home = os.environ.get(home)
|
|
413
437
|
if not batch_home:
|
|
414
438
|
if not read_file(home, home.lower()):
|
|
415
|
-
|
|
439
|
+
whatap_print('WHATAP: WHATAP_HOME_BATCH is empty')
|
|
416
440
|
return
|
|
417
441
|
|
|
418
442
|
if write_file(home, home.lower(), batch_home):
|
|
@@ -431,7 +455,7 @@ def batch_profiling(fn):
|
|
|
431
455
|
home = 'WHATAP_HOME_BATCH'
|
|
432
456
|
batch_home = read_file(home, home.lower())
|
|
433
457
|
if not batch_home:
|
|
434
|
-
|
|
458
|
+
whatap_print(
|
|
435
459
|
'WHATAP(@batch_profiling): try, whatap-start-batch')
|
|
436
460
|
return fn(*args, **kwargs)
|
|
437
461
|
else:
|
|
@@ -455,3 +479,78 @@ def batch_profiling(fn):
|
|
|
455
479
|
return callback if callback else fn(*args, **kwargs)
|
|
456
480
|
|
|
457
481
|
return trace
|
|
482
|
+
|
|
483
|
+
|
|
484
|
+
import fcntl, os, time
|
|
485
|
+
import errno
|
|
486
|
+
def openPortFile(filepath=os.environ.get('WHATAP_LOCK_FILE', '/tmp/whatap-python.lock')):
|
|
487
|
+
f = None
|
|
488
|
+
i=0
|
|
489
|
+
while f == None and i < 100:
|
|
490
|
+
try:
|
|
491
|
+
f = open(filepath, 'r+')
|
|
492
|
+
except IOError as e:
|
|
493
|
+
if e.errno == 2:
|
|
494
|
+
prefix = os.path.split(filepath)[0]
|
|
495
|
+
try:
|
|
496
|
+
if not os.path.exists(prefix):
|
|
497
|
+
os.makedirs(prefix)
|
|
498
|
+
f = open(filepath, 'w+')
|
|
499
|
+
except:
|
|
500
|
+
pass
|
|
501
|
+
i += 1
|
|
502
|
+
|
|
503
|
+
if f:
|
|
504
|
+
try:
|
|
505
|
+
fcntl.lockf(f, fcntl.LOCK_EX)
|
|
506
|
+
return f
|
|
507
|
+
except Exception as e:
|
|
508
|
+
whatap_print(e)
|
|
509
|
+
try:
|
|
510
|
+
f.close()
|
|
511
|
+
except:
|
|
512
|
+
pass
|
|
513
|
+
|
|
514
|
+
def get_port_number(port=6600, home=os.environ.get('WHATAP_HOME')):
|
|
515
|
+
if not home:
|
|
516
|
+
return None
|
|
517
|
+
|
|
518
|
+
for i in range(100):
|
|
519
|
+
f = openPortFile()
|
|
520
|
+
if not f:
|
|
521
|
+
if i > 50:
|
|
522
|
+
time.sleep(0.1)
|
|
523
|
+
continue
|
|
524
|
+
if f:
|
|
525
|
+
lastPortFound = None
|
|
526
|
+
for l in f.readlines():
|
|
527
|
+
l = l.strip()
|
|
528
|
+
try:
|
|
529
|
+
(portFound, portHome) = l.split()
|
|
530
|
+
portFound = int(portFound)
|
|
531
|
+
except:
|
|
532
|
+
continue
|
|
533
|
+
if home == portHome:
|
|
534
|
+
return portFound
|
|
535
|
+
if not lastPortFound or lastPortFound < portFound:
|
|
536
|
+
lastPortFound = int(portFound)
|
|
537
|
+
if not lastPortFound:
|
|
538
|
+
lastPortFound = port
|
|
539
|
+
else:
|
|
540
|
+
lastPortFound += 1
|
|
541
|
+
f.write(str(lastPortFound))
|
|
542
|
+
f.write('\t')
|
|
543
|
+
f.write(home)
|
|
544
|
+
f.write('\n')
|
|
545
|
+
fcntl.lockf(f, fcntl.LOCK_UN)
|
|
546
|
+
f.close()
|
|
547
|
+
return lastPortFound
|
|
548
|
+
|
|
549
|
+
return port
|
|
550
|
+
|
|
551
|
+
|
|
552
|
+
def configPort():
|
|
553
|
+
port = get_port_number()
|
|
554
|
+
if port:
|
|
555
|
+
update_config('WHATAP_HOME', 'net_udp_port', str(port))
|
|
556
|
+
return port
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import sys, os
|
|
2
|
+
|
|
3
|
+
try:
|
|
4
|
+
from whatap import agent
|
|
5
|
+
agent()
|
|
6
|
+
except ModuleNotFoundError:
|
|
7
|
+
pythonpath = os.environ.get('PYTHONPATH')
|
|
8
|
+
if pythonpath.endswith("/bootstrap"):
|
|
9
|
+
pythonpath,_ = os.path.split(pythonpath)
|
|
10
|
+
pythonpath,_ = os.path.split(pythonpath)
|
|
11
|
+
|
|
12
|
+
sys.path.append(pythonpath)
|
|
13
|
+
try:
|
|
14
|
+
from whatap import agent
|
|
15
|
+
agent()
|
|
16
|
+
except ModuleNotFoundError:
|
|
17
|
+
#final fail
|
|
18
|
+
pass
|
|
19
|
+
|
|
@@ -5,7 +5,12 @@ Configuration = {
|
|
|
5
5
|
"trace_auto_normalize_enabled": True,
|
|
6
6
|
"trace_user_enabled": True,
|
|
7
7
|
"trace_user_using_ip": True,
|
|
8
|
+
"trace_logging_enabled": False,
|
|
9
|
+
"trace_loguru_enabled": False,
|
|
10
|
+
"trace_ignore_url_set": [],
|
|
11
|
+
"trace_ignore_url_prefix": None,
|
|
8
12
|
|
|
13
|
+
"debug": False,
|
|
9
14
|
"query_string_enabled": False,
|
|
10
15
|
"query_string_urls": "",
|
|
11
16
|
|
|
@@ -194,4 +199,8 @@ Configuration = {
|
|
|
194
199
|
"master_agent_port" : 6600,
|
|
195
200
|
"unix_socket_enabled":False,
|
|
196
201
|
"unix_socket":"whatap.sock",
|
|
202
|
+
"debug_stack_enabled": False,
|
|
203
|
+
"log_unhandled_exception": 'false',
|
|
204
|
+
"threadstack_faulthandler": False,
|
|
205
|
+
"max_send_queue_size": 1000,
|
|
197
206
|
}
|
|
@@ -14,13 +14,23 @@ class Configure(object):
|
|
|
14
14
|
last_config_modified = 0
|
|
15
15
|
observers = []
|
|
16
16
|
POD_NAME = os.environ.get("POD_NAME") if os.environ.get('POD_NAME') else os.environ.get("PODNAME") if os.environ.get("PODNAME") else ''
|
|
17
|
+
license = None
|
|
18
|
+
max_send_queue_size = 1000
|
|
17
19
|
|
|
18
20
|
@classmethod
|
|
19
21
|
def init(cls, display=True):
|
|
20
|
-
|
|
22
|
+
if cls.last_loaded == 0:
|
|
23
|
+
cls.loadFromEnv()
|
|
21
24
|
cls.last_loaded = time.time()
|
|
22
25
|
return cls.load(display)
|
|
23
26
|
|
|
27
|
+
@classmethod
|
|
28
|
+
def loadFromEnv(cls):
|
|
29
|
+
for key, value in Configuration.items():
|
|
30
|
+
setattr(cls, key, value)
|
|
31
|
+
if not hasattr(cls, "license") and hasattr(cls, "accesskey"):
|
|
32
|
+
setattr(cls, "license", getattr(cls, "accesskey"))
|
|
33
|
+
|
|
24
34
|
@classmethod
|
|
25
35
|
def load(cls, display=True):
|
|
26
36
|
home = 'WHATAP_HOME'
|
|
@@ -29,8 +39,9 @@ class Configure(object):
|
|
|
29
39
|
last_modified = os.path.getmtime(whatap_config)
|
|
30
40
|
if cls.last_config_modified >= last_modified:
|
|
31
41
|
return True
|
|
32
|
-
for key, value in
|
|
42
|
+
for key, value in os.environ.items():
|
|
33
43
|
setattr(cls, key, value)
|
|
44
|
+
|
|
34
45
|
with open(whatap_config, 'r') as f:
|
|
35
46
|
for line in f:
|
|
36
47
|
cls.last_config_modified = last_modified
|
|
@@ -41,11 +52,15 @@ class Configure(object):
|
|
|
41
52
|
key, value = line.split('=')
|
|
42
53
|
key = key.strip()
|
|
43
54
|
value = value.strip()
|
|
55
|
+
if key and key.endswith("_set"):
|
|
56
|
+
value = value.split(",")
|
|
44
57
|
cls.setProperty(key, value)
|
|
45
58
|
|
|
46
59
|
except Exception as e:
|
|
47
60
|
print('WHATAP: ', e)
|
|
48
61
|
continue
|
|
62
|
+
if not getattr(cls, "license") and getattr(cls, "accesskey"):
|
|
63
|
+
setattr(cls, "license", getattr(cls, "accesskey"))
|
|
49
64
|
for callback in cls.observers:
|
|
50
65
|
callback()
|
|
51
66
|
except Exception as e:
|
|
@@ -63,6 +78,8 @@ class Configure(object):
|
|
|
63
78
|
def getProperty(cls, key, value=None):
|
|
64
79
|
if hasattr(cls, key):
|
|
65
80
|
return getattr(cls, key)
|
|
81
|
+
elif key in os.environ:
|
|
82
|
+
return os.environ[key]
|
|
66
83
|
else:
|
|
67
84
|
return value
|
|
68
85
|
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import queue, time, threading
|
|
2
|
+
from . import udp_session
|
|
3
|
+
from whatap.conf.configure import Configure as conf
|
|
4
|
+
from whatap.trace.simple_trace_context import SimpleTraceContext
|
|
5
|
+
|
|
6
|
+
q = queue.Queue(conf.max_send_queue_size)
|
|
7
|
+
|
|
8
|
+
from enum import Enum
|
|
9
|
+
class SendType(Enum):
|
|
10
|
+
DATAS = 1
|
|
11
|
+
RELAY = 2
|
|
12
|
+
|
|
13
|
+
def send_packet( packet_type, ctx, datas=[]):
|
|
14
|
+
ctx = SimpleTraceContext(ctx.id, ctx.start_time, ctx.elapsed, ctx.thread_id)
|
|
15
|
+
_initThread()
|
|
16
|
+
global q
|
|
17
|
+
if q.full():
|
|
18
|
+
return
|
|
19
|
+
q.put((SendType.DATAS, (packet_type, ctx, datas)))
|
|
20
|
+
|
|
21
|
+
def send_relaypack( packbytes):
|
|
22
|
+
_initThread()
|
|
23
|
+
global q
|
|
24
|
+
if q.full():
|
|
25
|
+
return
|
|
26
|
+
q.put((SendType.RELAY, packbytes))
|
|
27
|
+
|
|
28
|
+
def startWhatapThread():
|
|
29
|
+
def __sendPackets():
|
|
30
|
+
global q
|
|
31
|
+
while True:
|
|
32
|
+
packet_env = q.get()
|
|
33
|
+
if not packet_env:
|
|
34
|
+
time.sleep(0.1)
|
|
35
|
+
continue
|
|
36
|
+
sendType,params = packet_env
|
|
37
|
+
if sendType == SendType.DATAS:
|
|
38
|
+
packet_type, ctx, datas = params
|
|
39
|
+
udp_session.UdpSession.send_packet(packet_type, ctx, datas)
|
|
40
|
+
elif sendType == SendType.RELAY:
|
|
41
|
+
packbytes = params
|
|
42
|
+
udp_session.UdpSession.send_relaypack(packbytes)
|
|
43
|
+
t = threading.Thread(target=__sendPackets)
|
|
44
|
+
t.setDaemon(True)
|
|
45
|
+
t.start()
|
|
46
|
+
|
|
47
|
+
_lock = threading.Lock()
|
|
48
|
+
_initialized = False
|
|
49
|
+
|
|
50
|
+
def _initThread():
|
|
51
|
+
global _lock, _initialized
|
|
52
|
+
if _initialized:
|
|
53
|
+
return
|
|
54
|
+
try:
|
|
55
|
+
if _initialized:
|
|
56
|
+
return
|
|
57
|
+
_lock.acquire()
|
|
58
|
+
if _initialized:
|
|
59
|
+
return
|
|
60
|
+
_initialized=True
|
|
61
|
+
startWhatapThread()
|
|
62
|
+
finally:
|
|
63
|
+
_lock.release()
|
|
64
|
+
|