ipulse-shared-core-ftredge 2.54__tar.gz → 2.55__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of ipulse-shared-core-ftredge might be problematic. Click here for more details.
- {ipulse_shared_core_ftredge-2.54/src/ipulse_shared_core_ftredge.egg-info → ipulse_shared_core_ftredge-2.55}/PKG-INFO +1 -1
- {ipulse_shared_core_ftredge-2.54 → ipulse_shared_core_ftredge-2.55}/setup.py +1 -1
- {ipulse_shared_core_ftredge-2.54 → ipulse_shared_core_ftredge-2.55}/src/ipulse_shared_core_ftredge/__init__.py +1 -1
- {ipulse_shared_core_ftredge-2.54 → ipulse_shared_core_ftredge-2.55}/src/ipulse_shared_core_ftredge/utils_common.py +111 -25
- {ipulse_shared_core_ftredge-2.54 → ipulse_shared_core_ftredge-2.55/src/ipulse_shared_core_ftredge.egg-info}/PKG-INFO +1 -1
- {ipulse_shared_core_ftredge-2.54 → ipulse_shared_core_ftredge-2.55}/LICENCE +0 -0
- {ipulse_shared_core_ftredge-2.54 → ipulse_shared_core_ftredge-2.55}/README.md +0 -0
- {ipulse_shared_core_ftredge-2.54 → ipulse_shared_core_ftredge-2.55}/pyproject.toml +0 -0
- {ipulse_shared_core_ftredge-2.54 → ipulse_shared_core_ftredge-2.55}/setup.cfg +0 -0
- {ipulse_shared_core_ftredge-2.54 → ipulse_shared_core_ftredge-2.55}/src/ipulse_shared_core_ftredge/enums/__init__.py +0 -0
- {ipulse_shared_core_ftredge-2.54 → ipulse_shared_core_ftredge-2.55}/src/ipulse_shared_core_ftredge/enums/enums_common_utils.py +0 -0
- {ipulse_shared_core_ftredge-2.54 → ipulse_shared_core_ftredge-2.55}/src/ipulse_shared_core_ftredge/enums/enums_data_eng.py +0 -0
- {ipulse_shared_core_ftredge-2.54 → ipulse_shared_core_ftredge-2.55}/src/ipulse_shared_core_ftredge/enums/enums_module_fincore.py +0 -0
- {ipulse_shared_core_ftredge-2.54 → ipulse_shared_core_ftredge-2.55}/src/ipulse_shared_core_ftredge/enums/enums_modules.py +0 -0
- {ipulse_shared_core_ftredge-2.54 → ipulse_shared_core_ftredge-2.55}/src/ipulse_shared_core_ftredge/models/__init__.py +0 -0
- {ipulse_shared_core_ftredge-2.54 → ipulse_shared_core_ftredge-2.55}/src/ipulse_shared_core_ftredge/models/audit_log_firestore.py +0 -0
- {ipulse_shared_core_ftredge-2.54 → ipulse_shared_core_ftredge-2.55}/src/ipulse_shared_core_ftredge/models/organisation.py +0 -0
- {ipulse_shared_core_ftredge-2.54 → ipulse_shared_core_ftredge-2.55}/src/ipulse_shared_core_ftredge/models/pulse_enums.py +0 -0
- {ipulse_shared_core_ftredge-2.54 → ipulse_shared_core_ftredge-2.55}/src/ipulse_shared_core_ftredge/models/resource_catalog_item.py +0 -0
- {ipulse_shared_core_ftredge-2.54 → ipulse_shared_core_ftredge-2.55}/src/ipulse_shared_core_ftredge/models/user_auth.py +0 -0
- {ipulse_shared_core_ftredge-2.54 → ipulse_shared_core_ftredge-2.55}/src/ipulse_shared_core_ftredge/models/user_profile.py +0 -0
- {ipulse_shared_core_ftredge-2.54 → ipulse_shared_core_ftredge-2.55}/src/ipulse_shared_core_ftredge/models/user_profile_update.py +0 -0
- {ipulse_shared_core_ftredge-2.54 → ipulse_shared_core_ftredge-2.55}/src/ipulse_shared_core_ftredge/models/user_status.py +0 -0
- {ipulse_shared_core_ftredge-2.54 → ipulse_shared_core_ftredge-2.55}/src/ipulse_shared_core_ftredge/tests/__init__.py +0 -0
- {ipulse_shared_core_ftredge-2.54 → ipulse_shared_core_ftredge-2.55}/src/ipulse_shared_core_ftredge/tests/test.py +0 -0
- {ipulse_shared_core_ftredge-2.54 → ipulse_shared_core_ftredge-2.55}/src/ipulse_shared_core_ftredge/utils_gcp.py +0 -0
- {ipulse_shared_core_ftredge-2.54 → ipulse_shared_core_ftredge-2.55}/src/ipulse_shared_core_ftredge/utils_templates_and_schemas.py +0 -0
- {ipulse_shared_core_ftredge-2.54 → ipulse_shared_core_ftredge-2.55}/src/ipulse_shared_core_ftredge.egg-info/SOURCES.txt +0 -0
- {ipulse_shared_core_ftredge-2.54 → ipulse_shared_core_ftredge-2.55}/src/ipulse_shared_core_ftredge.egg-info/dependency_links.txt +0 -0
- {ipulse_shared_core_ftredge-2.54 → ipulse_shared_core_ftredge-2.55}/src/ipulse_shared_core_ftredge.egg-info/requires.txt +0 -0
- {ipulse_shared_core_ftredge-2.54 → ipulse_shared_core_ftredge-2.55}/src/ipulse_shared_core_ftredge.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: ipulse_shared_core_ftredge
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.55
|
|
4
4
|
Summary: Shared Core models and Logger util for the Pulse platform project. Using AI for financial advisory and investment management.
|
|
5
5
|
Home-page: https://github.com/TheFutureEdge/ipulse_shared_core
|
|
6
6
|
Author: Russlan Ramdowar
|
|
@@ -3,7 +3,7 @@ from setuptools import setup, find_packages
|
|
|
3
3
|
|
|
4
4
|
setup(
|
|
5
5
|
name='ipulse_shared_core_ftredge',
|
|
6
|
-
version='2.
|
|
6
|
+
version='2.55',
|
|
7
7
|
package_dir={'': 'src'}, # Specify the source directory
|
|
8
8
|
packages=find_packages(where='src'), # Look for packages in 'src'
|
|
9
9
|
install_requires=[
|
|
@@ -5,7 +5,7 @@ from .utils_gcp import (setup_gcp_logger_and_error_report,
|
|
|
5
5
|
write_csv_to_gcs, write_json_to_gcs)
|
|
6
6
|
from .utils_templates_and_schemas import (create_bigquery_schema_from_json,
|
|
7
7
|
check_format_against_schema_template)
|
|
8
|
-
from .utils_common import (ContextLog,
|
|
8
|
+
from .utils_common import (ContextLog, Pipelinemon)
|
|
9
9
|
|
|
10
10
|
from .enums import (TargetLogs, LogLevel, Unit, Frequency,
|
|
11
11
|
Module, SubModule, BaseDataCategory,
|
|
@@ -17,11 +17,12 @@ from ipulse_shared_core_ftredge.utils_gcp import write_json_to_gcs
|
|
|
17
17
|
# ["data_import","data_quality", "data_processing","data_general","data_persistance","metadata_quality", "metadata_processing", "metadata_persistance","metadata_general"]
|
|
18
18
|
|
|
19
19
|
class ContextLog:
|
|
20
|
-
MAX_TRACEBACK_LINES =
|
|
20
|
+
MAX_TRACEBACK_LINES = 24 # Define the maximum number of traceback lines to include
|
|
21
21
|
def __init__(self, level: LogLevel, base_context: str = None, collector_id: str = None,
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
context: str = None, description: str = None,
|
|
23
|
+
e: Exception = None, e_type: str = None, e_message: str = None, e_traceback: str = None,
|
|
24
|
+
log_status: LogStatus = LogStatus.OPEN, subject: str = None
|
|
25
|
+
):
|
|
25
26
|
if e is not None:
|
|
26
27
|
e_type = type(e).__name__ if e_type is None else e_type
|
|
27
28
|
e_message = str(e) if e_message is None else e_message
|
|
@@ -46,7 +47,7 @@ class ContextLog:
|
|
|
46
47
|
return None
|
|
47
48
|
|
|
48
49
|
traceback_lines = e_traceback.splitlines()
|
|
49
|
-
|
|
50
|
+
|
|
50
51
|
# Remove lines that are part of the exception message if they are present in traceback
|
|
51
52
|
message_lines = e_message.splitlines() if e_message else []
|
|
52
53
|
if message_lines:
|
|
@@ -56,7 +57,7 @@ class ContextLog:
|
|
|
56
57
|
|
|
57
58
|
# Filter out lines from third-party libraries (like site-packages)
|
|
58
59
|
filtered_lines = [line for line in traceback_lines if "site-packages" not in line]
|
|
59
|
-
|
|
60
|
+
|
|
60
61
|
# If filtering results in too few lines, revert to original traceback
|
|
61
62
|
if len(filtered_lines) < 2:
|
|
62
63
|
filtered_lines = traceback_lines
|
|
@@ -101,23 +102,108 @@ class ContextLog:
|
|
|
101
102
|
def context(self, value):
|
|
102
103
|
self._context = value
|
|
103
104
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
"
|
|
111
|
-
"
|
|
112
|
-
"
|
|
113
|
-
"
|
|
114
|
-
"
|
|
115
|
-
"
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
105
|
+
|
|
106
|
+
def to_dict(self, size_limit=256 * 1024 * 0.80):
|
|
107
|
+
size_limit = int(size_limit) # Ensure size_limit is an integer
|
|
108
|
+
|
|
109
|
+
# Define the priority order of the fields
|
|
110
|
+
priority_fields = [
|
|
111
|
+
("base_context", self.base_context),
|
|
112
|
+
("level_code", self.level.value),
|
|
113
|
+
("level_name", self.level.name),
|
|
114
|
+
("log_status", self.log_status.value),
|
|
115
|
+
("collector_id", self.collector_id),
|
|
116
|
+
("timestamp", self.timestamp),
|
|
117
|
+
]
|
|
118
|
+
|
|
119
|
+
# Additional fields to be truncated if necessary. Shorter fields are truncated first so that remaining size can increase for longer fields.
|
|
120
|
+
additional_fields = [
|
|
121
|
+
("subject", self.subject),
|
|
122
|
+
("description", self.description),
|
|
123
|
+
("exception_type", self.exception_type),
|
|
124
|
+
("exception_message", self.exception_message),
|
|
125
|
+
("context", self.context), # special sizing rules apply to it
|
|
126
|
+
("exception_traceback", self.exception_traceback)
|
|
127
|
+
]
|
|
128
|
+
|
|
129
|
+
all_fields = priority_fields + additional_fields
|
|
130
|
+
non_zero_fields = [(key, value) for key, value in all_fields if value is not None]
|
|
131
|
+
|
|
132
|
+
total_size = 0
|
|
133
|
+
truncated = False # Flag to indicate if truncation happened
|
|
134
|
+
|
|
135
|
+
# Function to calculate the byte size of a JSON-encoded field
|
|
136
|
+
def field_size(key, value):
|
|
137
|
+
return len(json.dumps({key: value}).encode('utf-8'))
|
|
138
|
+
|
|
139
|
+
# Function to truncate a value based on its type
|
|
140
|
+
def truncate_value(value, max_size):
|
|
141
|
+
if isinstance(value, str):
|
|
142
|
+
half_size = max_size // 2
|
|
143
|
+
return value[:half_size] + '...' + value[-(max_size - half_size - 3):]
|
|
144
|
+
elif isinstance(value, (list, tuple)):
|
|
145
|
+
half_size = max_size // 2
|
|
146
|
+
return list(value[:half_size]) + ['...'] + list(value[-(max_size - half_size - 1):])
|
|
147
|
+
elif isinstance(value, set):
|
|
148
|
+
truncated_set = set(list(value)[:max_size // 2]) | set(list(value)[-(max_size // 2):])
|
|
149
|
+
return truncated_set
|
|
150
|
+
elif isinstance(value, dict):
|
|
151
|
+
truncated_dict = {k: truncate_value(v, max_size // len(value)) for k, v in list(value.items())}
|
|
152
|
+
return truncated_dict
|
|
153
|
+
else:
|
|
154
|
+
return value
|
|
155
|
+
|
|
156
|
+
# Calculate the initial total size
|
|
157
|
+
for key, value in non_zero_fields:
|
|
158
|
+
total_size += field_size(key, value)
|
|
159
|
+
|
|
160
|
+
log_dict = {}
|
|
161
|
+
# Check if total size exceeds the size limit
|
|
162
|
+
if total_size > size_limit:
|
|
163
|
+
truncated = True # Set the truncation flag
|
|
164
|
+
# Calculate max size per field based on all non-zero fields
|
|
165
|
+
max_size_per_field = size_limit // len(non_zero_fields)
|
|
166
|
+
|
|
167
|
+
# Reset total_size to recompute with truncation
|
|
168
|
+
total_size = 0
|
|
169
|
+
|
|
170
|
+
# Add priority fields first with possible truncation
|
|
171
|
+
for key, value in priority_fields:
|
|
172
|
+
if value is not None:
|
|
173
|
+
truncated_value = value
|
|
174
|
+
if isinstance(value, (str, list, tuple, set, dict)) and field_size(key, value) > max_size_per_field:
|
|
175
|
+
truncated_value = truncate_value(value, max_size_per_field)
|
|
176
|
+
log_dict[key] = truncated_value
|
|
177
|
+
total_size += field_size(key, truncated_value)
|
|
178
|
+
else:
|
|
179
|
+
log_dict[key] = value
|
|
180
|
+
|
|
181
|
+
# Calculate remaining size for additional fields
|
|
182
|
+
remaining_size = size_limit - total_size
|
|
183
|
+
|
|
184
|
+
# Handle remaining additional fields
|
|
185
|
+
non_zero_additional_fields = [field for field in additional_fields[1:] if field[1]]
|
|
186
|
+
remaining_field_size = remaining_size // len(non_zero_additional_fields) if non_zero_additional_fields else 0
|
|
187
|
+
|
|
188
|
+
for key, value in additional_fields[1:]:
|
|
189
|
+
if value is not None:
|
|
190
|
+
if field_size(key, value) > remaining_field_size:
|
|
191
|
+
truncated_value = truncate_value(value, remaining_field_size)
|
|
192
|
+
else:
|
|
193
|
+
truncated_value = value
|
|
194
|
+
log_dict[key] = truncated_value
|
|
195
|
+
remaining_size -= field_size(key, truncated_value)
|
|
196
|
+
else:
|
|
197
|
+
log_dict[key] = value
|
|
198
|
+
else:
|
|
199
|
+
log_dict = dict(all_fields)
|
|
200
|
+
|
|
201
|
+
# Add trunc flag to the log dictionary
|
|
202
|
+
log_dict['trunc'] = truncated
|
|
203
|
+
|
|
204
|
+
return log_dict
|
|
205
|
+
|
|
206
|
+
class Pipelinemon:
|
|
121
207
|
ERROR_START_CODE = LogLevel.ERROR.value
|
|
122
208
|
WARNING_START_CODE = LogLevel.WARNING.value
|
|
123
209
|
NOTICE_START_CODE = LogLevel.NOTICE.value
|
|
@@ -192,7 +278,7 @@ class PipelineWatcher:
|
|
|
192
278
|
def add_log(self, log: ContextLog):
|
|
193
279
|
if (self._target_logs == TargetLogs.SUCCESSES and log.level >=self.NOTICE_START_CODE) or \
|
|
194
280
|
(self._target_logs == TargetLogs.WARNINGS_AND_ERRORS and log.level.value < self.WARNING_START_CODE):
|
|
195
|
-
raise ValueError(f"Invalid log level {log.level.name} for
|
|
281
|
+
raise ValueError(f"Invalid log level {log.level.name} for Pipelinemon target logs setup: {self._target_logs}")
|
|
196
282
|
log.base_context = self.base_context
|
|
197
283
|
log.context = self.current_context
|
|
198
284
|
log.collector_id = self.id
|
|
@@ -201,7 +287,7 @@ class PipelineWatcher:
|
|
|
201
287
|
self._update_counts(log_dict)
|
|
202
288
|
|
|
203
289
|
if self._logger:
|
|
204
|
-
# We specifically want to avoid having an ERROR log level for this structured
|
|
290
|
+
# We specifically want to avoid having an ERROR log level for this structured Pipelinemon reporting, to ensure Errors are alerting on Critical Application Services.
|
|
205
291
|
# A single ERROR log level can be used for the entire pipeline, which shall be used at the end of the pipeline
|
|
206
292
|
if log.level.value >= self.WARNING_START_CODE:
|
|
207
293
|
self._logger.log_struct(log_dict, severity="WARNING")
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: ipulse_shared_core_ftredge
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.55
|
|
4
4
|
Summary: Shared Core models and Logger util for the Pulse platform project. Using AI for financial advisory and investment management.
|
|
5
5
|
Home-page: https://github.com/TheFutureEdge/ipulse_shared_core
|
|
6
6
|
Author: Russlan Ramdowar
|
|
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
|