brynq-sdk-task-scheduler 1.1.4__tar.gz → 1.2.0__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.
- {brynq_sdk_task_scheduler-1.1.4 → brynq_sdk_task_scheduler-1.2.0}/PKG-INFO +1 -1
- {brynq_sdk_task_scheduler-1.1.4 → brynq_sdk_task_scheduler-1.2.0}/brynq_sdk/task_scheduler/task_scheduler.py +57 -58
- {brynq_sdk_task_scheduler-1.1.4 → brynq_sdk_task_scheduler-1.2.0}/brynq_sdk_task_scheduler.egg-info/PKG-INFO +1 -1
- {brynq_sdk_task_scheduler-1.1.4 → brynq_sdk_task_scheduler-1.2.0}/setup.py +1 -1
- {brynq_sdk_task_scheduler-1.1.4 → brynq_sdk_task_scheduler-1.2.0}/brynq_sdk/task_scheduler/__init__.py +0 -0
- {brynq_sdk_task_scheduler-1.1.4 → brynq_sdk_task_scheduler-1.2.0}/brynq_sdk_task_scheduler.egg-info/SOURCES.txt +0 -0
- {brynq_sdk_task_scheduler-1.1.4 → brynq_sdk_task_scheduler-1.2.0}/brynq_sdk_task_scheduler.egg-info/dependency_links.txt +0 -0
- {brynq_sdk_task_scheduler-1.1.4 → brynq_sdk_task_scheduler-1.2.0}/brynq_sdk_task_scheduler.egg-info/not-zip-safe +0 -0
- {brynq_sdk_task_scheduler-1.1.4 → brynq_sdk_task_scheduler-1.2.0}/brynq_sdk_task_scheduler.egg-info/requires.txt +0 -0
- {brynq_sdk_task_scheduler-1.1.4 → brynq_sdk_task_scheduler-1.2.0}/brynq_sdk_task_scheduler.egg-info/top_level.txt +0 -0
- {brynq_sdk_task_scheduler-1.1.4 → brynq_sdk_task_scheduler-1.2.0}/setup.cfg +0 -0
|
@@ -32,6 +32,9 @@ class TaskScheduler(BrynQ):
|
|
|
32
32
|
self.es = Elastic()
|
|
33
33
|
self.mysql = MySQL()
|
|
34
34
|
self.email_after_errors = email_after_errors
|
|
35
|
+
self.customer_db = self.mysql.database
|
|
36
|
+
self.customer_id = self.mysql.raw_query(f'SELECT id FROM sc.customers WHERE dbname = \'{self.customer_db}\'')[0][0]
|
|
37
|
+
self.partner_id = os.getenv('PARTNER_ID').lower().replace(' ', '_') if os.getenv('PARTNER_ID') else 'brynq'
|
|
35
38
|
self.task_id = task_id
|
|
36
39
|
self.loglevel = loglevel
|
|
37
40
|
self.started_at = datetime.datetime.now()
|
|
@@ -42,7 +45,6 @@ class TaskScheduler(BrynQ):
|
|
|
42
45
|
# If the task is started locally, the parameters should be set locally
|
|
43
46
|
else:
|
|
44
47
|
self.started_local = True
|
|
45
|
-
self.customer_db = 'placeholder'
|
|
46
48
|
self.run_id = int(round(time.time() * 100000))
|
|
47
49
|
print(self.task_id, self.run_id)
|
|
48
50
|
self.error_count = 0
|
|
@@ -55,7 +57,9 @@ class TaskScheduler(BrynQ):
|
|
|
55
57
|
self.task_manual_started = self.check_if_task_manual_started()
|
|
56
58
|
|
|
57
59
|
# Creates Elasticsearch index and data view if not exists
|
|
58
|
-
self.
|
|
60
|
+
self.es_index = f"task_execution_log_{self.customer_db}_{self.started_at.strftime('%Y_%m')}"
|
|
61
|
+
self.es.create_index(index_name=self.es_index)
|
|
62
|
+
self.es.create_data_view(space_name='interfaces', view_name=f'task_execution_log_{self.customer_db}', name=f'Task execution log {self.customer_db}', time_field='started_at')
|
|
59
63
|
|
|
60
64
|
# Start the task and setup the data in the database
|
|
61
65
|
self.start_task()
|
|
@@ -71,6 +75,14 @@ class TaskScheduler(BrynQ):
|
|
|
71
75
|
key_count += self.__count_keys(value) # Recursively count keys in nested dictionaries
|
|
72
76
|
return key_count
|
|
73
77
|
|
|
78
|
+
def __get_caller_info(self):
|
|
79
|
+
stack = inspect.stack()
|
|
80
|
+
caller_frame = stack[2][0]
|
|
81
|
+
file_name = caller_frame.f_code.co_filename
|
|
82
|
+
line_number = caller_frame.f_lineno
|
|
83
|
+
function_name = stack[2][3]
|
|
84
|
+
return file_name, line_number, function_name
|
|
85
|
+
|
|
74
86
|
def create_task_execution_steps(self, step_details: list):
|
|
75
87
|
"""
|
|
76
88
|
Check if the given steps already exists in the task_execution_steps table. If not, update or insert the values in the table
|
|
@@ -158,7 +170,8 @@ class TaskScheduler(BrynQ):
|
|
|
158
170
|
if loglevel not in allowed_loglevels:
|
|
159
171
|
raise Exception('You\'ve entered a not allowed loglevel. Choose one of: {}'.format(allowed_loglevels))
|
|
160
172
|
|
|
161
|
-
# Handling different data types and preparing extra payload information based on the data type
|
|
173
|
+
# For Elastic, we need to have the data in JSON format. Handling different data types and preparing extra payload information based on the data type
|
|
174
|
+
# If the data is just a series, count rows, columns and cells
|
|
162
175
|
if isinstance(data, pd.Series):
|
|
163
176
|
dataframe = pd.DataFrame(data).T
|
|
164
177
|
extra_payload = {
|
|
@@ -168,6 +181,7 @@ class TaskScheduler(BrynQ):
|
|
|
168
181
|
}
|
|
169
182
|
if not full_extract:
|
|
170
183
|
extra_payload['payload'] = dataframe.to_json(orient='records')
|
|
184
|
+
# If the data is a list, count rows, columns and cells
|
|
171
185
|
elif isinstance(data, dict):
|
|
172
186
|
records = self.__count_keys(data)
|
|
173
187
|
extra_payload = {
|
|
@@ -185,6 +199,7 @@ class TaskScheduler(BrynQ):
|
|
|
185
199
|
}
|
|
186
200
|
if not full_extract:
|
|
187
201
|
extra_payload['payload'] = data.to_json(orient='records')
|
|
202
|
+
# If the data is a response from an URL request, also store all the information about the URL request.
|
|
188
203
|
elif isinstance(data, requests.Response):
|
|
189
204
|
records = 1
|
|
190
205
|
if data.request.body is not None:
|
|
@@ -217,41 +232,37 @@ class TaskScheduler(BrynQ):
|
|
|
217
232
|
elif data is not None and full_extract is False:
|
|
218
233
|
extra_payload['full_load'] = False
|
|
219
234
|
|
|
220
|
-
#
|
|
235
|
+
# Get the linenumber from where the logline is executed.
|
|
236
|
+
file_name, line_number, function_name = self.__get_caller_info()
|
|
237
|
+
|
|
238
|
+
# Put everything together in the payload for ElasticSearch and send it
|
|
221
239
|
payload = {
|
|
222
|
-
'reload_id': self.run_id,
|
|
223
240
|
'task_id': self.task_id,
|
|
224
|
-
'
|
|
241
|
+
'reload_id': self.run_id,
|
|
225
242
|
'started_at': datetime.datetime.now().isoformat(),
|
|
226
|
-
'
|
|
243
|
+
'partner_id': self.partner_id,
|
|
244
|
+
'customer_id': self.customer_id,
|
|
245
|
+
'customer': os.getenv('BRYNQ_CUSTOMER_NAME').lower().replace(' ', '_'),
|
|
246
|
+
'file_name': file_name,
|
|
247
|
+
'function_name': function_name,
|
|
248
|
+
'line_number': line_number,
|
|
249
|
+
'task_loglevel': self.loglevel,
|
|
250
|
+
'line_loglevel': loglevel,
|
|
227
251
|
'message': message
|
|
228
252
|
}
|
|
229
253
|
payload.update(extra_payload)
|
|
254
|
+
self.es.post_document(index_name=self.es_index, document=payload)
|
|
230
255
|
|
|
231
|
-
#
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
# Get the linenumber from where the logline is executed. Get the stacktrace of this action, jump 1 file up and pick then the linenumber (second item)
|
|
235
|
-
linenumber = inspect.getouterframes(inspect.currentframe())[1][2]
|
|
236
|
-
# Write the logline to the database, depends on the chosen loglevel in the task
|
|
237
|
-
print('{} at line: {}'.format(message, linenumber))
|
|
256
|
+
# Write the logline to the MYSQL database, depends on the chosen loglevel in the task
|
|
257
|
+
print('{} at line: {}'.format(message, line_number))
|
|
238
258
|
# Remove quotes from message since these break the query
|
|
239
259
|
message = re.sub("[']", '', message)
|
|
240
|
-
timestamp = time.strftime("%Y-%m-%d %H:%M:%S")
|
|
241
|
-
information = {
|
|
242
|
-
'reload_id': self.run_id,
|
|
243
|
-
'task_id': self.task_id,
|
|
244
|
-
'log_level': loglevel,
|
|
245
|
-
'line_number': linenumber,
|
|
246
|
-
'message': message,
|
|
247
|
-
'created_at': timestamp
|
|
248
|
-
}
|
|
249
260
|
if self.loglevel == 'DEBUG':
|
|
250
261
|
# Count the errors
|
|
251
262
|
if loglevel == 'ERROR' or loglevel == 'CRITICAL':
|
|
252
263
|
self.error_count += 1
|
|
253
264
|
return self.mysql.raw_query(
|
|
254
|
-
"INSERT INTO `task_execution_log` (reload_id, task_id, log_level, created_at, line_number, message) VALUES ({}, {}, '{}', '{}', {}, '{}')".format(self.run_id, self.task_id, loglevel, datetime.datetime.now(),
|
|
265
|
+
"INSERT INTO `task_execution_log` (reload_id, task_id, log_level, created_at, line_number, message) VALUES ({}, {}, '{}', '{}', {}, '{}')".format(self.run_id, self.task_id, loglevel, datetime.datetime.now(), line_number, message), insert=True)
|
|
255
266
|
return self.mysql.update(table='task_execution_log',
|
|
256
267
|
columns=['reload_id', 'task_id', 'log_level', 'created_at', 'line_number', 'message'],
|
|
257
268
|
values=[self.run_id, self.task_id, loglevel, datetime.datetime.now(), linenumber, message])
|
|
@@ -260,15 +271,15 @@ class TaskScheduler(BrynQ):
|
|
|
260
271
|
if loglevel == 'ERROR' or loglevel == 'CRITICAL':
|
|
261
272
|
self.error_count += 1
|
|
262
273
|
return self.mysql.raw_query(
|
|
263
|
-
"INSERT INTO `task_execution_log` (reload_id, task_id, log_level, created_at, line_number, message) VALUES ({}, {}, '{}', '{}', {}, '{}')".format(self.run_id, self.task_id, loglevel, datetime.datetime.now(),
|
|
274
|
+
"INSERT INTO `task_execution_log` (reload_id, task_id, log_level, created_at, line_number, message) VALUES ({}, {}, '{}', '{}', {}, '{}')".format(self.run_id, self.task_id, loglevel, datetime.datetime.now(), line_number, message), insert=True)
|
|
264
275
|
elif self.loglevel == 'ERROR' and (loglevel == 'ERROR' or loglevel == 'CRITICAL'):
|
|
265
276
|
self.error_count += 1
|
|
266
277
|
return self.mysql.raw_query(
|
|
267
|
-
"INSERT INTO `task_execution_log` (reload_id, task_id, log_level, created_at, line_number, message) VALUES ({}, {}, '{}', '{}', {}, '{}')".format(self.run_id, self.task_id, loglevel, datetime.datetime.now(),
|
|
278
|
+
"INSERT INTO `task_execution_log` (reload_id, task_id, log_level, created_at, line_number, message) VALUES ({}, {}, '{}', '{}', {}, '{}')".format(self.run_id, self.task_id, loglevel, datetime.datetime.now(), line_number, message), insert=True)
|
|
268
279
|
elif self.loglevel == 'CRITICAL' and loglevel == 'CRITICAL':
|
|
269
280
|
self.error_count += 1
|
|
270
281
|
return self.mysql.raw_query(
|
|
271
|
-
"INSERT INTO `task_execution_log` (reload_id, task_id, log_level, created_at, line_number, message) VALUES ({}, {}, '{}', '{}', {}, '{}')".format(self.run_id, self.task_id, loglevel, datetime.datetime.now(),
|
|
282
|
+
"INSERT INTO `task_execution_log` (reload_id, task_id, log_level, created_at, line_number, message) VALUES ({}, {}, '{}', '{}', {}, '{}')".format(self.run_id, self.task_id, loglevel, datetime.datetime.now(), line_number, message), insert=True)
|
|
272
283
|
|
|
273
284
|
def update_execution_step(self, step_number: int):
|
|
274
285
|
"""
|
|
@@ -290,24 +301,32 @@ class TaskScheduler(BrynQ):
|
|
|
290
301
|
:param started_at: Give the time the task is started
|
|
291
302
|
:return: nothing
|
|
292
303
|
"""
|
|
304
|
+
# Format error to a somewhat readable format
|
|
305
|
+
exc_type, exc_obj, exc_tb = sys.exc_info()
|
|
306
|
+
error = str(e)[:400].replace('\'', '').replace('\"', '') + ' | Line: {}'.format(exc_tb.tb_lineno)
|
|
307
|
+
|
|
308
|
+
# Get the linenumber from where the logline is executed.
|
|
309
|
+
file_name, line_number, function_name = self.__get_caller_info()
|
|
293
310
|
|
|
294
|
-
# Preparing the primary payload with error details for upload to elastic
|
|
311
|
+
# Preparing the primary payload with error details for upload to elastic and send it
|
|
295
312
|
payload = {
|
|
296
|
-
'reload_id': self.run_id,
|
|
297
313
|
'task_id': self.task_id,
|
|
298
|
-
'
|
|
314
|
+
'reload_id': self.run_id,
|
|
299
315
|
'started_at': datetime.datetime.now().isoformat(),
|
|
300
|
-
'
|
|
316
|
+
'partner_id': self.partner_id,
|
|
317
|
+
'customer_id': self.customer_id,
|
|
318
|
+
'customer': os.getenv('BRYNQ_CUSTOMER_NAME').lower().replace(' ', '_'),
|
|
319
|
+
'file_name': file_name,
|
|
320
|
+
'function_name': function_name,
|
|
321
|
+
'line_number': line_number,
|
|
322
|
+
'task_loglevel': self.loglevel,
|
|
323
|
+
'line_loglevel': 'CRITICAL',
|
|
301
324
|
'message': str(e),
|
|
302
325
|
'traceback': traceback.format_exc()
|
|
303
326
|
}
|
|
327
|
+
self.es.post_document(index_name=self.es_index, document=payload)
|
|
304
328
|
|
|
305
|
-
# Sending the payload to ElasticSearch
|
|
306
|
-
self.es.task_execution_log(payload)
|
|
307
329
|
|
|
308
|
-
# Format error to a somewhat readable format
|
|
309
|
-
exc_type, exc_obj, exc_tb = sys.exc_info()
|
|
310
|
-
error = str(e)[:400].replace('\'', '').replace('\"', '') + ' | Line: {}'.format(exc_tb.tb_lineno)
|
|
311
330
|
# Get scheduler task details for logging
|
|
312
331
|
task_details = \
|
|
313
332
|
self.mysql.select('task_scheduler, data_interfaces', 'data_interfaces.docker_image, data_interfaces.runfile_path', 'WHERE task_scheduler.data_interface_id = data_interfaces.id AND task_scheduler.id = {}'.format(self.task_id))[0]
|
|
@@ -320,15 +339,6 @@ class TaskScheduler(BrynQ):
|
|
|
320
339
|
['IDLE', datetime.datetime.now(), 'Failed', 0],
|
|
321
340
|
'WHERE `id` = {}'.format(self.task_id))
|
|
322
341
|
# Log to database
|
|
323
|
-
timestamp = time.strftime("%Y-%m-%d %H:%M:%S")
|
|
324
|
-
information = {
|
|
325
|
-
'reload_id': self.run_id,
|
|
326
|
-
'task_id': self.task_id,
|
|
327
|
-
'log_level': 'CRITICAL',
|
|
328
|
-
'line_number': exc_tb.tb_lineno,
|
|
329
|
-
'message': error,
|
|
330
|
-
'created_at': timestamp
|
|
331
|
-
}
|
|
332
342
|
self.mysql.raw_query(
|
|
333
343
|
"INSERT INTO `task_execution_log` (reload_id, task_id, log_level, created_at, line_number, message) VALUES ({}, {}, 'CRITICAL', '{}', {}, '{}')".format(self.run_id,
|
|
334
344
|
self.task_id,
|
|
@@ -353,15 +363,6 @@ class TaskScheduler(BrynQ):
|
|
|
353
363
|
|
|
354
364
|
raise Exception(error)
|
|
355
365
|
else:
|
|
356
|
-
timestamp = time.strftime("%Y-%m-%d %H:%M:%S")
|
|
357
|
-
information = {
|
|
358
|
-
'reload_id': self.run_id,
|
|
359
|
-
'task_id': self.task_id,
|
|
360
|
-
'log_level': 'CRITICAL',
|
|
361
|
-
'line_number': exc_tb.tb_lineno,
|
|
362
|
-
'message': error,
|
|
363
|
-
'created_at': timestamp
|
|
364
|
-
}
|
|
365
366
|
self.mysql.raw_query(
|
|
366
367
|
"INSERT INTO `task_execution_log` (reload_id, task_id, log_level, created_at, line_number, message) VALUES ({}, {}, 'CRITICAL', '{}', {}, '{}')".format(self.run_id,
|
|
367
368
|
self.task_id,
|
|
@@ -442,11 +443,9 @@ class TaskScheduler(BrynQ):
|
|
|
442
443
|
for i in email_to:
|
|
443
444
|
email_list.append({'name': 'BrynQ User', 'mail': i.strip()})
|
|
444
445
|
# Set the content of the mail and all other stuff
|
|
445
|
-
task = self.mysql.select(table='
|
|
446
|
-
0]
|
|
446
|
+
task = self.mysql.select(table='data_interfaces', selection='title', filter=f'WHERE id = {self.task_id}')[0][0]
|
|
447
447
|
finished_at = \
|
|
448
|
-
self.mysql.select(table='task_scheduler', selection='last_reload', filter=f'WHERE
|
|
449
|
-
0]
|
|
448
|
+
self.mysql.select(table='task_scheduler', selection='last_reload', filter=f'WHERE data_interface_id = {self.task_id}')[0][0]
|
|
450
449
|
if failed:
|
|
451
450
|
subject = f'Task \'{task}\' has failed'
|
|
452
451
|
content = f'Task \'{task}\' with task ID \'{self.task_id}\' failed during its last run and was stopped at {finished_at}. ' \
|
|
@@ -3,7 +3,7 @@ from setuptools import setup
|
|
|
3
3
|
|
|
4
4
|
setup(
|
|
5
5
|
name='brynq_sdk_task_scheduler',
|
|
6
|
-
version='1.
|
|
6
|
+
version='1.2.0',
|
|
7
7
|
description='Code to execute tasks in BrynQ.com with the task scheduler',
|
|
8
8
|
long_description='Code to execute tasks in the BrynQ.com platform with the task scheduler',
|
|
9
9
|
author='BrynQ',
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|