dtlpy 1.114.17__py3-none-any.whl → 1.116.6__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.
- dtlpy/__init__.py +491 -491
- dtlpy/__version__.py +1 -1
- dtlpy/assets/__init__.py +26 -26
- dtlpy/assets/code_server/config.yaml +2 -2
- dtlpy/assets/code_server/installation.sh +24 -24
- dtlpy/assets/code_server/launch.json +13 -13
- dtlpy/assets/code_server/settings.json +2 -2
- dtlpy/assets/main.py +53 -53
- dtlpy/assets/main_partial.py +18 -18
- dtlpy/assets/mock.json +11 -11
- dtlpy/assets/model_adapter.py +83 -83
- dtlpy/assets/package.json +61 -61
- dtlpy/assets/package_catalog.json +29 -29
- dtlpy/assets/package_gitignore +307 -307
- dtlpy/assets/service_runners/__init__.py +33 -33
- dtlpy/assets/service_runners/converter.py +96 -96
- dtlpy/assets/service_runners/multi_method.py +49 -49
- dtlpy/assets/service_runners/multi_method_annotation.py +54 -54
- dtlpy/assets/service_runners/multi_method_dataset.py +55 -55
- dtlpy/assets/service_runners/multi_method_item.py +52 -52
- dtlpy/assets/service_runners/multi_method_json.py +52 -52
- dtlpy/assets/service_runners/single_method.py +37 -37
- dtlpy/assets/service_runners/single_method_annotation.py +43 -43
- dtlpy/assets/service_runners/single_method_dataset.py +43 -43
- dtlpy/assets/service_runners/single_method_item.py +41 -41
- dtlpy/assets/service_runners/single_method_json.py +42 -42
- dtlpy/assets/service_runners/single_method_multi_input.py +45 -45
- dtlpy/assets/voc_annotation_template.xml +23 -23
- dtlpy/caches/base_cache.py +32 -32
- dtlpy/caches/cache.py +473 -473
- dtlpy/caches/dl_cache.py +201 -201
- dtlpy/caches/filesystem_cache.py +89 -89
- dtlpy/caches/redis_cache.py +84 -84
- dtlpy/dlp/__init__.py +20 -20
- dtlpy/dlp/cli_utilities.py +367 -367
- dtlpy/dlp/command_executor.py +764 -764
- dtlpy/dlp/dlp +1 -1
- dtlpy/dlp/dlp.bat +1 -1
- dtlpy/dlp/dlp.py +128 -128
- dtlpy/dlp/parser.py +651 -651
- dtlpy/entities/__init__.py +83 -83
- dtlpy/entities/analytic.py +347 -311
- dtlpy/entities/annotation.py +1879 -1879
- dtlpy/entities/annotation_collection.py +699 -699
- dtlpy/entities/annotation_definitions/__init__.py +20 -20
- dtlpy/entities/annotation_definitions/base_annotation_definition.py +100 -100
- dtlpy/entities/annotation_definitions/box.py +195 -195
- dtlpy/entities/annotation_definitions/classification.py +67 -67
- dtlpy/entities/annotation_definitions/comparison.py +72 -72
- dtlpy/entities/annotation_definitions/cube.py +204 -204
- dtlpy/entities/annotation_definitions/cube_3d.py +149 -149
- dtlpy/entities/annotation_definitions/description.py +32 -32
- dtlpy/entities/annotation_definitions/ellipse.py +124 -124
- dtlpy/entities/annotation_definitions/free_text.py +62 -62
- dtlpy/entities/annotation_definitions/gis.py +69 -69
- dtlpy/entities/annotation_definitions/note.py +139 -139
- dtlpy/entities/annotation_definitions/point.py +117 -117
- dtlpy/entities/annotation_definitions/polygon.py +182 -182
- dtlpy/entities/annotation_definitions/polyline.py +111 -111
- dtlpy/entities/annotation_definitions/pose.py +92 -92
- dtlpy/entities/annotation_definitions/ref_image.py +86 -86
- dtlpy/entities/annotation_definitions/segmentation.py +240 -240
- dtlpy/entities/annotation_definitions/subtitle.py +34 -34
- dtlpy/entities/annotation_definitions/text.py +85 -85
- dtlpy/entities/annotation_definitions/undefined_annotation.py +74 -74
- dtlpy/entities/app.py +220 -220
- dtlpy/entities/app_module.py +107 -107
- dtlpy/entities/artifact.py +174 -174
- dtlpy/entities/assignment.py +399 -399
- dtlpy/entities/base_entity.py +214 -214
- dtlpy/entities/bot.py +113 -113
- dtlpy/entities/codebase.py +292 -296
- dtlpy/entities/collection.py +38 -38
- dtlpy/entities/command.py +169 -169
- dtlpy/entities/compute.py +449 -442
- dtlpy/entities/dataset.py +1299 -1285
- dtlpy/entities/directory_tree.py +44 -44
- dtlpy/entities/dpk.py +470 -470
- dtlpy/entities/driver.py +235 -223
- dtlpy/entities/execution.py +397 -397
- dtlpy/entities/feature.py +124 -124
- dtlpy/entities/feature_set.py +145 -145
- dtlpy/entities/filters.py +798 -645
- dtlpy/entities/gis_item.py +107 -107
- dtlpy/entities/integration.py +184 -184
- dtlpy/entities/item.py +959 -953
- dtlpy/entities/label.py +123 -123
- dtlpy/entities/links.py +85 -85
- dtlpy/entities/message.py +175 -175
- dtlpy/entities/model.py +684 -684
- dtlpy/entities/node.py +1005 -1005
- dtlpy/entities/ontology.py +810 -803
- dtlpy/entities/organization.py +287 -287
- dtlpy/entities/package.py +657 -657
- dtlpy/entities/package_defaults.py +5 -5
- dtlpy/entities/package_function.py +185 -185
- dtlpy/entities/package_module.py +113 -113
- dtlpy/entities/package_slot.py +118 -118
- dtlpy/entities/paged_entities.py +299 -299
- dtlpy/entities/pipeline.py +624 -624
- dtlpy/entities/pipeline_execution.py +279 -279
- dtlpy/entities/project.py +394 -394
- dtlpy/entities/prompt_item.py +505 -499
- dtlpy/entities/recipe.py +301 -301
- dtlpy/entities/reflect_dict.py +102 -102
- dtlpy/entities/resource_execution.py +138 -138
- dtlpy/entities/service.py +963 -958
- dtlpy/entities/service_driver.py +117 -117
- dtlpy/entities/setting.py +294 -294
- dtlpy/entities/task.py +495 -495
- dtlpy/entities/time_series.py +143 -143
- dtlpy/entities/trigger.py +426 -426
- dtlpy/entities/user.py +118 -118
- dtlpy/entities/webhook.py +124 -124
- dtlpy/examples/__init__.py +19 -19
- dtlpy/examples/add_labels.py +135 -135
- dtlpy/examples/add_metadata_to_item.py +21 -21
- dtlpy/examples/annotate_items_using_model.py +65 -65
- dtlpy/examples/annotate_video_using_model_and_tracker.py +75 -75
- dtlpy/examples/annotations_convert_to_voc.py +9 -9
- dtlpy/examples/annotations_convert_to_yolo.py +9 -9
- dtlpy/examples/convert_annotation_types.py +51 -51
- dtlpy/examples/converter.py +143 -143
- dtlpy/examples/copy_annotations.py +22 -22
- dtlpy/examples/copy_folder.py +31 -31
- dtlpy/examples/create_annotations.py +51 -51
- dtlpy/examples/create_video_annotations.py +83 -83
- dtlpy/examples/delete_annotations.py +26 -26
- dtlpy/examples/filters.py +113 -113
- dtlpy/examples/move_item.py +23 -23
- dtlpy/examples/play_video_annotation.py +13 -13
- dtlpy/examples/show_item_and_mask.py +53 -53
- dtlpy/examples/triggers.py +49 -49
- dtlpy/examples/upload_batch_of_items.py +20 -20
- dtlpy/examples/upload_items_and_custom_format_annotations.py +55 -55
- dtlpy/examples/upload_items_with_modalities.py +43 -43
- dtlpy/examples/upload_segmentation_annotations_from_mask_image.py +44 -44
- dtlpy/examples/upload_yolo_format_annotations.py +70 -70
- dtlpy/exceptions.py +125 -125
- dtlpy/miscellaneous/__init__.py +20 -20
- dtlpy/miscellaneous/dict_differ.py +95 -95
- dtlpy/miscellaneous/git_utils.py +217 -217
- dtlpy/miscellaneous/json_utils.py +14 -14
- dtlpy/miscellaneous/list_print.py +105 -105
- dtlpy/miscellaneous/zipping.py +130 -130
- dtlpy/ml/__init__.py +20 -20
- dtlpy/ml/base_feature_extractor_adapter.py +27 -27
- dtlpy/ml/base_model_adapter.py +1257 -1086
- dtlpy/ml/metrics.py +461 -461
- dtlpy/ml/predictions_utils.py +274 -274
- dtlpy/ml/summary_writer.py +57 -57
- dtlpy/ml/train_utils.py +60 -60
- dtlpy/new_instance.py +252 -252
- dtlpy/repositories/__init__.py +56 -56
- dtlpy/repositories/analytics.py +85 -85
- dtlpy/repositories/annotations.py +916 -916
- dtlpy/repositories/apps.py +383 -383
- dtlpy/repositories/artifacts.py +452 -452
- dtlpy/repositories/assignments.py +599 -599
- dtlpy/repositories/bots.py +213 -213
- dtlpy/repositories/codebases.py +559 -559
- dtlpy/repositories/collections.py +332 -332
- dtlpy/repositories/commands.py +152 -158
- dtlpy/repositories/compositions.py +61 -61
- dtlpy/repositories/computes.py +439 -435
- dtlpy/repositories/datasets.py +1504 -1291
- dtlpy/repositories/downloader.py +976 -903
- dtlpy/repositories/dpks.py +433 -433
- dtlpy/repositories/drivers.py +482 -470
- dtlpy/repositories/executions.py +815 -817
- dtlpy/repositories/feature_sets.py +226 -226
- dtlpy/repositories/features.py +255 -238
- dtlpy/repositories/integrations.py +484 -484
- dtlpy/repositories/items.py +912 -909
- dtlpy/repositories/messages.py +94 -94
- dtlpy/repositories/models.py +1000 -988
- dtlpy/repositories/nodes.py +80 -80
- dtlpy/repositories/ontologies.py +511 -511
- dtlpy/repositories/organizations.py +525 -525
- dtlpy/repositories/packages.py +1941 -1941
- dtlpy/repositories/pipeline_executions.py +451 -451
- dtlpy/repositories/pipelines.py +640 -640
- dtlpy/repositories/projects.py +539 -539
- dtlpy/repositories/recipes.py +419 -399
- dtlpy/repositories/resource_executions.py +137 -137
- dtlpy/repositories/schema.py +120 -120
- dtlpy/repositories/service_drivers.py +213 -213
- dtlpy/repositories/services.py +1704 -1704
- dtlpy/repositories/settings.py +339 -339
- dtlpy/repositories/tasks.py +1477 -1477
- dtlpy/repositories/times_series.py +278 -278
- dtlpy/repositories/triggers.py +536 -536
- dtlpy/repositories/upload_element.py +257 -257
- dtlpy/repositories/uploader.py +661 -651
- dtlpy/repositories/webhooks.py +249 -249
- dtlpy/services/__init__.py +22 -22
- dtlpy/services/aihttp_retry.py +131 -131
- dtlpy/services/api_client.py +1785 -1782
- dtlpy/services/api_reference.py +40 -40
- dtlpy/services/async_utils.py +133 -133
- dtlpy/services/calls_counter.py +44 -44
- dtlpy/services/check_sdk.py +68 -68
- dtlpy/services/cookie.py +115 -115
- dtlpy/services/create_logger.py +156 -156
- dtlpy/services/events.py +84 -84
- dtlpy/services/logins.py +235 -235
- dtlpy/services/reporter.py +256 -256
- dtlpy/services/service_defaults.py +91 -91
- dtlpy/utilities/__init__.py +20 -20
- dtlpy/utilities/annotations/__init__.py +16 -16
- dtlpy/utilities/annotations/annotation_converters.py +269 -269
- dtlpy/utilities/base_package_runner.py +285 -264
- dtlpy/utilities/converter.py +1650 -1650
- dtlpy/utilities/dataset_generators/__init__.py +1 -1
- dtlpy/utilities/dataset_generators/dataset_generator.py +670 -670
- dtlpy/utilities/dataset_generators/dataset_generator_tensorflow.py +23 -23
- dtlpy/utilities/dataset_generators/dataset_generator_torch.py +21 -21
- dtlpy/utilities/local_development/__init__.py +1 -1
- dtlpy/utilities/local_development/local_session.py +179 -179
- dtlpy/utilities/reports/__init__.py +2 -2
- dtlpy/utilities/reports/figures.py +343 -343
- dtlpy/utilities/reports/report.py +71 -71
- dtlpy/utilities/videos/__init__.py +17 -17
- dtlpy/utilities/videos/video_player.py +598 -598
- dtlpy/utilities/videos/videos.py +470 -470
- {dtlpy-1.114.17.data → dtlpy-1.116.6.data}/scripts/dlp +1 -1
- dtlpy-1.116.6.data/scripts/dlp.bat +2 -0
- {dtlpy-1.114.17.data → dtlpy-1.116.6.data}/scripts/dlp.py +128 -128
- {dtlpy-1.114.17.dist-info → dtlpy-1.116.6.dist-info}/METADATA +186 -183
- dtlpy-1.116.6.dist-info/RECORD +239 -0
- {dtlpy-1.114.17.dist-info → dtlpy-1.116.6.dist-info}/WHEEL +1 -1
- {dtlpy-1.114.17.dist-info → dtlpy-1.116.6.dist-info}/licenses/LICENSE +200 -200
- tests/features/environment.py +551 -551
- dtlpy/assets/__pycache__/__init__.cpython-310.pyc +0 -0
- dtlpy-1.114.17.data/scripts/dlp.bat +0 -2
- dtlpy-1.114.17.dist-info/RECORD +0 -240
- {dtlpy-1.114.17.dist-info → dtlpy-1.116.6.dist-info}/entry_points.txt +0 -0
- {dtlpy-1.114.17.dist-info → dtlpy-1.116.6.dist-info}/top_level.txt +0 -0
dtlpy/services/reporter.py
CHANGED
|
@@ -1,256 +1,256 @@
|
|
|
1
|
-
import os
|
|
2
|
-
import datetime
|
|
3
|
-
import json
|
|
4
|
-
import threading
|
|
5
|
-
from .. import services
|
|
6
|
-
from .. import exceptions
|
|
7
|
-
import logging
|
|
8
|
-
from ..caches import dl_cache
|
|
9
|
-
|
|
10
|
-
logger = logging.getLogger(name='dtlpy')
|
|
11
|
-
CHUNK = 200000
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
class Reporter:
|
|
15
|
-
"""
|
|
16
|
-
ThreadPool Report summary
|
|
17
|
-
"""
|
|
18
|
-
ITEMS_DOWNLOAD = 'downloader'
|
|
19
|
-
ITEMS_UPLOAD = 'uploader'
|
|
20
|
-
CONVERTER = 'converter'
|
|
21
|
-
|
|
22
|
-
def __init__(self,
|
|
23
|
-
num_workers,
|
|
24
|
-
resource,
|
|
25
|
-
client_api,
|
|
26
|
-
print_error_logs=False,
|
|
27
|
-
output_entity=None,
|
|
28
|
-
no_output=False):
|
|
29
|
-
self._num_workers = num_workers
|
|
30
|
-
self.mutex = threading.Lock()
|
|
31
|
-
self.no_output = no_output
|
|
32
|
-
self._client_api = client_api
|
|
33
|
-
self.key = datetime.datetime.now().strftime('%Y-%m-%d-%H-%M-%S')
|
|
34
|
-
self.cache_mode = client_api.cache_state.enable_cache
|
|
35
|
-
if self.cache_mode is None:
|
|
36
|
-
self.cache_mode = True
|
|
37
|
-
self.cache_chunk = client_api.cache_state.chunk_cache
|
|
38
|
-
if self.cache_chunk is None:
|
|
39
|
-
self.cache_chunk = CHUNK
|
|
40
|
-
self._reports = None
|
|
41
|
-
self._success = dict()
|
|
42
|
-
self._status = dict()
|
|
43
|
-
self._errors = dict()
|
|
44
|
-
self._output = dict()
|
|
45
|
-
self.cache_items = {'errors': self._errors,
|
|
46
|
-
'status': self._status,
|
|
47
|
-
'output': self._output}
|
|
48
|
-
self._resource = resource
|
|
49
|
-
self._print_error_logs = print_error_logs
|
|
50
|
-
self._output_entity = output_entity
|
|
51
|
-
|
|
52
|
-
@property
|
|
53
|
-
def has_errors(self):
|
|
54
|
-
"""
|
|
55
|
-
return True if errors has occurred False otherwise
|
|
56
|
-
"""
|
|
57
|
-
return self.failure_count > 0
|
|
58
|
-
|
|
59
|
-
def build_cache(self):
|
|
60
|
-
if self.cache_mode:
|
|
61
|
-
try:
|
|
62
|
-
self._reports = {'errors': dl_cache.DiskCache('errors-' + self.key),
|
|
63
|
-
'output': dl_cache.DiskCache('output-' + self.key),
|
|
64
|
-
'status': dl_cache.DiskCache('status-' + self.key),
|
|
65
|
-
}
|
|
66
|
-
self._reports.get('status').add('success', 0)
|
|
67
|
-
self._reports.get('status').add('failure', 0)
|
|
68
|
-
self.clear_reporter()
|
|
69
|
-
except:
|
|
70
|
-
raise exceptions.PlatformException(
|
|
71
|
-
error='2001',
|
|
72
|
-
message='Failed to initialize cache handler. Please disable cache usage: dl.cache_state.enable_cache = False')
|
|
73
|
-
|
|
74
|
-
def construct_output(self, entity):
|
|
75
|
-
"""
|
|
76
|
-
convert the json to his entity object
|
|
77
|
-
"""
|
|
78
|
-
if self._output_entity and entity:
|
|
79
|
-
return self._output_entity.from_json(client_api=self._client_api, _json=entity)
|
|
80
|
-
return entity
|
|
81
|
-
|
|
82
|
-
@property
|
|
83
|
-
def output(self):
|
|
84
|
-
"""
|
|
85
|
-
return a generator for all the outputs or the output it self if it is single
|
|
86
|
-
"""
|
|
87
|
-
if self.no_output:
|
|
88
|
-
return
|
|
89
|
-
if self.cache_mode == 'diskcache':
|
|
90
|
-
output = self._reports.get('output')
|
|
91
|
-
for k in output.keys():
|
|
92
|
-
for item in list(output.get(key=k).values()):
|
|
93
|
-
yield self.construct_output(item)
|
|
94
|
-
|
|
95
|
-
current = [self.construct_output(output) for output in list(self._output.values()) if output is not None]
|
|
96
|
-
for item in current:
|
|
97
|
-
yield item
|
|
98
|
-
|
|
99
|
-
@property
|
|
100
|
-
def status_list(self):
|
|
101
|
-
"""
|
|
102
|
-
return a list of all the status that get
|
|
103
|
-
"""
|
|
104
|
-
output = dict()
|
|
105
|
-
if self.cache_mode == 'diskcache':
|
|
106
|
-
status_cache = self._reports.get('status')
|
|
107
|
-
for key in status_cache.keys():
|
|
108
|
-
if key not in ['failure', 'success']:
|
|
109
|
-
output.update(status_cache.get(key=key))
|
|
110
|
-
output.update(self._status)
|
|
111
|
-
return list(output.values())
|
|
112
|
-
|
|
113
|
-
@property
|
|
114
|
-
def num_workers(self):
|
|
115
|
-
"""
|
|
116
|
-
number of the threads to work
|
|
117
|
-
"""
|
|
118
|
-
return self._num_workers
|
|
119
|
-
|
|
120
|
-
def upcount_num_workers(self):
|
|
121
|
-
"""
|
|
122
|
-
increase the number of the threads to work
|
|
123
|
-
"""
|
|
124
|
-
self._num_workers += 1
|
|
125
|
-
|
|
126
|
-
@property
|
|
127
|
-
def failure_count(self):
|
|
128
|
-
"""
|
|
129
|
-
return how many actions fail
|
|
130
|
-
"""
|
|
131
|
-
curr = len([suc for suc in (self._success.values()) if suc is False])
|
|
132
|
-
if self.cache_mode == 'diskcache':
|
|
133
|
-
return self._reports.get('status').get(key='failure') + curr
|
|
134
|
-
else:
|
|
135
|
-
return curr
|
|
136
|
-
|
|
137
|
-
@property
|
|
138
|
-
def success_count(self):
|
|
139
|
-
"""
|
|
140
|
-
return how many actions success
|
|
141
|
-
"""
|
|
142
|
-
curr = len([suc for suc in (self._success.values()) if suc is True])
|
|
143
|
-
if self.cache_mode == 'diskcache':
|
|
144
|
-
return self._reports.get('status').get(key='success') + curr
|
|
145
|
-
else:
|
|
146
|
-
return curr
|
|
147
|
-
|
|
148
|
-
def status_count(self, status):
|
|
149
|
-
"""
|
|
150
|
-
:param status: str of status to check it
|
|
151
|
-
:return: how many times this status appear
|
|
152
|
-
"""
|
|
153
|
-
status_list = self.status_list
|
|
154
|
-
return list(status_list).count(status)
|
|
155
|
-
|
|
156
|
-
def _write_to_disk(self):
|
|
157
|
-
"""
|
|
158
|
-
the function write to the dick the outputs that get until the chunk amount
|
|
159
|
-
"""
|
|
160
|
-
with self.mutex:
|
|
161
|
-
if self._reports is None:
|
|
162
|
-
self.build_cache()
|
|
163
|
-
if len(self._success) > self.cache_chunk:
|
|
164
|
-
status_cache = self._reports.get('status')
|
|
165
|
-
num_true = sum(list(self._success.values()))
|
|
166
|
-
status_cache.incr(key='failure',
|
|
167
|
-
value=len(self._success) - num_true)
|
|
168
|
-
status_cache.incr(key='success',
|
|
169
|
-
value=num_true)
|
|
170
|
-
self._success.clear()
|
|
171
|
-
for name, cache_list in self.cache_items.items():
|
|
172
|
-
if len(cache_list) > self.cache_chunk:
|
|
173
|
-
self._reports[name].push(cache_list)
|
|
174
|
-
cache_list.clear()
|
|
175
|
-
|
|
176
|
-
def set_index(self, ref, error=None, status=None, success=None, output=None):
|
|
177
|
-
"""
|
|
178
|
-
set the values that we get from the actions in the reporter
|
|
179
|
-
"""
|
|
180
|
-
if self.mutex.locked():
|
|
181
|
-
self.mutex.acquire()
|
|
182
|
-
self.mutex.release()
|
|
183
|
-
if error is not None:
|
|
184
|
-
self._errors[ref] = error
|
|
185
|
-
|
|
186
|
-
if status is not None:
|
|
187
|
-
self._status[ref] = status
|
|
188
|
-
|
|
189
|
-
if success is not None:
|
|
190
|
-
self._success[ref] = success
|
|
191
|
-
|
|
192
|
-
if success and output is not None:
|
|
193
|
-
if not self.no_output:
|
|
194
|
-
self._output[ref] = output
|
|
195
|
-
|
|
196
|
-
if len(self._errors) > self.cache_chunk or \
|
|
197
|
-
len(self._status) > self.cache_chunk or \
|
|
198
|
-
len(self._output) > self.cache_chunk or \
|
|
199
|
-
len(self._success) > self.cache_chunk:
|
|
200
|
-
if self.cache_mode:
|
|
201
|
-
self._write_to_disk()
|
|
202
|
-
|
|
203
|
-
def generate_log_files(self):
|
|
204
|
-
"""
|
|
205
|
-
build a log file that display the errors
|
|
206
|
-
"""
|
|
207
|
-
if len(self._errors) > 0 and self.cache_mode == 'diskcache':
|
|
208
|
-
# write from RAM to disk
|
|
209
|
-
self._reports['errors'].push(self._errors)
|
|
210
|
-
self._errors.clear()
|
|
211
|
-
|
|
212
|
-
reports_dir = os.path.join(services.service_defaults.DATALOOP_PATH, 'reporters')
|
|
213
|
-
if not os.path.exists(reports_dir):
|
|
214
|
-
os.mkdir(reports_dir)
|
|
215
|
-
log_filepath = os.path.join(reports_dir,
|
|
216
|
-
"log_{}_{}.json".format(self._resource,
|
|
217
|
-
datetime.datetime.now(datetime.timezone.utc).strftime("%Y%m%d_%H%M%S")))
|
|
218
|
-
errors_json = dict()
|
|
219
|
-
if self.cache_mode == 'diskcache':
|
|
220
|
-
err_cache = self._reports['errors']
|
|
221
|
-
for k in err_cache.keys():
|
|
222
|
-
errors_json.update(err_cache.get(k))
|
|
223
|
-
if self._errors:
|
|
224
|
-
errors_json.update(self._errors)
|
|
225
|
-
if self._print_error_logs:
|
|
226
|
-
for key in errors_json:
|
|
227
|
-
logger.warning("{}\n{}".format(key, errors_json[key]))
|
|
228
|
-
return None
|
|
229
|
-
else:
|
|
230
|
-
with open(log_filepath, "w") as f:
|
|
231
|
-
json.dump(errors_json, f, indent=2)
|
|
232
|
-
return log_filepath
|
|
233
|
-
|
|
234
|
-
def clear_reporter(self):
|
|
235
|
-
"""
|
|
236
|
-
clear the file system from the outputs
|
|
237
|
-
"""
|
|
238
|
-
import shutil
|
|
239
|
-
date_now = datetime.datetime(year=int(self.key.split('-')[0]),
|
|
240
|
-
month=int(self.key.split('-')[1]),
|
|
241
|
-
day=int(self.key.split('-')[2]))
|
|
242
|
-
cache_dir = os.path.dirname(self._reports['output'].cache_dir)
|
|
243
|
-
cache_files_list = os.listdir(cache_dir)
|
|
244
|
-
# remove all the cache files from the last day
|
|
245
|
-
for filename in cache_files_list:
|
|
246
|
-
try:
|
|
247
|
-
date_file = datetime.datetime(year=int(filename.split('-')[1]),
|
|
248
|
-
month=int(filename.split('-')[2]),
|
|
249
|
-
day=int(filename.split('-')[3]))
|
|
250
|
-
except:
|
|
251
|
-
continue
|
|
252
|
-
if date_file < date_now:
|
|
253
|
-
try:
|
|
254
|
-
shutil.rmtree(cache_dir + '\\' + filename)
|
|
255
|
-
except OSError: # Windows wonkiness
|
|
256
|
-
pass
|
|
1
|
+
import os
|
|
2
|
+
import datetime
|
|
3
|
+
import json
|
|
4
|
+
import threading
|
|
5
|
+
from .. import services
|
|
6
|
+
from .. import exceptions
|
|
7
|
+
import logging
|
|
8
|
+
from ..caches import dl_cache
|
|
9
|
+
|
|
10
|
+
logger = logging.getLogger(name='dtlpy')
|
|
11
|
+
CHUNK = 200000
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class Reporter:
|
|
15
|
+
"""
|
|
16
|
+
ThreadPool Report summary
|
|
17
|
+
"""
|
|
18
|
+
ITEMS_DOWNLOAD = 'downloader'
|
|
19
|
+
ITEMS_UPLOAD = 'uploader'
|
|
20
|
+
CONVERTER = 'converter'
|
|
21
|
+
|
|
22
|
+
def __init__(self,
|
|
23
|
+
num_workers,
|
|
24
|
+
resource,
|
|
25
|
+
client_api,
|
|
26
|
+
print_error_logs=False,
|
|
27
|
+
output_entity=None,
|
|
28
|
+
no_output=False):
|
|
29
|
+
self._num_workers = num_workers
|
|
30
|
+
self.mutex = threading.Lock()
|
|
31
|
+
self.no_output = no_output
|
|
32
|
+
self._client_api = client_api
|
|
33
|
+
self.key = datetime.datetime.now().strftime('%Y-%m-%d-%H-%M-%S')
|
|
34
|
+
self.cache_mode = client_api.cache_state.enable_cache
|
|
35
|
+
if self.cache_mode is None:
|
|
36
|
+
self.cache_mode = True
|
|
37
|
+
self.cache_chunk = client_api.cache_state.chunk_cache
|
|
38
|
+
if self.cache_chunk is None:
|
|
39
|
+
self.cache_chunk = CHUNK
|
|
40
|
+
self._reports = None
|
|
41
|
+
self._success = dict()
|
|
42
|
+
self._status = dict()
|
|
43
|
+
self._errors = dict()
|
|
44
|
+
self._output = dict()
|
|
45
|
+
self.cache_items = {'errors': self._errors,
|
|
46
|
+
'status': self._status,
|
|
47
|
+
'output': self._output}
|
|
48
|
+
self._resource = resource
|
|
49
|
+
self._print_error_logs = print_error_logs
|
|
50
|
+
self._output_entity = output_entity
|
|
51
|
+
|
|
52
|
+
@property
|
|
53
|
+
def has_errors(self):
|
|
54
|
+
"""
|
|
55
|
+
return True if errors has occurred False otherwise
|
|
56
|
+
"""
|
|
57
|
+
return self.failure_count > 0
|
|
58
|
+
|
|
59
|
+
def build_cache(self):
|
|
60
|
+
if self.cache_mode:
|
|
61
|
+
try:
|
|
62
|
+
self._reports = {'errors': dl_cache.DiskCache('errors-' + self.key),
|
|
63
|
+
'output': dl_cache.DiskCache('output-' + self.key),
|
|
64
|
+
'status': dl_cache.DiskCache('status-' + self.key),
|
|
65
|
+
}
|
|
66
|
+
self._reports.get('status').add('success', 0)
|
|
67
|
+
self._reports.get('status').add('failure', 0)
|
|
68
|
+
self.clear_reporter()
|
|
69
|
+
except:
|
|
70
|
+
raise exceptions.PlatformException(
|
|
71
|
+
error='2001',
|
|
72
|
+
message='Failed to initialize cache handler. Please disable cache usage: dl.cache_state.enable_cache = False')
|
|
73
|
+
|
|
74
|
+
def construct_output(self, entity):
|
|
75
|
+
"""
|
|
76
|
+
convert the json to his entity object
|
|
77
|
+
"""
|
|
78
|
+
if self._output_entity and entity:
|
|
79
|
+
return self._output_entity.from_json(client_api=self._client_api, _json=entity)
|
|
80
|
+
return entity
|
|
81
|
+
|
|
82
|
+
@property
|
|
83
|
+
def output(self):
|
|
84
|
+
"""
|
|
85
|
+
return a generator for all the outputs or the output it self if it is single
|
|
86
|
+
"""
|
|
87
|
+
if self.no_output:
|
|
88
|
+
return
|
|
89
|
+
if self.cache_mode == 'diskcache':
|
|
90
|
+
output = self._reports.get('output')
|
|
91
|
+
for k in output.keys():
|
|
92
|
+
for item in list(output.get(key=k).values()):
|
|
93
|
+
yield self.construct_output(item)
|
|
94
|
+
|
|
95
|
+
current = [self.construct_output(output) for output in list(self._output.values()) if output is not None]
|
|
96
|
+
for item in current:
|
|
97
|
+
yield item
|
|
98
|
+
|
|
99
|
+
@property
|
|
100
|
+
def status_list(self):
|
|
101
|
+
"""
|
|
102
|
+
return a list of all the status that get
|
|
103
|
+
"""
|
|
104
|
+
output = dict()
|
|
105
|
+
if self.cache_mode == 'diskcache':
|
|
106
|
+
status_cache = self._reports.get('status')
|
|
107
|
+
for key in status_cache.keys():
|
|
108
|
+
if key not in ['failure', 'success']:
|
|
109
|
+
output.update(status_cache.get(key=key))
|
|
110
|
+
output.update(self._status)
|
|
111
|
+
return list(output.values())
|
|
112
|
+
|
|
113
|
+
@property
|
|
114
|
+
def num_workers(self):
|
|
115
|
+
"""
|
|
116
|
+
number of the threads to work
|
|
117
|
+
"""
|
|
118
|
+
return self._num_workers
|
|
119
|
+
|
|
120
|
+
def upcount_num_workers(self):
|
|
121
|
+
"""
|
|
122
|
+
increase the number of the threads to work
|
|
123
|
+
"""
|
|
124
|
+
self._num_workers += 1
|
|
125
|
+
|
|
126
|
+
@property
|
|
127
|
+
def failure_count(self):
|
|
128
|
+
"""
|
|
129
|
+
return how many actions fail
|
|
130
|
+
"""
|
|
131
|
+
curr = len([suc for suc in (self._success.values()) if suc is False])
|
|
132
|
+
if self.cache_mode == 'diskcache':
|
|
133
|
+
return self._reports.get('status').get(key='failure') + curr
|
|
134
|
+
else:
|
|
135
|
+
return curr
|
|
136
|
+
|
|
137
|
+
@property
|
|
138
|
+
def success_count(self):
|
|
139
|
+
"""
|
|
140
|
+
return how many actions success
|
|
141
|
+
"""
|
|
142
|
+
curr = len([suc for suc in (self._success.values()) if suc is True])
|
|
143
|
+
if self.cache_mode == 'diskcache':
|
|
144
|
+
return self._reports.get('status').get(key='success') + curr
|
|
145
|
+
else:
|
|
146
|
+
return curr
|
|
147
|
+
|
|
148
|
+
def status_count(self, status):
|
|
149
|
+
"""
|
|
150
|
+
:param status: str of status to check it
|
|
151
|
+
:return: how many times this status appear
|
|
152
|
+
"""
|
|
153
|
+
status_list = self.status_list
|
|
154
|
+
return list(status_list).count(status)
|
|
155
|
+
|
|
156
|
+
def _write_to_disk(self):
|
|
157
|
+
"""
|
|
158
|
+
the function write to the dick the outputs that get until the chunk amount
|
|
159
|
+
"""
|
|
160
|
+
with self.mutex:
|
|
161
|
+
if self._reports is None:
|
|
162
|
+
self.build_cache()
|
|
163
|
+
if len(self._success) > self.cache_chunk:
|
|
164
|
+
status_cache = self._reports.get('status')
|
|
165
|
+
num_true = sum(list(self._success.values()))
|
|
166
|
+
status_cache.incr(key='failure',
|
|
167
|
+
value=len(self._success) - num_true)
|
|
168
|
+
status_cache.incr(key='success',
|
|
169
|
+
value=num_true)
|
|
170
|
+
self._success.clear()
|
|
171
|
+
for name, cache_list in self.cache_items.items():
|
|
172
|
+
if len(cache_list) > self.cache_chunk:
|
|
173
|
+
self._reports[name].push(cache_list)
|
|
174
|
+
cache_list.clear()
|
|
175
|
+
|
|
176
|
+
def set_index(self, ref, error=None, status=None, success=None, output=None):
|
|
177
|
+
"""
|
|
178
|
+
set the values that we get from the actions in the reporter
|
|
179
|
+
"""
|
|
180
|
+
if self.mutex.locked():
|
|
181
|
+
self.mutex.acquire()
|
|
182
|
+
self.mutex.release()
|
|
183
|
+
if error is not None:
|
|
184
|
+
self._errors[ref] = error
|
|
185
|
+
|
|
186
|
+
if status is not None:
|
|
187
|
+
self._status[ref] = status
|
|
188
|
+
|
|
189
|
+
if success is not None:
|
|
190
|
+
self._success[ref] = success
|
|
191
|
+
|
|
192
|
+
if success and output is not None:
|
|
193
|
+
if not self.no_output:
|
|
194
|
+
self._output[ref] = output
|
|
195
|
+
|
|
196
|
+
if len(self._errors) > self.cache_chunk or \
|
|
197
|
+
len(self._status) > self.cache_chunk or \
|
|
198
|
+
len(self._output) > self.cache_chunk or \
|
|
199
|
+
len(self._success) > self.cache_chunk:
|
|
200
|
+
if self.cache_mode:
|
|
201
|
+
self._write_to_disk()
|
|
202
|
+
|
|
203
|
+
def generate_log_files(self):
|
|
204
|
+
"""
|
|
205
|
+
build a log file that display the errors
|
|
206
|
+
"""
|
|
207
|
+
if len(self._errors) > 0 and self.cache_mode == 'diskcache':
|
|
208
|
+
# write from RAM to disk
|
|
209
|
+
self._reports['errors'].push(self._errors)
|
|
210
|
+
self._errors.clear()
|
|
211
|
+
|
|
212
|
+
reports_dir = os.path.join(services.service_defaults.DATALOOP_PATH, 'reporters')
|
|
213
|
+
if not os.path.exists(reports_dir):
|
|
214
|
+
os.mkdir(reports_dir)
|
|
215
|
+
log_filepath = os.path.join(reports_dir,
|
|
216
|
+
"log_{}_{}.json".format(self._resource,
|
|
217
|
+
datetime.datetime.now(datetime.timezone.utc).strftime("%Y%m%d_%H%M%S%f"))) # Added %f to the format to include microseconds
|
|
218
|
+
errors_json = dict()
|
|
219
|
+
if self.cache_mode == 'diskcache':
|
|
220
|
+
err_cache = self._reports['errors']
|
|
221
|
+
for k in err_cache.keys():
|
|
222
|
+
errors_json.update(err_cache.get(k))
|
|
223
|
+
if self._errors:
|
|
224
|
+
errors_json.update(self._errors)
|
|
225
|
+
if self._print_error_logs:
|
|
226
|
+
for key in errors_json:
|
|
227
|
+
logger.warning("{}\n{}".format(key, errors_json[key]))
|
|
228
|
+
return None
|
|
229
|
+
else:
|
|
230
|
+
with open(log_filepath, "w") as f:
|
|
231
|
+
json.dump(errors_json, f, indent=2)
|
|
232
|
+
return log_filepath
|
|
233
|
+
|
|
234
|
+
def clear_reporter(self):
|
|
235
|
+
"""
|
|
236
|
+
clear the file system from the outputs
|
|
237
|
+
"""
|
|
238
|
+
import shutil
|
|
239
|
+
date_now = datetime.datetime(year=int(self.key.split('-')[0]),
|
|
240
|
+
month=int(self.key.split('-')[1]),
|
|
241
|
+
day=int(self.key.split('-')[2]))
|
|
242
|
+
cache_dir = os.path.dirname(self._reports['output'].cache_dir)
|
|
243
|
+
cache_files_list = os.listdir(cache_dir)
|
|
244
|
+
# remove all the cache files from the last day
|
|
245
|
+
for filename in cache_files_list:
|
|
246
|
+
try:
|
|
247
|
+
date_file = datetime.datetime(year=int(filename.split('-')[1]),
|
|
248
|
+
month=int(filename.split('-')[2]),
|
|
249
|
+
day=int(filename.split('-')[3]))
|
|
250
|
+
except:
|
|
251
|
+
continue
|
|
252
|
+
if date_file < date_now:
|
|
253
|
+
try:
|
|
254
|
+
shutil.rmtree(cache_dir + '\\' + filename)
|
|
255
|
+
except OSError: # Windows wonkiness
|
|
256
|
+
pass
|