easy-utils-dev 2.155__tar.gz → 2.157__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.
- {easy_utils_dev-2.155 → easy_utils_dev-2.157}/PKG-INFO +1 -1
- {easy_utils_dev-2.155 → easy_utils_dev-2.157}/easy_utils_dev/debugger.py +42 -24
- {easy_utils_dev-2.155 → easy_utils_dev-2.157}/easy_utils_dev/ne1830PSS.py +16 -2
- {easy_utils_dev-2.155 → easy_utils_dev-2.157}/easy_utils_dev/uiserver.py +118 -11
- {easy_utils_dev-2.155 → easy_utils_dev-2.157}/easy_utils_dev/wsnoclib.py +1 -1
- {easy_utils_dev-2.155 → easy_utils_dev-2.157}/easy_utils_dev.egg-info/PKG-INFO +1 -1
- {easy_utils_dev-2.155 → easy_utils_dev-2.157}/easy_utils_dev.egg-info/SOURCES.txt +0 -1
- {easy_utils_dev-2.155 → easy_utils_dev-2.157}/setup.py +1 -1
- easy_utils_dev-2.155/easy_utils_dev/debugger-C-PF4PAMMP.py +0 -486
- {easy_utils_dev-2.155 → easy_utils_dev-2.157}/MANIFEST.in +0 -0
- {easy_utils_dev-2.155 → easy_utils_dev-2.157}/easy_utils_dev/EasySsh.py +0 -0
- {easy_utils_dev-2.155 → easy_utils_dev-2.157}/easy_utils_dev/Events.py +0 -0
- {easy_utils_dev-2.155 → easy_utils_dev-2.157}/easy_utils_dev/FastQueue.py +0 -0
- {easy_utils_dev-2.155 → easy_utils_dev-2.157}/easy_utils_dev/NameObject.py +0 -0
- {easy_utils_dev-2.155 → easy_utils_dev-2.157}/easy_utils_dev/__init__.py +0 -0
- {easy_utils_dev-2.155 → easy_utils_dev-2.157}/easy_utils_dev/abortable.py +0 -0
- {easy_utils_dev-2.155 → easy_utils_dev-2.157}/easy_utils_dev/brevosmtp.py +0 -0
- {easy_utils_dev-2.155 → easy_utils_dev-2.157}/easy_utils_dev/check_license.py +0 -0
- {easy_utils_dev-2.155 → easy_utils_dev-2.157}/easy_utils_dev/cplib.py +0 -0
- {easy_utils_dev-2.155 → easy_utils_dev-2.157}/easy_utils_dev/custom_env.py +0 -0
- {easy_utils_dev-2.155 → easy_utils_dev-2.157}/easy_utils_dev/easy_oracle.py +0 -0
- {easy_utils_dev-2.155 → easy_utils_dev-2.157}/easy_utils_dev/encryptor.py +0 -0
- {easy_utils_dev-2.155 → easy_utils_dev-2.157}/easy_utils_dev/ept.py +0 -0
- {easy_utils_dev-2.155 → easy_utils_dev-2.157}/easy_utils_dev/ept_sql/create_dirs.sql +0 -0
- {easy_utils_dev-2.155 → easy_utils_dev-2.157}/easy_utils_dev/ept_sql/create_ept_tables.sql +0 -0
- {easy_utils_dev-2.155 → easy_utils_dev-2.157}/easy_utils_dev/exceptions.py +0 -0
- {easy_utils_dev-2.155 → easy_utils_dev-2.157}/easy_utils_dev/filescompressor.py +0 -0
- {easy_utils_dev-2.155 → easy_utils_dev-2.157}/easy_utils_dev/generate_license.py +0 -0
- {easy_utils_dev-2.155 → easy_utils_dev-2.157}/easy_utils_dev/keycloakapi.py +0 -0
- {easy_utils_dev-2.155 → easy_utils_dev-2.157}/easy_utils_dev/lralib.py +0 -0
- {easy_utils_dev-2.155 → easy_utils_dev-2.157}/easy_utils_dev/nsp_kafka.py +0 -0
- {easy_utils_dev-2.155 → easy_utils_dev-2.157}/easy_utils_dev/openid_server.py +0 -0
- {easy_utils_dev-2.155 → easy_utils_dev-2.157}/easy_utils_dev/optics_utils.py +0 -0
- {easy_utils_dev-2.155 → easy_utils_dev-2.157}/easy_utils_dev/require_auth.py +0 -0
- {easy_utils_dev-2.155 → easy_utils_dev-2.157}/easy_utils_dev/simple_sqlite.py +0 -0
- {easy_utils_dev-2.155 → easy_utils_dev-2.157}/easy_utils_dev/temp_memory.py +0 -0
- {easy_utils_dev-2.155 → easy_utils_dev-2.157}/easy_utils_dev/utils.py +0 -0
- {easy_utils_dev-2.155 → easy_utils_dev-2.157}/easy_utils_dev/winserviceapi.py +0 -0
- {easy_utils_dev-2.155 → easy_utils_dev-2.157}/easy_utils_dev/wsselib.py +0 -0
- {easy_utils_dev-2.155 → easy_utils_dev-2.157}/easy_utils_dev.egg-info/dependency_links.txt +0 -0
- {easy_utils_dev-2.155 → easy_utils_dev-2.157}/easy_utils_dev.egg-info/requires.txt +0 -0
- {easy_utils_dev-2.155 → easy_utils_dev-2.157}/easy_utils_dev.egg-info/top_level.txt +0 -0
- {easy_utils_dev-2.155 → easy_utils_dev-2.157}/setup.cfg +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
import os
|
|
3
3
|
import shutil
|
|
4
|
-
import sys
|
|
4
|
+
import sys , re , random
|
|
5
5
|
from datetime import datetime
|
|
6
6
|
from logging.handlers import RotatingFileHandler
|
|
7
7
|
from .utils import getRandomKey , convert_mb_to_bytes , getTimestamp, mkdirs , start_thread
|
|
@@ -33,6 +33,33 @@ def setGlobalDebugLevel(level='info') :
|
|
|
33
33
|
gEvent.dispatchEvent('update_debug_level')
|
|
34
34
|
|
|
35
35
|
|
|
36
|
+
class CensorFilter(logging.Filter):
|
|
37
|
+
def __init__(self):
|
|
38
|
+
super().__init__()
|
|
39
|
+
self.censored_strings = []
|
|
40
|
+
self.censor_ip = True
|
|
41
|
+
# Regex for IPv4
|
|
42
|
+
self.ip_regex = re.compile(r"\b\d{1,3}(?:\.\d{1,3}){3}\b")
|
|
43
|
+
|
|
44
|
+
def add_censored_string(self, value):
|
|
45
|
+
if value:
|
|
46
|
+
self.censored_strings.append(str(value))
|
|
47
|
+
|
|
48
|
+
def filter(self, record):
|
|
49
|
+
msg = record.getMessage()
|
|
50
|
+
|
|
51
|
+
# Replace registered sensitive strings
|
|
52
|
+
for s in self.censored_strings:
|
|
53
|
+
x = random.randint(5, 10)
|
|
54
|
+
msg = msg.replace(s, '*'*x)
|
|
55
|
+
# Replace IPs
|
|
56
|
+
if self.censor_ip :
|
|
57
|
+
msg = self.ip_regex.sub("***.***.***.***", msg)
|
|
58
|
+
# Overwrite message
|
|
59
|
+
record.msg = msg
|
|
60
|
+
record.args = ()
|
|
61
|
+
return True
|
|
62
|
+
|
|
36
63
|
class DEBUGGER:
|
|
37
64
|
def __init__(self
|
|
38
65
|
, name
|
|
@@ -45,7 +72,8 @@ class DEBUGGER:
|
|
|
45
72
|
global_debugger=None,
|
|
46
73
|
disable_log_write=False,
|
|
47
74
|
file_name=None,
|
|
48
|
-
seperate_files=True
|
|
75
|
+
seperate_files=True,
|
|
76
|
+
trust_env_log_path=True
|
|
49
77
|
):
|
|
50
78
|
env = custom_env()
|
|
51
79
|
setupEnvironment( 'debugger' )
|
|
@@ -63,6 +91,7 @@ class DEBUGGER:
|
|
|
63
91
|
self.create_log_path(homePath, file_name)
|
|
64
92
|
self.fullSyntax=fullSyntax
|
|
65
93
|
self.onScreen= onscreen
|
|
94
|
+
self.trust_env_log_path = trust_env_log_path
|
|
66
95
|
self.id = id
|
|
67
96
|
self.stream_service = None
|
|
68
97
|
if not env['debugger'].get(name) :
|
|
@@ -78,6 +107,9 @@ class DEBUGGER:
|
|
|
78
107
|
self.global_debugger = global_debugger
|
|
79
108
|
self.isLogWriteDisabled = disable_log_write
|
|
80
109
|
self.type = "CUSTOM_DEBUGGER"
|
|
110
|
+
self.censor = CensorFilter()
|
|
111
|
+
console_handler.addFilter(self.censor)
|
|
112
|
+
|
|
81
113
|
self.seperate_files=seperate_files
|
|
82
114
|
if fullSyntax :
|
|
83
115
|
f = f"[%(asctime)s]-[{self.name}]-[%(levelname)s]: %(message)s"
|
|
@@ -118,8 +150,9 @@ class DEBUGGER:
|
|
|
118
150
|
start_thread(target=self.checks_in_bg)
|
|
119
151
|
|
|
120
152
|
def create_log_path(self , base_path , logname ) :
|
|
153
|
+
# print(f"Creating log path : {base_path} {logname}")
|
|
121
154
|
if not base_path :
|
|
122
|
-
base_path = os.
|
|
155
|
+
base_path = os.getcwd()
|
|
123
156
|
if not logname :
|
|
124
157
|
logname = self.name
|
|
125
158
|
if base_path :
|
|
@@ -128,23 +161,6 @@ class DEBUGGER:
|
|
|
128
161
|
self.filename = logname
|
|
129
162
|
self.lastAbsoluteHomePath = base_path
|
|
130
163
|
self.log_path_with_filename = os.path.join(base_path, f'{logname}.log')
|
|
131
|
-
# print(f"Filename : {self.filename}")
|
|
132
|
-
# print(f"Base Home Path : {self.baseHomePath}")
|
|
133
|
-
# print(f"Log path With Filename : {self.log_path_with_filename}")
|
|
134
|
-
# print(f"Last Absolute Home Path : {self.lastAbsoluteHomePath}")
|
|
135
|
-
|
|
136
|
-
def fix_file_not_found_file_rotation(self) :
|
|
137
|
-
for i in range(self.BACKUP_COUNT) :
|
|
138
|
-
try :
|
|
139
|
-
file_path = self.homePath + f'.{i}'
|
|
140
|
-
# print(f"Checking log file path : {file_path}")
|
|
141
|
-
if not os.path.exists(file_path) :
|
|
142
|
-
with open(file_path, 'a+') as f :
|
|
143
|
-
# print(f"Creating log file path : {file_path}")
|
|
144
|
-
f.write('')
|
|
145
|
-
except :
|
|
146
|
-
pass
|
|
147
|
-
|
|
148
164
|
|
|
149
165
|
def switch_full_syntax(self , toggle) :
|
|
150
166
|
if toggle :
|
|
@@ -165,9 +181,10 @@ class DEBUGGER:
|
|
|
165
181
|
self.console.setFormatter(self.formatter)
|
|
166
182
|
|
|
167
183
|
def updateGlobalHomePath(self ) :
|
|
184
|
+
if not self.trust_env_log_path :
|
|
185
|
+
return
|
|
168
186
|
if not self.isLogWriteDisabled :
|
|
169
187
|
getFromEnv = self.env.get('debugger_homepath' , None )
|
|
170
|
-
# print(f"getFromEnv : {getFromEnv}")
|
|
171
188
|
if getFromEnv :
|
|
172
189
|
self.create_log_path(getFromEnv, self.filename)
|
|
173
190
|
self.file_handler_class = self.createRotateFileHandler(self.log_path_with_filename)
|
|
@@ -258,7 +275,6 @@ class DEBUGGER:
|
|
|
258
275
|
|
|
259
276
|
def checks_in_bg(self) :
|
|
260
277
|
while True :
|
|
261
|
-
#self.fix_file_not_found_file_rotation()
|
|
262
278
|
if self.env.get('GLOBAL_DEBUGGER_STREAM_SERVICE') :
|
|
263
279
|
self.addStreamService(socketio=self.env.get('GLOBAL_DEBUGGER_STREAM_SERVICE'))
|
|
264
280
|
if self.env.get('debugger_global_level' , None) :
|
|
@@ -273,7 +289,8 @@ class DEBUGGER:
|
|
|
273
289
|
self.logger.error(f'EASY_UTILS_DEBUG_LEVEL ENV must be one of [info,debug,warning,error,critical] | Current Env Variable Is "{EASY_UTILS_DEBUG_LEVEL}". Skipping ')
|
|
274
290
|
else :
|
|
275
291
|
self.set_level(EASY_UTILS_DEBUG_LEVEL)
|
|
276
|
-
self.
|
|
292
|
+
if self.trust_env_log_path :
|
|
293
|
+
self.updateGlobalHomePath()
|
|
277
294
|
if os.environ.get("EASY_UTILS_ENABLE_PRINT" , '' ).lower() == 'true' :
|
|
278
295
|
self.enable_print()
|
|
279
296
|
sleep(10)
|
|
@@ -314,12 +331,13 @@ class DEBUGGER:
|
|
|
314
331
|
def changeHomePath( self , path ) :
|
|
315
332
|
def delet_later(lastAbsoluteHomePath) :
|
|
316
333
|
if lastAbsoluteHomePath :
|
|
317
|
-
sleep(
|
|
334
|
+
sleep(1)
|
|
318
335
|
try :
|
|
319
336
|
shutil.rmtree(lastAbsoluteHomePath)
|
|
320
337
|
except :
|
|
321
338
|
pass
|
|
322
339
|
start_thread(target=delet_later, args=[self.lastAbsoluteHomePath])
|
|
340
|
+
sleep(.5)
|
|
323
341
|
self.create_log_path( path , self.filename)
|
|
324
342
|
self.file_handler_class = self.createRotateFileHandler(self.log_path_with_filename)
|
|
325
343
|
|
|
@@ -12,9 +12,23 @@ from easy_utils_dev import exceptions
|
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
class PSS1830 :
|
|
15
|
-
def __init__(self ,
|
|
15
|
+
def __init__(self ,
|
|
16
|
+
sim=False ,
|
|
17
|
+
debug_name='Auto1830PSS' ,
|
|
18
|
+
auto_enable_tcp_forward=False,
|
|
19
|
+
file_name=None,
|
|
20
|
+
debug_home_path=None,
|
|
21
|
+
trust_env_log_path=True,
|
|
22
|
+
debugger_kwargs={}
|
|
23
|
+
) -> None:
|
|
16
24
|
self.port = None
|
|
17
|
-
self.
|
|
25
|
+
self.trust_env_log_path = trust_env_log_path
|
|
26
|
+
self.logger = DEBUGGER(
|
|
27
|
+
debug_name,file_name=file_name,
|
|
28
|
+
homePath=debug_home_path,
|
|
29
|
+
trust_env_log_path=trust_env_log_path,
|
|
30
|
+
**debugger_kwargs
|
|
31
|
+
)
|
|
18
32
|
self.connected = False
|
|
19
33
|
self.channel = None
|
|
20
34
|
self.nodeName = None
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import gc
|
|
2
|
+
import json
|
|
2
3
|
import time
|
|
4
|
+
from flask.ctx import F
|
|
3
5
|
from werkzeug.serving import ThreadedWSGIServer
|
|
4
|
-
from easy_utils_dev.utils import getRandomKey , generateToken , getTimestamp
|
|
6
|
+
from easy_utils_dev.utils import convertTimestampToDate, getRandomKey , generateToken , getTimestamp
|
|
5
7
|
from flask_socketio import SocketIO
|
|
6
8
|
from engineio.async_drivers import gevent
|
|
9
|
+
from engineio.async_drivers import threading as threading_engineio
|
|
7
10
|
from flask_cors import CORS
|
|
8
11
|
import logging , os
|
|
9
12
|
from flask import jsonify, request , current_app , copy_current_request_context
|
|
@@ -18,6 +21,9 @@ from werkzeug.serving import make_ssl_devcert
|
|
|
18
21
|
from time import sleep
|
|
19
22
|
from easy_utils_dev.utils import start_thread , getRandomKeysAndStr , mkdirs
|
|
20
23
|
from easy_utils_dev.temp_memory import TemporaryMemory
|
|
24
|
+
from easy_utils_dev.debugger import DEBUGGER
|
|
25
|
+
import signal
|
|
26
|
+
import sys
|
|
21
27
|
|
|
22
28
|
def getClassById( id ) :
|
|
23
29
|
return cenv[id]
|
|
@@ -92,6 +98,7 @@ class SocketClientObject :
|
|
|
92
98
|
|
|
93
99
|
class UISERVER :
|
|
94
100
|
def __init__(self ,
|
|
101
|
+
logger : DEBUGGER = None,
|
|
95
102
|
id=getRandomKey(n=15),
|
|
96
103
|
secretkey=generateToken(),
|
|
97
104
|
serve_with_secret_key=False,
|
|
@@ -121,6 +128,7 @@ class UISERVER :
|
|
|
121
128
|
self.bg_requests = {}
|
|
122
129
|
self.socketio_clients = []
|
|
123
130
|
self.abort_base_url = '/request/abort'
|
|
131
|
+
self.return_exception_as_code_400 = True
|
|
124
132
|
self.request_reply_base_url= '/request/result'
|
|
125
133
|
if https :
|
|
126
134
|
self.httpProtocol = 'https'
|
|
@@ -133,6 +141,10 @@ class UISERVER :
|
|
|
133
141
|
start_thread(target=self.delete_very_old_requests)
|
|
134
142
|
self.secret_key_execlude_urls = []
|
|
135
143
|
self.socketio_rooms = {}
|
|
144
|
+
self.log_url_requests = True
|
|
145
|
+
self.logger = logger
|
|
146
|
+
self.simulate_network_delay = False
|
|
147
|
+
|
|
136
148
|
|
|
137
149
|
def update_cert(self , crt, ssl ) :
|
|
138
150
|
self.ssl_crt=crt
|
|
@@ -158,6 +170,7 @@ class UISERVER :
|
|
|
158
170
|
|
|
159
171
|
def delete_very_old_requests(self) :
|
|
160
172
|
while True :
|
|
173
|
+
sleep(320)
|
|
161
174
|
now = getTimestamp()
|
|
162
175
|
for key, value in list(self.bg_requests.items()) :
|
|
163
176
|
value : AbortRequest = value
|
|
@@ -165,7 +178,6 @@ class UISERVER :
|
|
|
165
178
|
if value.delete_async_request_ts > now :
|
|
166
179
|
del self.bg_requests[key]
|
|
167
180
|
gc.collect()
|
|
168
|
-
sleep(320)
|
|
169
181
|
|
|
170
182
|
def create_room(self , room_id : str , members : list[str] ) :
|
|
171
183
|
self.socketio_rooms[room_id] = members
|
|
@@ -197,6 +209,14 @@ class UISERVER :
|
|
|
197
209
|
else :
|
|
198
210
|
return { 'status' : 404 , 'message' : 'Request not found or request is not abortable. Check request headers for abortable flag.'}
|
|
199
211
|
|
|
212
|
+
@self.app.route(f"/request/traceback/<key>" , methods=['GET'])
|
|
213
|
+
def get_traceback(key : str ) :
|
|
214
|
+
traceback = self.cache.get(key)
|
|
215
|
+
if traceback :
|
|
216
|
+
return { 'status' : 200 , 'traceback' : traceback.get('traceback') }
|
|
217
|
+
else :
|
|
218
|
+
return { 'status' : 404 , 'message' : 'Traceback not found or expired' }
|
|
219
|
+
|
|
200
220
|
@self.app.route(f'{self.request_reply_base_url}/<id>' , methods=['GET'])
|
|
201
221
|
def get_result_of_async_request(id : str ) :
|
|
202
222
|
request : AbortRequest = self.bg_requests.get(id)
|
|
@@ -217,6 +237,10 @@ class UISERVER :
|
|
|
217
237
|
|
|
218
238
|
@self.app.before_request
|
|
219
239
|
def before_request() :
|
|
240
|
+
if self.log_url_requests and self.logger :
|
|
241
|
+
self.logger.info(f'[{request.method}]: {request.url}' , source='WebServer')
|
|
242
|
+
|
|
243
|
+
|
|
220
244
|
if (self.serve_with_secret_key) and (request.path not in self.secret_key_execlude_urls) and (request.headers.get('secretkey') != self.secretkey):
|
|
221
245
|
return jsonify({"error": "Secret key is invalid"}), 401
|
|
222
246
|
|
|
@@ -257,26 +281,72 @@ class UISERVER :
|
|
|
257
281
|
if request.headers.get('async') == 'false' :
|
|
258
282
|
target_func = current_app.view_functions.get(request.endpoint)
|
|
259
283
|
if not target_func:
|
|
260
|
-
return
|
|
284
|
+
return {"error": "Route not found"}, 404
|
|
261
285
|
th = start_thread(target=run_async_job_results, args=[target_func , abort ])
|
|
262
286
|
abort.thread = th
|
|
263
287
|
self.bg_requests[requestId] = abort
|
|
264
288
|
return {"status": 200, "message": "Request now in running bg", "abort_id": abort.abort_id} , 200
|
|
265
289
|
|
|
290
|
+
if self.return_exception_as_code_400 :
|
|
291
|
+
@self.app.errorhandler(Exception)
|
|
292
|
+
def handle_exception(e):
|
|
293
|
+
|
|
294
|
+
exc_type, exc_value, exc_traceback = sys.exc_info()
|
|
295
|
+
key = getRandomKeysAndStr(n=10)
|
|
296
|
+
tb_last = traceback.extract_tb(exc_traceback)[-1] # Get last traceback frame
|
|
297
|
+
# Example: file, line, function, text
|
|
298
|
+
error_file = tb_last.filename
|
|
299
|
+
error_line = tb_last.lineno
|
|
300
|
+
error_func = tb_last.name
|
|
301
|
+
error_code = tb_last.line
|
|
302
|
+
|
|
303
|
+
# Log the full traceback (optional)
|
|
304
|
+
traceback.print_exc()
|
|
305
|
+
# Customize the error response
|
|
306
|
+
t = getTimestamp()
|
|
307
|
+
response = {
|
|
308
|
+
"status" : 400 ,
|
|
309
|
+
"key" : key,
|
|
310
|
+
"error": str(e),
|
|
311
|
+
"message": str(e),
|
|
312
|
+
"type": type(e).__name__ ,
|
|
313
|
+
"request_full_url" : request.url ,
|
|
314
|
+
"request_method" : request.method ,
|
|
315
|
+
"endpoint" : request.endpoint ,
|
|
316
|
+
"request_path" : request.path ,
|
|
317
|
+
"error_file" : os.path.basename(error_file).replace('.py' , ''),
|
|
318
|
+
"error_line" : error_line,
|
|
319
|
+
"error_func" : error_func,
|
|
320
|
+
"error_code" : error_code,
|
|
321
|
+
'timestamp' : t ,
|
|
322
|
+
"date" : convertTimestampToDate(t) ,
|
|
323
|
+
'traceback_url' : f"/request/traceback/{key}"
|
|
324
|
+
}
|
|
325
|
+
self.logger.error(f'error: {json.dumps(response , indent=4)}')
|
|
326
|
+
self.cache.set( custom_key=key , item={**response , 'traceback' : str(traceback.format_exc())} , auto_destroy_period=1800 , store_deleted_key=False )
|
|
327
|
+
# del response['traceback']
|
|
328
|
+
return response , 200
|
|
266
329
|
|
|
267
330
|
@self.app.after_request
|
|
268
331
|
def after_request(response) :
|
|
332
|
+
|
|
333
|
+
if self.simulate_network_delay :
|
|
334
|
+
time.sleep(self.simulate_network_delay)
|
|
335
|
+
|
|
269
336
|
try :
|
|
270
337
|
now = getTimestamp()
|
|
271
338
|
response.headers['internalid'] = request.internalid
|
|
272
339
|
response.headers['start_ts'] = request.start_ts
|
|
273
340
|
response.headers['end_ts'] = now
|
|
274
|
-
|
|
341
|
+
x = round(now - request.start_ts, 2)
|
|
342
|
+
response.headers['execution'] = x
|
|
275
343
|
if request.abortable :
|
|
276
344
|
response.headers['abortid'] = request.abort_id
|
|
277
345
|
response.headers['abortable'] = True
|
|
278
346
|
except :
|
|
279
347
|
response.headers['abortable'] = False
|
|
348
|
+
if self.log_url_requests and self.logger :
|
|
349
|
+
self.logger.info(f'[{request.method}]: {request.url} - [{response.status_code}] [secs:{x}]' , source='WebServer')
|
|
280
350
|
return response
|
|
281
351
|
|
|
282
352
|
# socketio client connected.
|
|
@@ -322,12 +392,18 @@ class UISERVER :
|
|
|
322
392
|
return self.wsgi_server
|
|
323
393
|
|
|
324
394
|
def shutdownUi(self) :
|
|
395
|
+
if hasattr(self, 'wsgi_server') and self.wsgi_server:
|
|
396
|
+
try:
|
|
397
|
+
self.wsgi_server.shutdown()
|
|
398
|
+
self.wsgi_server.server_close()
|
|
399
|
+
except:
|
|
400
|
+
pass
|
|
325
401
|
kill_thread(self.thread)
|
|
326
|
-
self.wsgi_server.server_close()
|
|
327
|
-
self.wsgi_server.shutdown()
|
|
328
402
|
|
|
329
403
|
def _wait_th(self , t ) :
|
|
330
|
-
t.join()
|
|
404
|
+
# t.join()
|
|
405
|
+
while True :
|
|
406
|
+
time.sleep(10)
|
|
331
407
|
|
|
332
408
|
|
|
333
409
|
def thrStartUi(self , suppress_prints=True) :
|
|
@@ -356,15 +432,46 @@ class UISERVER :
|
|
|
356
432
|
log.setLevel(logging.ERROR)
|
|
357
433
|
wsgi_server.serve_forever()
|
|
358
434
|
|
|
359
|
-
def
|
|
435
|
+
def on_ctrl_c(self , sig=None, frame=None):
|
|
436
|
+
self.stopUi()
|
|
437
|
+
pid = os.getpid()
|
|
438
|
+
os.kill(pid, signal.SIGTERM)
|
|
439
|
+
sys.exit(0)
|
|
440
|
+
|
|
441
|
+
|
|
442
|
+
def startUi(self , daemon=False , suppress_prints=True , block=False) :
|
|
360
443
|
self.start_before_request()
|
|
361
444
|
self.thread = self.flaskprocess = Thread(target=self.thrStartUi , args=[suppress_prints])
|
|
362
|
-
self.flaskprocess.daemon =
|
|
445
|
+
self.flaskprocess.daemon = daemon
|
|
363
446
|
self.flaskprocess.start()
|
|
364
447
|
start_thread(target=self._wait_th , args=[self.thread] , daemon=daemon)
|
|
448
|
+
signal.signal(signal.SIGINT, self.on_ctrl_c )
|
|
449
|
+
if block:
|
|
450
|
+
self.wait()
|
|
365
451
|
return self.thread
|
|
366
452
|
|
|
453
|
+
def wait(self):
|
|
454
|
+
"""
|
|
455
|
+
Block the main thread to keep it alive for signal handling (Ctrl+C).
|
|
456
|
+
This allows Ctrl+C to be properly detected. Call this after startUi()
|
|
457
|
+
if you want signal handling to work.
|
|
458
|
+
"""
|
|
459
|
+
try:
|
|
460
|
+
while self.flaskprocess.is_alive():
|
|
461
|
+
self.flaskprocess.join(timeout=0.1)
|
|
462
|
+
except KeyboardInterrupt:
|
|
463
|
+
if not hasattr(self, '_shutting_down'):
|
|
464
|
+
self._shutting_down = True
|
|
465
|
+
self.on_ctrl_c()
|
|
466
|
+
except SystemExit:
|
|
467
|
+
# Re-raise SystemExit to allow proper program termination
|
|
468
|
+
raise
|
|
469
|
+
|
|
367
470
|
def stopUi(self) :
|
|
471
|
+
if hasattr(self, 'wsgi_server') and self.wsgi_server:
|
|
472
|
+
try:
|
|
473
|
+
self.wsgi_server.shutdown()
|
|
474
|
+
except:
|
|
475
|
+
pass
|
|
368
476
|
kill_thread(self.thread)
|
|
369
|
-
return True
|
|
370
|
-
|
|
477
|
+
return True
|
|
@@ -1,486 +0,0 @@
|
|
|
1
|
-
import logging
|
|
2
|
-
import os
|
|
3
|
-
import sys
|
|
4
|
-
from datetime import datetime
|
|
5
|
-
from logging.handlers import RotatingFileHandler
|
|
6
|
-
from .utils import getRandomKey , convert_mb_to_bytes , getTimestamp , start_thread
|
|
7
|
-
from .custom_env import custom_env , setupEnvironment
|
|
8
|
-
from .Events import EventEmitter
|
|
9
|
-
from threading import Thread
|
|
10
|
-
from time import sleep
|
|
11
|
-
|
|
12
|
-
gEvent = EventEmitter()
|
|
13
|
-
logging.addLevelName(25, "SCREEN")
|
|
14
|
-
|
|
15
|
-
def setGlobalHomePath( path ) :
|
|
16
|
-
env = custom_env()
|
|
17
|
-
env['debugger_homepath'] = path
|
|
18
|
-
gEvent.dispatchEvent('update_home_path')
|
|
19
|
-
|
|
20
|
-
def setGlobalDisableOnScreen(on_screen=False) :
|
|
21
|
-
env = custom_env()
|
|
22
|
-
env['debugger_on_screen'] = on_screen
|
|
23
|
-
if not on_screen :
|
|
24
|
-
gEvent.dispatchEvent('disable_global_printing')
|
|
25
|
-
else :
|
|
26
|
-
gEvent.dispatchEvent('enable_global_printing')
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
def setGlobalDebugLevel(level='info') :
|
|
30
|
-
env = custom_env()
|
|
31
|
-
env['debugger_global_level'] = level
|
|
32
|
-
gEvent.dispatchEvent('update_debug_level')
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
class DEBUGGER:
|
|
36
|
-
def __init__(self
|
|
37
|
-
, name
|
|
38
|
-
, level='info',
|
|
39
|
-
fullSyntax=True,
|
|
40
|
-
onscreen=True,
|
|
41
|
-
log_rotation=3,
|
|
42
|
-
homePath=None,
|
|
43
|
-
id=getRandomKey(9) ,
|
|
44
|
-
global_debugger=None,
|
|
45
|
-
disable_log_write=False,
|
|
46
|
-
file_name=None,
|
|
47
|
-
seperate_files=True
|
|
48
|
-
):
|
|
49
|
-
env = custom_env()
|
|
50
|
-
setupEnvironment( 'debugger' )
|
|
51
|
-
debugger_on_screen = env.get('debugger_on_screen' , True)
|
|
52
|
-
env['debugger_on_screen'] = debugger_on_screen
|
|
53
|
-
self.env = env
|
|
54
|
-
self.events = gEvent
|
|
55
|
-
self.debuggerLabel = f"{name}"
|
|
56
|
-
self.logger = logging.getLogger(self.debuggerLabel)
|
|
57
|
-
self.set_level(level)
|
|
58
|
-
self.file_handler_class=None
|
|
59
|
-
self.LOG_SIZE_THRESHOLD_IN_BYTES = 10 * 1024 * 1024
|
|
60
|
-
self.BACKUP_COUNT = log_rotation
|
|
61
|
-
self.homePath = homePath
|
|
62
|
-
self.lastAbsoluteHomePath= None
|
|
63
|
-
self.fullSyntax=fullSyntax
|
|
64
|
-
self.onScreen= onscreen
|
|
65
|
-
self.id = id
|
|
66
|
-
self.how_many_times_write= 0
|
|
67
|
-
self.stream_service = None
|
|
68
|
-
if not env['debugger'].get(name) :
|
|
69
|
-
self.console = console_handler = logging.StreamHandler()
|
|
70
|
-
else :
|
|
71
|
-
self.console = console_handler = env['debugger'].get(name).console
|
|
72
|
-
if not self.logger.hasHandlers() :
|
|
73
|
-
self.logger.addHandler(self.console)
|
|
74
|
-
self.name = name
|
|
75
|
-
self.rotate_disabled=False
|
|
76
|
-
self.isInPyinstaller = False
|
|
77
|
-
self.log_iterations=0
|
|
78
|
-
self.log_iterations_threshold = 200
|
|
79
|
-
self.global_debugger = global_debugger
|
|
80
|
-
self.isLogWriteDisabled = disable_log_write
|
|
81
|
-
self.type = "CUSTOM_DEBUGGER"
|
|
82
|
-
self.seperate_files=seperate_files
|
|
83
|
-
if fullSyntax :
|
|
84
|
-
f = f"[%(asctime)s]-[{self.name}]-[%(levelname)s]: %(message)s"
|
|
85
|
-
else :
|
|
86
|
-
f = f"[{self.name}]-[%(levelname)s]: %(message)s"
|
|
87
|
-
self.syntax = f
|
|
88
|
-
self.formatter = logging.Formatter(f , datefmt='%Y-%m-%d %H:%M:%S' )
|
|
89
|
-
self.filename = file_name
|
|
90
|
-
path = self.homepath(homePath)
|
|
91
|
-
if not env['debugger'].get(name) :
|
|
92
|
-
console_handler.setFormatter(self.formatter)
|
|
93
|
-
if not disable_log_write :
|
|
94
|
-
if not env['debugger'].get(name) :
|
|
95
|
-
self.file_handler_class = self.createRotateFileHandler(path)
|
|
96
|
-
if onscreen :
|
|
97
|
-
self.enable_print()
|
|
98
|
-
elif not onscreen :
|
|
99
|
-
self.disable_print()
|
|
100
|
-
self.events.addEventListener('disable_global_printing' , self.disable_print )
|
|
101
|
-
self.events.addEventListener('enable_global_printing' , self.enable_print )
|
|
102
|
-
self.events.addEventListener('update_home_path' , self.updateGlobalHomePath )
|
|
103
|
-
self.events.addEventListener('update_debug_level' , self.updateGlobalSetLevel )
|
|
104
|
-
if env['debugger'].get(name) :
|
|
105
|
-
self = env['debugger'].get(name)
|
|
106
|
-
else:
|
|
107
|
-
env['debugger'][id] = self
|
|
108
|
-
env['debugger'][name] = self
|
|
109
|
-
if not env.get('debugger_on_screen' , True ) :
|
|
110
|
-
self.disable_print()
|
|
111
|
-
if env.get('debugger_on_screen' , True ) :
|
|
112
|
-
self.enable_print()
|
|
113
|
-
if os.environ.get("EASY_UTILS_DEBUG_LEVEL") :
|
|
114
|
-
EASY_UTILS_DEBUG_LEVEL = os.environ.get("EASY_UTILS_DEBUG_LEVEL")
|
|
115
|
-
if not EASY_UTILS_DEBUG_LEVEL.lower() in ['info' , 'debug' , 'warning' , 'error' , 'critical'] :
|
|
116
|
-
self.logger.error(f'EASY_UTILS_DEBUG_LEVEL ENV must be one of [info,debug,warning,error,critical] | Current Env Variable Is "{EASY_UTILS_DEBUG_LEVEL}". Skipping ')
|
|
117
|
-
else :
|
|
118
|
-
self.set_level(EASY_UTILS_DEBUG_LEVEL)
|
|
119
|
-
if os.environ.get("EASY_UTILS_ENABLE_PRINT" , '' ).lower() == 'true' :
|
|
120
|
-
self.enable_print()
|
|
121
|
-
|
|
122
|
-
def switch_full_syntax(self , toggle) :
|
|
123
|
-
if toggle :
|
|
124
|
-
f = f"[%(asctime)s]-[{self.name}]-[%(levelname)s]: %(message)s"
|
|
125
|
-
else :
|
|
126
|
-
f = f"[{self.name}]-[%(levelname)s]: %(message)s"
|
|
127
|
-
self.syntax = f
|
|
128
|
-
self.formatter = logging.Formatter(f , datefmt='%Y-%m-%d %H:%M:%S' )
|
|
129
|
-
self.console.setFormatter(self.formatter)
|
|
130
|
-
|
|
131
|
-
def custom_log_syntax(self , syntax) :
|
|
132
|
-
'''
|
|
133
|
-
f"[%(asctime)s]-[{self.name}]-[%(levelname)s]: %(message)s"
|
|
134
|
-
'''
|
|
135
|
-
f = syntax
|
|
136
|
-
self.syntax = f
|
|
137
|
-
self.formatter = logging.Formatter(f , datefmt='%Y-%m-%d %H:%M:%S' )
|
|
138
|
-
self.console.setFormatter(self.formatter)
|
|
139
|
-
|
|
140
|
-
def updateGlobalHomePath(self ) :
|
|
141
|
-
if not self.isLogWriteDisabled :
|
|
142
|
-
getFromEnv = self.env.get('debugger_homepath' , None )
|
|
143
|
-
self.homepath(getFromEnv)
|
|
144
|
-
if getFromEnv :
|
|
145
|
-
self.file_handler_class = self.createRotateFileHandler(self.homePath)
|
|
146
|
-
|
|
147
|
-
def updateGlobalSetLevel( self ) :
|
|
148
|
-
self.set_level(self.env['debugger_global_level'])
|
|
149
|
-
|
|
150
|
-
def advertiseGlobalDebugLevel(self , level) :
|
|
151
|
-
setGlobalDebugLevel(level)
|
|
152
|
-
|
|
153
|
-
def disable_rotate(self) :
|
|
154
|
-
self.rotate_disabled = True
|
|
155
|
-
|
|
156
|
-
def enable_rotate(self) :
|
|
157
|
-
self.rotate_disabled = False
|
|
158
|
-
|
|
159
|
-
def createRotateFileHandler( self , path ) :
|
|
160
|
-
old = self.file_handler_class
|
|
161
|
-
if old :
|
|
162
|
-
self.logger.removeHandler(old)
|
|
163
|
-
file_handler = RotatingFileHandler(path , maxBytes=self.LOG_SIZE_THRESHOLD_IN_BYTES , backupCount=self.BACKUP_COUNT , delay=True )
|
|
164
|
-
self.file_handler= file_handler.setFormatter(self.formatter)
|
|
165
|
-
self.logger.addHandler(file_handler)
|
|
166
|
-
return file_handler
|
|
167
|
-
|
|
168
|
-
def update_log_iterantions_threshold(self,threshold : int ):
|
|
169
|
-
'''
|
|
170
|
-
set value when rotation should be checked. when every on_log function called.
|
|
171
|
-
by default rotation will be checked every 200 on_log function call.
|
|
172
|
-
'''
|
|
173
|
-
self.log_iterations_threshold = threshold
|
|
174
|
-
|
|
175
|
-
def updateGlobalDebugger(self , logger ) :
|
|
176
|
-
'''
|
|
177
|
-
this function pass the log message to other logger to write the same log message to it.
|
|
178
|
-
logger must be debugger class.
|
|
179
|
-
'''
|
|
180
|
-
if logger.type != 'CUSTOM_DEBUGGER' :
|
|
181
|
-
raise Exception(f'Invalid logger type. must pass debugger class.')
|
|
182
|
-
self.global_debugger = logger
|
|
183
|
-
|
|
184
|
-
def getStreamServiceUrlPath(self) :
|
|
185
|
-
return self.streampath
|
|
186
|
-
|
|
187
|
-
def getStreamService(self) :
|
|
188
|
-
return self.stream_service
|
|
189
|
-
|
|
190
|
-
def isStreamServiceAvailable(self) :
|
|
191
|
-
if self.stream_service :
|
|
192
|
-
return True
|
|
193
|
-
return False
|
|
194
|
-
|
|
195
|
-
def addStreamService( self , socketio , streampath='/debugger/stream/log' ) :
|
|
196
|
-
"""
|
|
197
|
-
This function takes a live socketio server. it emit the log message using default path which is /debugger/stream/log
|
|
198
|
-
"""
|
|
199
|
-
self.stream_service = socketio
|
|
200
|
-
self.streampath = streampath
|
|
201
|
-
|
|
202
|
-
def updateLogName( self , name ) :
|
|
203
|
-
self.name = name
|
|
204
|
-
|
|
205
|
-
def disable_log_write(self) :
|
|
206
|
-
'''
|
|
207
|
-
this function is used to disable the log write to file. if onScreen is enabled, logs will be displayed only on screen.
|
|
208
|
-
'''
|
|
209
|
-
self.isLogWriteDisabled = True
|
|
210
|
-
if self.file_handler_class :
|
|
211
|
-
self.logger.removeHandler(self.file_handler_class)
|
|
212
|
-
|
|
213
|
-
def enable_log_write(self) :
|
|
214
|
-
self.createRotateFileHandler(self.homePath)
|
|
215
|
-
|
|
216
|
-
def manage_file_rotation(self, record ) :
|
|
217
|
-
handler = self.get_rotate_handler()
|
|
218
|
-
if handler.shouldRollover(record) :
|
|
219
|
-
handler.doRollover()
|
|
220
|
-
self.log_iterations = 0
|
|
221
|
-
|
|
222
|
-
def get_rotate_handler(self) :
|
|
223
|
-
return self.file_handler_class
|
|
224
|
-
|
|
225
|
-
def change_log_size(self, size) -> bool:
|
|
226
|
-
'''
|
|
227
|
-
change the size of each log file rotation.
|
|
228
|
-
default is 10M
|
|
229
|
-
size should be passed as MB
|
|
230
|
-
'''
|
|
231
|
-
size = convert_mb_to_bytes(size)
|
|
232
|
-
self.LOG_SIZE_THRESHOLD_IN_BYTES = size
|
|
233
|
-
handler = self.get_rotate_handler()
|
|
234
|
-
handler.maxBytes = size
|
|
235
|
-
return True
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
def checks_in_bg(self) :
|
|
239
|
-
while True :
|
|
240
|
-
if self.env.get('GLOBAL_DEBUGGER_STREAM_SERVICE') :
|
|
241
|
-
self.addStreamService(socketio=self.env.get('GLOBAL_DEBUGGER_STREAM_SERVICE'))
|
|
242
|
-
if self.env.get('debugger_global_level' , None) :
|
|
243
|
-
self.set_level( level=self.env.get('debugger_global_level') )
|
|
244
|
-
if not self.env.get('debugger_on_screen' , True ) :
|
|
245
|
-
self.disable_print()
|
|
246
|
-
if self.env.get('debugger_on_screen' , True ) :
|
|
247
|
-
self.enable_print()
|
|
248
|
-
if os.environ.get("EASY_UTILS_DEBUG_LEVEL") :
|
|
249
|
-
EASY_UTILS_DEBUG_LEVEL = os.environ.get("EASY_UTILS_DEBUG_LEVEL")
|
|
250
|
-
if not EASY_UTILS_DEBUG_LEVEL.lower() in ['info' , 'debug' , 'warning' , 'error' , 'critical'] :
|
|
251
|
-
self.logger.error(f'EASY_UTILS_DEBUG_LEVEL ENV must be one of [info,debug,warning,error,critical] | Current Env Variable Is "{EASY_UTILS_DEBUG_LEVEL}". Skipping ')
|
|
252
|
-
else :
|
|
253
|
-
self.set_level(EASY_UTILS_DEBUG_LEVEL)
|
|
254
|
-
self.updateGlobalHomePath()
|
|
255
|
-
if os.environ.get("EASY_UTILS_ENABLE_PRINT" , '' ).lower() == 'true' :
|
|
256
|
-
self.enable_print()
|
|
257
|
-
sleep(5)
|
|
258
|
-
|
|
259
|
-
def close(self) :
|
|
260
|
-
try :
|
|
261
|
-
logging.shutdown()
|
|
262
|
-
except :
|
|
263
|
-
pass
|
|
264
|
-
|
|
265
|
-
def homepath(self , path=None ) :
|
|
266
|
-
env = custom_env()
|
|
267
|
-
getFromEnv = env.get('debugger_homepath' , None )
|
|
268
|
-
if getFromEnv is not None :
|
|
269
|
-
self.homePath = getFromEnv
|
|
270
|
-
else :
|
|
271
|
-
if path is not None :
|
|
272
|
-
if self.homePath and '.log' in str(self.homePath):
|
|
273
|
-
self.lastAbsoluteHomePath= self.homePath
|
|
274
|
-
self.homePath = path
|
|
275
|
-
else :
|
|
276
|
-
self.homePath = os.path.join(os.getcwd() , 'debug')
|
|
277
|
-
if not os.path.exists( self.homePath ) :
|
|
278
|
-
try :
|
|
279
|
-
os.makedirs( self.homePath )
|
|
280
|
-
except :
|
|
281
|
-
pass
|
|
282
|
-
if self.filename :
|
|
283
|
-
self.homePath = os.path.join( self.homePath, f'{self.filename}.log' )
|
|
284
|
-
else :
|
|
285
|
-
self.homePath = os.path.join( self.homePath, f'{self.name}.log' )
|
|
286
|
-
return self.homePath
|
|
287
|
-
|
|
288
|
-
def get_current_levels(self):
|
|
289
|
-
"""
|
|
290
|
-
Returns a list of log levels that will be printed based on the current logging level.
|
|
291
|
-
"""
|
|
292
|
-
levels_order = [
|
|
293
|
-
('debug', logging.DEBUG),
|
|
294
|
-
('info', logging.INFO),
|
|
295
|
-
('warning', logging.WARNING),
|
|
296
|
-
('error', logging.ERROR),
|
|
297
|
-
('critical', logging.CRITICAL),
|
|
298
|
-
]
|
|
299
|
-
# Optional custom level
|
|
300
|
-
if hasattr(logging, 'SCREEN'):
|
|
301
|
-
levels_order.append(('screen', logging.SCREEN))
|
|
302
|
-
current_level = self.logger.level
|
|
303
|
-
# Return all levels with numeric value >= current_level
|
|
304
|
-
return [name for name, value in levels_order if value >= current_level]
|
|
305
|
-
|
|
306
|
-
def enable_print(self) :
|
|
307
|
-
self.onScreen = True
|
|
308
|
-
self.logger.addHandler(self.console)
|
|
309
|
-
|
|
310
|
-
def disable_print(self) :
|
|
311
|
-
self.onScreen = False
|
|
312
|
-
self.logger.removeHandler(self.console)
|
|
313
|
-
|
|
314
|
-
def changeHomePath( self , path ) :
|
|
315
|
-
p = self.homepath(path)
|
|
316
|
-
self.file_handler_class = self.createRotateFileHandler(p)
|
|
317
|
-
if self.lastAbsoluteHomePath :
|
|
318
|
-
os.remove(self.lastAbsoluteHomePath)
|
|
319
|
-
|
|
320
|
-
def isGlobalDebuggerDefined(self) :
|
|
321
|
-
if self.global_debugger :
|
|
322
|
-
return True
|
|
323
|
-
else :
|
|
324
|
-
return False
|
|
325
|
-
|
|
326
|
-
def set_level(self, level : str):
|
|
327
|
-
if 'info' in level.lower() : lvl = logging.INFO
|
|
328
|
-
elif 'warn' in level.lower() : lvl = logging.WARNING
|
|
329
|
-
elif 'warning' in level.lower() : lvl = logging.WARNING
|
|
330
|
-
elif 'critical' in level.lower() : lvl = logging.CRITICAL
|
|
331
|
-
elif 'debug' in level.lower() : lvl = logging.DEBUG
|
|
332
|
-
elif 'error' in level.lower() : lvl = logging.ERROR
|
|
333
|
-
elif 'screen' in level.lower() : lvl = logging.SCREEN
|
|
334
|
-
else : raise ValueError('Unknown level, not one of [info,warn,warning,critical,debug,error,screen]')
|
|
335
|
-
self.currentDebugLevel = level
|
|
336
|
-
self.logger.setLevel(lvl)
|
|
337
|
-
|
|
338
|
-
def get_current_debug_level(self) :
|
|
339
|
-
return self.currentDebugLevel
|
|
340
|
-
|
|
341
|
-
def get_logger(self) :
|
|
342
|
-
return self.logger
|
|
343
|
-
|
|
344
|
-
def before_log(self , message , level) :
|
|
345
|
-
|
|
346
|
-
def __call_thread__() :
|
|
347
|
-
if not level in self.get_current_levels() :
|
|
348
|
-
return
|
|
349
|
-
if self.isStreamServiceAvailable() :
|
|
350
|
-
d = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
|
|
351
|
-
streamUrl = self.getStreamServiceUrlPath()
|
|
352
|
-
self.stream_service.emit( streamUrl , {
|
|
353
|
-
'message' : message ,
|
|
354
|
-
'level' : level ,
|
|
355
|
-
'msg' : message,
|
|
356
|
-
'date' : d ,
|
|
357
|
-
'id' : self.id,
|
|
358
|
-
'formate' : 'json' ,
|
|
359
|
-
'source' : self.name ,
|
|
360
|
-
'getTimestamp' : getTimestamp()
|
|
361
|
-
})
|
|
362
|
-
try :
|
|
363
|
-
t= Thread(target=__call_thread__)
|
|
364
|
-
# t.daemon=True
|
|
365
|
-
t.start()
|
|
366
|
-
except :
|
|
367
|
-
__call_thread__()
|
|
368
|
-
|
|
369
|
-
params = {
|
|
370
|
-
'screen' : True ,
|
|
371
|
-
'file': True
|
|
372
|
-
}
|
|
373
|
-
if self.onScreen and self.env['debugger_on_screen'] == True :
|
|
374
|
-
params['screen'] = True
|
|
375
|
-
else :
|
|
376
|
-
params['screen'] = False
|
|
377
|
-
return params
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
def info(self, message , external_debugger=None,source=None):
|
|
381
|
-
def __call__(message) :
|
|
382
|
-
if source :
|
|
383
|
-
message = f'[{source}]-{message}'
|
|
384
|
-
self.before_log(message , 'info')
|
|
385
|
-
self.logger.info(message)
|
|
386
|
-
if self.isGlobalDebuggerDefined() :
|
|
387
|
-
self.global_debugger.info(message)
|
|
388
|
-
if external_debugger :
|
|
389
|
-
external_debugger.info(message)
|
|
390
|
-
try :
|
|
391
|
-
r=Thread(target=__call__,args=[message])
|
|
392
|
-
r.daemon=True
|
|
393
|
-
r.start()
|
|
394
|
-
r.join()
|
|
395
|
-
except :
|
|
396
|
-
__call__(message)
|
|
397
|
-
|
|
398
|
-
def debug(self, message , external_debugger=None,source=None):
|
|
399
|
-
def __call__(message) :
|
|
400
|
-
if source :
|
|
401
|
-
message = f'[{source}]-{message}'
|
|
402
|
-
self.before_log(message , 'debug')
|
|
403
|
-
self.logger.debug(message)
|
|
404
|
-
if self.isGlobalDebuggerDefined() :
|
|
405
|
-
self.global_debugger.debug(message)
|
|
406
|
-
if external_debugger :
|
|
407
|
-
external_debugger.debug(message)
|
|
408
|
-
try :
|
|
409
|
-
r=Thread(target=__call__,args=[message])
|
|
410
|
-
r.daemon=True
|
|
411
|
-
r.start()
|
|
412
|
-
r.join()
|
|
413
|
-
except :
|
|
414
|
-
__call__(message)
|
|
415
|
-
|
|
416
|
-
def warning(self, message , external_debugger=None,source=None):
|
|
417
|
-
def __call__(message) :
|
|
418
|
-
if source :
|
|
419
|
-
message = f'[{source}]-{message}'
|
|
420
|
-
self.before_log(message , 'warning')
|
|
421
|
-
self.logger.warning(message)
|
|
422
|
-
if self.isGlobalDebuggerDefined() :
|
|
423
|
-
self.global_debugger.warning(message)
|
|
424
|
-
if external_debugger :
|
|
425
|
-
external_debugger.warning(message)
|
|
426
|
-
try :
|
|
427
|
-
r=Thread(target=__call__,args=[message])
|
|
428
|
-
r.daemon=True
|
|
429
|
-
r.start()
|
|
430
|
-
r.join()
|
|
431
|
-
except :
|
|
432
|
-
__call__(message)
|
|
433
|
-
|
|
434
|
-
def error(self, message,external_debugger=None,source=None):
|
|
435
|
-
def __call__(message) :
|
|
436
|
-
if source :
|
|
437
|
-
message = f'[{source}]-{message}'
|
|
438
|
-
self.before_log(message , 'error')
|
|
439
|
-
self.logger.error(message)
|
|
440
|
-
if self.isGlobalDebuggerDefined() :
|
|
441
|
-
self.global_debugger.error(message)
|
|
442
|
-
if external_debugger :
|
|
443
|
-
external_debugger.error(message)
|
|
444
|
-
try :
|
|
445
|
-
r=Thread(target=__call__,args=[message])
|
|
446
|
-
r.daemon=True
|
|
447
|
-
r.start()
|
|
448
|
-
r.join()
|
|
449
|
-
except :
|
|
450
|
-
__call__(message)
|
|
451
|
-
|
|
452
|
-
def critical(self, message,external_debugger=None,source=None):
|
|
453
|
-
def __call__() :
|
|
454
|
-
if source :
|
|
455
|
-
message = f'[{source}]-{message}'
|
|
456
|
-
self.before_log(message , 'critical')
|
|
457
|
-
self.logger.critical(message)
|
|
458
|
-
if self.isGlobalDebuggerDefined() :
|
|
459
|
-
self.global_debugger.critical(message)
|
|
460
|
-
if external_debugger :
|
|
461
|
-
external_debugger.critical(message)
|
|
462
|
-
try :
|
|
463
|
-
r=Thread(target=__call__,args=[message])
|
|
464
|
-
r.daemon=True
|
|
465
|
-
r.start()
|
|
466
|
-
r.join()
|
|
467
|
-
except :
|
|
468
|
-
__call__(message)
|
|
469
|
-
|
|
470
|
-
def screen(self, message,external_debugger=None,source=None):
|
|
471
|
-
def __call__() :
|
|
472
|
-
if source :
|
|
473
|
-
message = f'[{source}]-{message}'
|
|
474
|
-
self.before_log(message , 'critical')
|
|
475
|
-
print(f"{self.syntax}")
|
|
476
|
-
if self.isGlobalDebuggerDefined() :
|
|
477
|
-
self.global_debugger.critical(message)
|
|
478
|
-
if external_debugger :
|
|
479
|
-
external_debugger.critical(message)
|
|
480
|
-
try :
|
|
481
|
-
r=Thread(target=__call__,args=[message])
|
|
482
|
-
r.daemon=True
|
|
483
|
-
r.start()
|
|
484
|
-
r.join()
|
|
485
|
-
except :
|
|
486
|
-
__call__(message)
|
|
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
|