berryworld 1.0.0.197723__py3-none-any.whl → 1.0.0.199021__py3-none-any.whl

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.
berryworld/__init__.py CHANGED
@@ -4,6 +4,7 @@ from .transportation_solver import TransportationAlgorithm
4
4
  from .allocation_solver import AllocationSolver
5
5
  from .pickle_management import PickleManagement
6
6
  from .email_logging import EmailLogging
7
+ from .python_logs import ErrorLogs
7
8
  from .verify_keys import Verify
8
9
  from .credentials import SnowflakeCredentials, SQLCredentials, WebServiceCredentials, MicrosoftTeamsCredentials
9
10
  from .persistent_storage import PersistentStorage
berryworld/logging.py CHANGED
@@ -1,6 +1,3 @@
1
-
2
-
3
-
4
1
  class PythonLogs:
5
2
  """ Register the Python Logs """
6
3
  def __init__(self, conn, batch_process):
@@ -0,0 +1,112 @@
1
+ import time
2
+ import math
3
+ import datetime
4
+ from uuid import uuid4
5
+ import pandas as pd
6
+ from threading import Thread
7
+
8
+
9
+ class ErrorLogs:
10
+ """ Register Python Error Logs """
11
+
12
+ def __init__(self, project_name, pipeline, ip_address, request_url, sql_con, timeout=30*60, print_sql=False):
13
+ """ Initialize the class
14
+ :param project_name: Name of the project being run. it must be already declared in PythonEmailProjectSeverity
15
+ :param pipeline: Pipeline name being run. It must identify the process being executed uniquely
16
+ :param ip_address: IP Address
17
+ :param request_url: URL requested by the client
18
+ :param sql_con: Connection to the Database to upload the Logs
19
+ :param timeout: Time in seconds after which an unsuccessful log will be sent
20
+ :param print_sql: Print the SQL statement sent to the server
21
+ """
22
+ self.log_df = pd.DataFrame({'ProjectName': [project_name], 'Successful': [0], 'Sent': [0],
23
+ 'IPAddress': [str(ip_address).replace("'", '"')],
24
+ 'RequestUrl': [str(request_url).replace("'", '"')],
25
+ 'StartedDate': [datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f")]})
26
+ self.sql_con = sql_con
27
+ self.timeout = timeout
28
+ self.print_sql = print_sql
29
+ self.guid = str(uuid4())
30
+ self.pipeline = pipeline
31
+ self.failure_type = []
32
+ Thread(target=self.start_threading).start()
33
+
34
+ def start_threading(self):
35
+ """ Start a threading to update on failure if the script breaks or the pipeline gets blocked
36
+ """
37
+ time_range = math.ceil(self.timeout / 10)
38
+ for times in range(time_range):
39
+ time.sleep(10)
40
+ if len(self.failure_type) > 0:
41
+ break
42
+
43
+ if len(self.failure_type) == 0:
44
+ elapsed_time = str(datetime.timedelta(seconds=round(self.timeout)))[2:]
45
+ self.on_failure(error_message=f'The pipeline failed to succeed after running '
46
+ f'for {elapsed_time} minutes')
47
+
48
+ def on_success(self, pipeline=None):
49
+ """ Update log on success
50
+ :param pipeline: Pipeline name being run. It must identify the process being executed uniquely
51
+ """
52
+ if not any(self.failure_type):
53
+ if pipeline is not None:
54
+ self.pipeline = pipeline
55
+ successful_columns = {'Successful': 1, 'Resolved': 1, 'Pipeline': self.pipeline, 'GuidKey': self.guid,
56
+ 'FinishedDate': datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f")}
57
+ self.log_df = self.log_df.assign(**successful_columns)
58
+ self.sql_con.insert(self.log_df, 'Staging', 'Logs', print_sql=self.print_sql)
59
+ self.failure_type.append(True)
60
+
61
+ Thread(target=self.trigger_merge_stored_procedure).start()
62
+
63
+ def on_failure(self, error_message, pipeline=None, section=None, critical=True, proposed_solution=None):
64
+ """ Update log on failure
65
+ :param error_message: Error message to be sent in the Log
66
+ :param pipeline: Pipeline name being run. It must identify the process being executed uniquely
67
+ :param section: Indicate the script section. Useful to locate the error
68
+ :param critical: Indicate whether it should avoid sending successful logs
69
+ :param proposed_solution: Proposed solution to the error message
70
+ """
71
+ save_failure = True
72
+ if section is not None:
73
+ if ((('prod' not in str(self.sql_con.server)) | ('prd' not in str(self.sql_con.server)))
74
+ & (('connection' in str(section).lower()) & ('dw' in str(section).lower()))):
75
+ print('Avoiding to report a connection DW error in a non-production environment')
76
+ save_failure = False
77
+
78
+ if save_failure:
79
+ if pipeline is not None:
80
+ self.pipeline = pipeline
81
+ unsuccessful_columns = {'Successful': 0, 'Section': section, 'Pipeline': self.pipeline,
82
+ 'GuidKey': self.guid, 'Critical': 1 if critical is True else 0,
83
+ 'FinishedDate': datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f"),
84
+ 'ErrorMessage': str(error_message).replace("'", '"')}
85
+ self.log_df = self.log_df.assign(**unsuccessful_columns)
86
+ if proposed_solution is not None:
87
+ self.log_df = self.log_df.assign(**{'ProposedSolution': proposed_solution})
88
+ self.sql_con.insert(self.log_df, 'Staging', 'Logs', print_sql=self.print_sql)
89
+ self.failure_type.append(critical)
90
+
91
+ Thread(target=self.trigger_merge_stored_procedure).start()
92
+
93
+ def trigger_merge_stored_procedure(self):
94
+ """ Trigger the merge stored procedure to aggregate logs
95
+ """
96
+ stored_procedure = 'Logging.spLogsMerge'
97
+ self.sql_con.run_statement(f"EXEC {stored_procedure}")
98
+
99
+ @staticmethod
100
+ def register_failure(email_log, section, error_, solutions=None):
101
+ """Register a failure in the email log
102
+ :param email_log: Instance of PythonEmailProjectSeverity
103
+ :param section: Indicate the script section. Useful to locate the error
104
+ :param error_: Error message to be sent in the Log
105
+ :param solutions: List of solutions for the error messages
106
+ """
107
+ solution_header = list(filter(lambda x: section.startswith(x), list(solutions.keys())))
108
+ if len(solution_header) > 0:
109
+ proposed_solution = solutions[solution_header[0]]
110
+ email_log.on_failure(error_, section=section, proposed_solution=proposed_solution)
111
+ else:
112
+ email_log.on_failure(error_, section=section)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: berryworld
3
- Version: 1.0.0.197723
3
+ Version: 1.0.0.199021
4
4
  Summary: Handy classes to improve ETL processes
5
5
  Home-page: https://www.berryworld.com
6
6
  Author: BerryWorld ltd
@@ -1,4 +1,4 @@
1
- berryworld/__init__.py,sha256=dDnmPuE2CZfPzh08BfjJjmyeM0mjs5mIP0OS7RujDco,1140
1
+ berryworld/__init__.py,sha256=xYQwJeCZ2di85E0_O3Sx8AUsRhoT6USUxcPGJyCr-gY,1175
2
2
  berryworld/aks_logs.py,sha256=Gb2_cokiZbEX01Yoptd0MxpDociaug-GrXdwliyxFBo,2293
3
3
  berryworld/allocation_solver.py,sha256=asFtaCAze6-eHUGWXA0kAp67UBS-Upj1KKdrVLj_ttQ,8513
4
4
  berryworld/app_logs.py,sha256=MKzKPYd3JuPfOQNAapIgaeZeFHw1z_w2mbn9I6QCADE,4180
@@ -10,12 +10,13 @@ berryworld/email_con.py,sha256=CVyEDVnc_iVeRTwJgIU31ToFgyix7L2yn4Ih9Wu7I5s,15806
10
10
  berryworld/email_logging.py,sha256=LeSrTExhQhar49gJR2wGC1dS0lqsNpFl9pS3eYWqnuo,4936
11
11
  berryworld/generate_env.py,sha256=LrqUH8AjCI6P0uU6BMBRYC9cnmyKkYcpXF1KKIzxkZ8,15900
12
12
  berryworld/handy_mix.py,sha256=SqJ3UjIjmIOgjbp-_1eyKQJ3OJLN7OfpDQIASvjNZ_Q,9672
13
- berryworld/logging.py,sha256=tOxzaFALQm3aVVEc3I7t8MU6PwgUI9VSnzNCH9yRryo,1013
13
+ berryworld/logging.py,sha256=mFFueg1OKudoYFDVJIzCYNY7lRipoefllJiHzytkmzk,1010
14
14
  berryworld/logic_apps.py,sha256=a0uU4tNO3v2w7grdBv-OOx4hUf7VBIerJpwZ9U-29dQ,14591
15
15
  berryworld/microsoft_teams.py,sha256=8uPo0yku-euBj2VdzBoZCeX3IcsCCOqISLqaVZUVxfA,16030
16
16
  berryworld/persistent_storage.py,sha256=L15kLyzN42T6UB1WAg8rFXJq3Mdb1M8Sw4P5YQaUN84,8711
17
17
  berryworld/pickle_management.py,sha256=5o6UuXBpTj23Jgpz6sj9V-vdcdWBK1xMEckWxT-Whj4,2436
18
18
  berryworld/power_automate.py,sha256=V86QEGG9H36DrDvod9Q6yp8OUu307hfYcXJhw06pYrA,27912
19
+ berryworld/python_logs.py,sha256=SEWrzK5kpG6kd_7qjGXd-d5SiVgEm595Tuud14uGGzw,5810
19
20
  berryworld/sharepoint_con.py,sha256=nmyZJIcaAKJ6Y-ti4gQbvzA_rRbrMGIxTDXe4eP-tiI,44950
20
21
  berryworld/snowflake_conn.py,sha256=L0ePgTKa3tvaxj88BZmsjS6cFp3ZU3rytw7S2jkuA-U,3161
21
22
  berryworld/sql_conn.py,sha256=6kUR3oLXweakz2IBc4zI1ZMqRoN8K6nbQneHhenM-7I,47668
@@ -26,12 +27,12 @@ berryworld/verify_keys.py,sha256=X7VUHqYDklWPDO0bGVHIOXeLq5Qi4fZRZbHYw5x7UnA,435
26
27
  berryworld/vivantio.py,sha256=QfZo0UKqkzVRg_LyiwivNd3aEup4TH57x4KxLZkCJwc,10627
27
28
  berryworld/vivantio_logging.py,sha256=ciy7gA4u3FrgUIpEBnMgocbNPp6jcu9TPoy-kLcrTZU,5736
28
29
  berryworld/xml_parser.py,sha256=HWD71NaTN3DaIOGT6Wzxs4CEsroFhGQwe9iPLIL80Co,957
29
- berryworld-1.0.0.197723.dist-info/licenses/LICENSE,sha256=vtkVCJM6E2af2gnsi2XxKPr4WY-uIbvzVLXieFND0UU,1074
30
+ berryworld-1.0.0.199021.dist-info/licenses/LICENSE,sha256=vtkVCJM6E2af2gnsi2XxKPr4WY-uIbvzVLXieFND0UU,1074
30
31
  tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
31
32
  tests/test_allocation_config.py,sha256=e12l6fE9U57eSPS35g6ekJ_hol7-RHg89JV60_m1BlE,4633
32
33
  tests/test_handy_mix_config.py,sha256=Un56mz9KJmdn4K4OwzHAHLSRzDU1Xv2nFrONNuzOG04,2594
33
34
  tests/test_xml_parser.py,sha256=3QTlhFEd6KbK6nRFKZnc35tad6wqukTbe4QrFi8mr_8,859
34
- berryworld-1.0.0.197723.dist-info/METADATA,sha256=Btf-waInlfkM3ovW6JgnQaM2Nytj0gy0xbMDY_ppEG8,1445
35
- berryworld-1.0.0.197723.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
36
- berryworld-1.0.0.197723.dist-info/top_level.txt,sha256=GIZ5qy-P5oxfEH755vA1IMFeTVdX3-40JxMe6nOe5I8,17
37
- berryworld-1.0.0.197723.dist-info/RECORD,,
35
+ berryworld-1.0.0.199021.dist-info/METADATA,sha256=RVDaYgMC_ojVtgoJQL2uXuIA8TsqPxLwPpgntPyeFQM,1445
36
+ berryworld-1.0.0.199021.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
37
+ berryworld-1.0.0.199021.dist-info/top_level.txt,sha256=GIZ5qy-P5oxfEH755vA1IMFeTVdX3-40JxMe6nOe5I8,17
38
+ berryworld-1.0.0.199021.dist-info/RECORD,,