deltacat 1.1.2__py3-none-any.whl → 1.1.4__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.
- deltacat/__init__.py +1 -1
- deltacat/aws/constants.py +0 -4
- deltacat/aws/s3u.py +26 -5
- deltacat/compute/compactor/utils/round_completion_file.py +3 -0
- deltacat/compute/compactor_v2/compaction_session.py +2 -10
- deltacat/compute/compactor_v2/constants.py +0 -3
- deltacat/compute/compactor_v2/utils/merge.py +0 -3
- deltacat/logs.py +126 -69
- deltacat/tests/aws/test_s3u.py +12 -0
- deltacat/tests/test_logs.py +127 -0
- deltacat/tests/utils/test_metrics.py +26 -99
- deltacat/tests/utils/test_placement.py +25 -0
- deltacat/utils/metrics.py +35 -18
- deltacat/utils/placement.py +14 -7
- {deltacat-1.1.2.dist-info → deltacat-1.1.4.dist-info}/METADATA +1 -1
- {deltacat-1.1.2.dist-info → deltacat-1.1.4.dist-info}/RECORD +19 -16
- {deltacat-1.1.2.dist-info → deltacat-1.1.4.dist-info}/LICENSE +0 -0
- {deltacat-1.1.2.dist-info → deltacat-1.1.4.dist-info}/WHEEL +0 -0
- {deltacat-1.1.2.dist-info → deltacat-1.1.4.dist-info}/top_level.txt +0 -0
deltacat/__init__.py
CHANGED
deltacat/aws/constants.py
CHANGED
@@ -6,7 +6,3 @@ DAFT_MAX_S3_CONNECTIONS_PER_FILE = env_integer("DAFT_MAX_S3_CONNECTIONS_PER_FILE
|
|
6
6
|
BOTO_MAX_RETRIES = env_integer("BOTO_MAX_RETRIES", 5)
|
7
7
|
TIMEOUT_ERROR_CODES: List[str] = ["ReadTimeoutError", "ConnectTimeoutError"]
|
8
8
|
AWS_REGION = env_string("AWS_REGION", "us-east-1")
|
9
|
-
|
10
|
-
# Metric Names
|
11
|
-
DOWNLOAD_MANIFEST_ENTRY_METRIC_PREFIX = "download_manifest_entry"
|
12
|
-
UPLOAD_SLICED_TABLE_METRIC_PREFIX = "upload_sliced_table"
|
deltacat/aws/s3u.py
CHANGED
@@ -27,8 +27,6 @@ import deltacat.aws.clients as aws_utils
|
|
27
27
|
from deltacat import logs
|
28
28
|
from deltacat.aws.constants import (
|
29
29
|
TIMEOUT_ERROR_CODES,
|
30
|
-
DOWNLOAD_MANIFEST_ENTRY_METRIC_PREFIX,
|
31
|
-
UPLOAD_SLICED_TABLE_METRIC_PREFIX,
|
32
30
|
)
|
33
31
|
from deltacat.exceptions import NonRetryableError, RetryableError
|
34
32
|
from deltacat.storage import (
|
@@ -54,7 +52,6 @@ from deltacat.types.tables import (
|
|
54
52
|
)
|
55
53
|
from deltacat.types.partial_download import PartialFileDownloadParams
|
56
54
|
from deltacat.utils.common import ReadKwargsProvider
|
57
|
-
from deltacat.utils.metrics import metrics
|
58
55
|
|
59
56
|
logger = logs.configure_deltacat_logger(logging.getLogger(__name__))
|
60
57
|
|
@@ -121,6 +118,32 @@ class UuidBlockWritePathProvider(BlockWritePathProvider):
|
|
121
118
|
self.block_refs.append(block)
|
122
119
|
return write_path
|
123
120
|
|
121
|
+
def __call__(
|
122
|
+
self,
|
123
|
+
base_path: str,
|
124
|
+
*,
|
125
|
+
filesystem: Optional[pa.filesystem.FileSystem] = None,
|
126
|
+
dataset_uuid: Optional[str] = None,
|
127
|
+
block: Optional[ObjectRef[Block]] = None,
|
128
|
+
block_index: Optional[int] = None,
|
129
|
+
file_format: Optional[str] = None,
|
130
|
+
) -> str:
|
131
|
+
"""
|
132
|
+
TODO: BlockWritePathProvider is deprecated as of Ray version 2.20.0. Please use FilenameProvider.
|
133
|
+
See: https://docs.ray.io/en/master/data/api/doc/ray.data.datasource.FilenameProvider.html
|
134
|
+
Also See: https://github.com/ray-project/deltacat/issues/299
|
135
|
+
|
136
|
+
Hence, this class only works with Ray version 2.20.0 or lower when used in Ray Dataset.
|
137
|
+
"""
|
138
|
+
return self._get_write_path_for_block(
|
139
|
+
base_path,
|
140
|
+
filesystem=filesystem,
|
141
|
+
dataset_uuid=dataset_uuid,
|
142
|
+
block=block,
|
143
|
+
block_index=block_index,
|
144
|
+
file_format=file_format,
|
145
|
+
)
|
146
|
+
|
124
147
|
|
125
148
|
class S3Url:
|
126
149
|
def __init__(self, url: str):
|
@@ -243,7 +266,6 @@ def read_file(
|
|
243
266
|
raise e
|
244
267
|
|
245
268
|
|
246
|
-
@metrics(prefix=UPLOAD_SLICED_TABLE_METRIC_PREFIX)
|
247
269
|
def upload_sliced_table(
|
248
270
|
table: Union[LocalTable, DistributedDataset],
|
249
271
|
s3_url_prefix: str,
|
@@ -352,7 +374,6 @@ def upload_table(
|
|
352
374
|
return manifest_entries
|
353
375
|
|
354
376
|
|
355
|
-
@metrics(prefix=DOWNLOAD_MANIFEST_ENTRY_METRIC_PREFIX)
|
356
377
|
def download_manifest_entry(
|
357
378
|
manifest_entry: ManifestEntry,
|
358
379
|
token_holder: Optional[Dict[str, Any]] = None,
|
@@ -6,6 +6,7 @@ from deltacat.compute.compactor import RoundCompletionInfo
|
|
6
6
|
from deltacat.storage import PartitionLocator
|
7
7
|
from deltacat.aws import s3u as s3_utils
|
8
8
|
from typing import Optional
|
9
|
+
from deltacat.utils.metrics import metrics
|
9
10
|
|
10
11
|
logger = logs.configure_deltacat_logger(logging.getLogger(__name__))
|
11
12
|
|
@@ -18,6 +19,7 @@ def get_round_completion_file_s3_url(
|
|
18
19
|
return f"{base_url}.json"
|
19
20
|
|
20
21
|
|
22
|
+
@metrics
|
21
23
|
def read_round_completion_file(
|
22
24
|
bucket: str,
|
23
25
|
source_partition_locator: PartitionLocator,
|
@@ -38,6 +40,7 @@ def read_round_completion_file(
|
|
38
40
|
return round_completion_info
|
39
41
|
|
40
42
|
|
43
|
+
@metrics
|
41
44
|
def write_round_completion_file(
|
42
45
|
bucket: Optional[str],
|
43
46
|
source_partition_locator: Optional[PartitionLocator],
|
@@ -50,6 +50,7 @@ from deltacat.compute.compactor_v2.steps import merge as mg
|
|
50
50
|
from deltacat.compute.compactor_v2.steps import hash_bucket as hb
|
51
51
|
from deltacat.compute.compactor_v2.utils import io
|
52
52
|
from deltacat.compute.compactor.utils import round_completion_file as rcf
|
53
|
+
from deltacat.utils.metrics import metrics
|
53
54
|
|
54
55
|
from typing import List, Optional, Tuple
|
55
56
|
from collections import defaultdict
|
@@ -65,7 +66,6 @@ from deltacat.compute.compactor_v2.utils.task_options import (
|
|
65
66
|
local_merge_resource_options_provider,
|
66
67
|
)
|
67
68
|
from deltacat.compute.compactor.model.compactor_version import CompactorVersion
|
68
|
-
from deltacat.utils.metrics import MetricsActor, METRICS_CONFIG_ACTOR_NAME
|
69
69
|
|
70
70
|
if importlib.util.find_spec("memray"):
|
71
71
|
import memray
|
@@ -74,6 +74,7 @@ if importlib.util.find_spec("memray"):
|
|
74
74
|
logger = logs.configure_deltacat_logger(logging.getLogger(__name__))
|
75
75
|
|
76
76
|
|
77
|
+
@metrics
|
77
78
|
def compact_partition(params: CompactPartitionParams, **kwargs) -> Optional[str]:
|
78
79
|
|
79
80
|
assert (
|
@@ -119,15 +120,6 @@ def _execute_compaction(
|
|
119
120
|
params: CompactPartitionParams, **kwargs
|
120
121
|
) -> Tuple[Optional[Partition], Optional[RoundCompletionInfo], Optional[str]]:
|
121
122
|
|
122
|
-
if params.metrics_config:
|
123
|
-
logger.info(
|
124
|
-
f"Setting metrics config with target: {params.metrics_config.metrics_target}"
|
125
|
-
)
|
126
|
-
metrics_actor = MetricsActor.options(
|
127
|
-
name=METRICS_CONFIG_ACTOR_NAME, get_if_exists=True
|
128
|
-
).remote()
|
129
|
-
ray.get(metrics_actor.set_metrics_config.remote(params.metrics_config))
|
130
|
-
|
131
123
|
rcf_source_partition_locator = (
|
132
124
|
params.rebase_source_partition_locator or params.source_partition_locator
|
133
125
|
)
|
@@ -31,14 +31,11 @@ from deltacat.compute.compactor_v2.deletes.delete_strategy import (
|
|
31
31
|
from deltacat.compute.compactor_v2.deletes.delete_file_envelope import (
|
32
32
|
DeleteFileEnvelope,
|
33
33
|
)
|
34
|
-
from deltacat.utils.metrics import metrics
|
35
|
-
from deltacat.compute.compactor_v2.constants import MATERIALIZE_METRIC_PREFIX
|
36
34
|
|
37
35
|
|
38
36
|
logger = logs.configure_deltacat_logger(logging.getLogger(__name__))
|
39
37
|
|
40
38
|
|
41
|
-
@metrics(prefix=MATERIALIZE_METRIC_PREFIX)
|
42
39
|
def materialize(
|
43
40
|
input: MergeInput,
|
44
41
|
task_index: int,
|
deltacat/logs.py
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
import logging
|
2
2
|
import os
|
3
|
+
import json
|
3
4
|
import pathlib
|
4
5
|
from logging import FileHandler, Handler, Logger, LoggerAdapter, handlers
|
5
6
|
from typing import Any, Dict, Optional, Union
|
@@ -19,13 +20,106 @@ from deltacat.constants import (
|
|
19
20
|
)
|
20
21
|
|
21
22
|
DEFAULT_LOG_LEVEL = "INFO"
|
22
|
-
DEFAULT_LOG_FORMAT =
|
23
|
-
"
|
24
|
-
|
23
|
+
DEFAULT_LOG_FORMAT = {
|
24
|
+
"level": "levelname",
|
25
|
+
"message": "message",
|
26
|
+
"loggerName": "name",
|
27
|
+
"processName": "processName",
|
28
|
+
"processID": "process",
|
29
|
+
"threadName": "threadName",
|
30
|
+
"timestamp": "asctime",
|
31
|
+
"filename": "filename",
|
32
|
+
"lineno": "lineno",
|
33
|
+
}
|
25
34
|
DEFAULT_MAX_BYTES_PER_LOG = 2 ^ 20 * 256 # 256 MiB
|
26
35
|
DEFAULT_BACKUP_COUNT = 0
|
27
36
|
|
28
37
|
|
38
|
+
class JsonFormatter(logging.Formatter):
|
39
|
+
"""
|
40
|
+
Formatter that outputs JSON strings after parsing the LogRecord.
|
41
|
+
|
42
|
+
@param dict fmt_dict: Key: logging format attribute pairs. Defaults to {"message": "message"}.
|
43
|
+
@param str time_format: time.strftime() format string. Default: "%Y-%m-%dT%H:%M:%S"
|
44
|
+
@param str msec_format: Microsecond formatting. Appended at the end. Default: "%s.%03dZ"
|
45
|
+
"""
|
46
|
+
|
47
|
+
def __init__(
|
48
|
+
self,
|
49
|
+
fmt_dict: dict = None,
|
50
|
+
time_format: str = "%Y-%m-%dT%H:%M:%S",
|
51
|
+
msec_format: str = "%s.%03dZ",
|
52
|
+
):
|
53
|
+
self.fmt_dict = fmt_dict if fmt_dict is not None else {"message": "message"}
|
54
|
+
self.default_time_format = time_format
|
55
|
+
self.default_msec_format = msec_format
|
56
|
+
self.datefmt = None
|
57
|
+
if ray.is_initialized():
|
58
|
+
self.ray_runtime_ctx: RuntimeContext = ray.get_runtime_context()
|
59
|
+
self.context = {}
|
60
|
+
self.context["worker_id"] = self.ray_runtime_ctx.get_worker_id()
|
61
|
+
self.context["node_id"] = self.ray_runtime_ctx.get_node_id()
|
62
|
+
self.context["job_id"] = self.ray_runtime_ctx.get_job_id()
|
63
|
+
else:
|
64
|
+
self.ray_runtime_ctx = None
|
65
|
+
self.context = {}
|
66
|
+
|
67
|
+
def usesTime(self) -> bool:
|
68
|
+
"""
|
69
|
+
Overwritten to look for the attribute in the format dict values instead of the fmt string.
|
70
|
+
"""
|
71
|
+
return "asctime" in self.fmt_dict.values()
|
72
|
+
|
73
|
+
def formatMessage(self, record) -> dict:
|
74
|
+
"""
|
75
|
+
Overwritten to return a dictionary of the relevant LogRecord attributes instead of a string.
|
76
|
+
KeyError is raised if an unknown attribute is provided in the fmt_dict.
|
77
|
+
"""
|
78
|
+
return {
|
79
|
+
fmt_key: record.__dict__[fmt_val]
|
80
|
+
for fmt_key, fmt_val in self.fmt_dict.items()
|
81
|
+
}
|
82
|
+
|
83
|
+
def format(self, record) -> str:
|
84
|
+
"""
|
85
|
+
Mostly the same as the parent's class method, the difference being that a dict is manipulated and dumped as JSON
|
86
|
+
instead of a string.
|
87
|
+
"""
|
88
|
+
record.message = record.getMessage()
|
89
|
+
|
90
|
+
if self.usesTime():
|
91
|
+
record.asctime = self.formatTime(record, self.datefmt)
|
92
|
+
|
93
|
+
message_dict = self.formatMessage(record)
|
94
|
+
|
95
|
+
if record.exc_info:
|
96
|
+
# Cache the traceback text to avoid converting it multiple times
|
97
|
+
# (it's constant anyway)
|
98
|
+
if not record.exc_text:
|
99
|
+
record.exc_text = self.formatException(record.exc_info)
|
100
|
+
|
101
|
+
if record.exc_text:
|
102
|
+
message_dict["exc_info"] = record.exc_text
|
103
|
+
|
104
|
+
if record.stack_info:
|
105
|
+
message_dict["stack_info"] = self.formatStack(record.stack_info)
|
106
|
+
|
107
|
+
if self.ray_runtime_ctx:
|
108
|
+
# only workers will have task ID
|
109
|
+
if (
|
110
|
+
self.ray_runtime_ctx.worker
|
111
|
+
and self.ray_runtime_ctx.worker.mode == ray._private.worker.WORKER_MODE
|
112
|
+
):
|
113
|
+
self.context["task_id"] = self.ray_runtime_ctx.get_task_id()
|
114
|
+
self.context[
|
115
|
+
"assigned_resources"
|
116
|
+
] = self.ray_runtime_ctx.get_assigned_resources()
|
117
|
+
|
118
|
+
message_dict["ray_runtime_context"] = self.context
|
119
|
+
|
120
|
+
return json.dumps(message_dict, default=str)
|
121
|
+
|
122
|
+
|
29
123
|
class DeltaCATLoggerAdapter(logging.LoggerAdapter):
|
30
124
|
"""
|
31
125
|
Logger Adapter class with additional functionality
|
@@ -51,54 +145,6 @@ class DeltaCATLoggerAdapter(logging.LoggerAdapter):
|
|
51
145
|
self.error(msg, *args, **kwargs)
|
52
146
|
|
53
147
|
|
54
|
-
class RayRuntimeContextLoggerAdapter(DeltaCATLoggerAdapter):
|
55
|
-
"""
|
56
|
-
Logger Adapter for injecting Ray Runtime Context into logging messages.
|
57
|
-
"""
|
58
|
-
|
59
|
-
def __init__(self, logger: Logger, runtime_context: RuntimeContext):
|
60
|
-
super().__init__(logger, {})
|
61
|
-
self.runtime_context = runtime_context
|
62
|
-
|
63
|
-
def process(self, msg, kwargs):
|
64
|
-
"""
|
65
|
-
Injects Ray Runtime Context details into each log message.
|
66
|
-
|
67
|
-
This may include information such as the raylet node ID, task/actor ID, job ID,
|
68
|
-
placement group ID of the worker, and assigned resources to the task/actor.
|
69
|
-
|
70
|
-
Args:
|
71
|
-
msg: The original log message
|
72
|
-
kwargs: Keyword arguments for the log message
|
73
|
-
|
74
|
-
Returns: A log message with Ray Runtime Context details
|
75
|
-
|
76
|
-
"""
|
77
|
-
runtime_context_dict = self.runtime_context.get()
|
78
|
-
runtime_context_dict[
|
79
|
-
"worker_id"
|
80
|
-
] = self.runtime_context.worker.core_worker.get_worker_id()
|
81
|
-
if self.runtime_context.get_task_id() or self.runtime_context.get_actor_id():
|
82
|
-
runtime_context_dict[
|
83
|
-
"pg_id"
|
84
|
-
] = self.runtime_context.get_placement_group_id()
|
85
|
-
runtime_context_dict[
|
86
|
-
"assigned_resources"
|
87
|
-
] = self.runtime_context.get_assigned_resources()
|
88
|
-
|
89
|
-
return "(ray_runtime_context=%s) -- %s" % (runtime_context_dict, msg), kwargs
|
90
|
-
|
91
|
-
def __reduce__(self):
|
92
|
-
"""
|
93
|
-
Used to unpickle the class during Ray object store transfer.
|
94
|
-
"""
|
95
|
-
|
96
|
-
def deserializer(*args):
|
97
|
-
return RayRuntimeContextLoggerAdapter(args[0], ray.get_runtime_context())
|
98
|
-
|
99
|
-
return deserializer, (self.logger,)
|
100
|
-
|
101
|
-
|
102
148
|
def _add_logger_handler(logger: Logger, handler: Handler) -> Logger:
|
103
149
|
|
104
150
|
logger.setLevel(logging.getLevelName("DEBUG"))
|
@@ -109,10 +155,10 @@ def _add_logger_handler(logger: Logger, handler: Handler) -> Logger:
|
|
109
155
|
def _create_rotating_file_handler(
|
110
156
|
log_directory: str,
|
111
157
|
log_base_file_name: str,
|
112
|
-
logging_level: str = DEFAULT_LOG_LEVEL,
|
158
|
+
logging_level: Union[str, int] = DEFAULT_LOG_LEVEL,
|
113
159
|
max_bytes_per_log_file: int = DEFAULT_MAX_BYTES_PER_LOG,
|
114
160
|
backup_count: int = DEFAULT_BACKUP_COUNT,
|
115
|
-
logging_format: str = DEFAULT_LOG_FORMAT,
|
161
|
+
logging_format: Union[str, dict] = DEFAULT_LOG_FORMAT,
|
116
162
|
) -> FileHandler:
|
117
163
|
|
118
164
|
if type(logging_level) is str:
|
@@ -126,7 +172,12 @@ def _create_rotating_file_handler(
|
|
126
172
|
maxBytes=max_bytes_per_log_file,
|
127
173
|
backupCount=backup_count,
|
128
174
|
)
|
129
|
-
|
175
|
+
|
176
|
+
if type(logging_format) is str:
|
177
|
+
handler.setFormatter(logging.Formatter(logging_format))
|
178
|
+
else:
|
179
|
+
handler.setFormatter(JsonFormatter(logging_format))
|
180
|
+
|
130
181
|
handler.setLevel(logging_level)
|
131
182
|
return handler
|
132
183
|
|
@@ -135,7 +186,8 @@ def _file_handler_exists(logger: Logger, log_dir: str, log_base_file_name: str)
|
|
135
186
|
|
136
187
|
handler_exists = False
|
137
188
|
base_file_path = os.path.join(log_dir, log_base_file_name)
|
138
|
-
|
189
|
+
|
190
|
+
if logger.handlers:
|
139
191
|
norm_base_file_path = os.path.normpath(base_file_path)
|
140
192
|
handler_exists = any(
|
141
193
|
[
|
@@ -149,49 +201,54 @@ def _file_handler_exists(logger: Logger, log_dir: str, log_base_file_name: str)
|
|
149
201
|
|
150
202
|
def _configure_logger(
|
151
203
|
logger: Logger,
|
152
|
-
log_level:
|
204
|
+
log_level: int,
|
153
205
|
log_dir: str,
|
154
206
|
log_base_file_name: str,
|
155
207
|
debug_log_base_file_name: str,
|
156
208
|
) -> Union[Logger, LoggerAdapter]:
|
209
|
+
# This maintains log level of rotating file handlers
|
157
210
|
primary_log_level = log_level
|
158
211
|
logger.propagate = False
|
159
|
-
if log_level.
|
212
|
+
if log_level <= logging.getLevelName("DEBUG"):
|
160
213
|
if not _file_handler_exists(logger, log_dir, debug_log_base_file_name):
|
161
214
|
handler = _create_rotating_file_handler(
|
162
215
|
log_dir, debug_log_base_file_name, "DEBUG"
|
163
216
|
)
|
164
217
|
_add_logger_handler(logger, handler)
|
165
|
-
primary_log_level = "INFO"
|
218
|
+
primary_log_level = logging.getLevelName("INFO")
|
166
219
|
if not _file_handler_exists(logger, log_dir, log_base_file_name):
|
167
220
|
handler = _create_rotating_file_handler(
|
168
221
|
log_dir, log_base_file_name, primary_log_level
|
169
222
|
)
|
170
223
|
_add_logger_handler(logger, handler)
|
171
|
-
if ray.is_initialized():
|
172
|
-
ray_runtime_ctx = ray.get_runtime_context()
|
173
|
-
if ray_runtime_ctx.worker.connected:
|
174
|
-
logger = RayRuntimeContextLoggerAdapter(logger, ray_runtime_ctx)
|
175
|
-
else:
|
176
|
-
logger = DeltaCATLoggerAdapter(logger)
|
177
224
|
|
178
|
-
return logger
|
225
|
+
return DeltaCATLoggerAdapter(logger)
|
226
|
+
|
179
227
|
|
228
|
+
def configure_deltacat_logger(
|
229
|
+
logger: Logger, level: int = None
|
230
|
+
) -> Union[Logger, LoggerAdapter]:
|
231
|
+
if level is None:
|
232
|
+
level = logging.getLevelName(DELTACAT_SYS_LOG_LEVEL)
|
180
233
|
|
181
|
-
def configure_deltacat_logger(logger: Logger) -> Union[Logger, LoggerAdapter]:
|
182
234
|
return _configure_logger(
|
183
235
|
logger,
|
184
|
-
|
236
|
+
level,
|
185
237
|
DELTACAT_SYS_LOG_DIR,
|
186
238
|
DELTACAT_SYS_INFO_LOG_BASE_FILE_NAME,
|
187
239
|
DELTACAT_SYS_DEBUG_LOG_BASE_FILE_NAME,
|
188
240
|
)
|
189
241
|
|
190
242
|
|
191
|
-
def configure_application_logger(
|
243
|
+
def configure_application_logger(
|
244
|
+
logger: Logger, level: int = None
|
245
|
+
) -> Union[Logger, LoggerAdapter]:
|
246
|
+
if level is None:
|
247
|
+
level = logging.getLevelName(DELTACAT_APP_LOG_LEVEL)
|
248
|
+
|
192
249
|
return _configure_logger(
|
193
250
|
logger,
|
194
|
-
|
251
|
+
level,
|
195
252
|
DELTACAT_APP_LOG_DIR,
|
196
253
|
DELTACAT_APP_INFO_LOG_BASE_FILE_NAME,
|
197
254
|
DELTACAT_APP_DEBUG_LOG_BASE_FILE_NAME,
|
@@ -0,0 +1,12 @@
|
|
1
|
+
import unittest
|
2
|
+
from deltacat.aws.s3u import UuidBlockWritePathProvider, CapturedBlockWritePaths
|
3
|
+
|
4
|
+
|
5
|
+
class TestUuidBlockWritePathProvider(unittest.TestCase):
|
6
|
+
def test_uuid_block_write_provider_sanity(self):
|
7
|
+
capture_object = CapturedBlockWritePaths()
|
8
|
+
provider = UuidBlockWritePathProvider(capture_object=capture_object)
|
9
|
+
|
10
|
+
result = provider("base_path")
|
11
|
+
|
12
|
+
self.assertRegex(result, r"^base_path/[\w-]{36}$")
|
@@ -0,0 +1,127 @@
|
|
1
|
+
import unittest
|
2
|
+
import json
|
3
|
+
import ray
|
4
|
+
from logging import LogRecord
|
5
|
+
from deltacat.logs import JsonFormatter
|
6
|
+
|
7
|
+
|
8
|
+
class TestJsonFormatter(unittest.TestCase):
|
9
|
+
def test_usesTime_sanity(self):
|
10
|
+
|
11
|
+
formatter = JsonFormatter()
|
12
|
+
|
13
|
+
self.assertFalse(formatter.usesTime())
|
14
|
+
|
15
|
+
def test_usesTime_success_case(self):
|
16
|
+
|
17
|
+
formatter = JsonFormatter(fmt_dict={"asctime": "asctime"})
|
18
|
+
|
19
|
+
self.assertTrue(formatter.usesTime())
|
20
|
+
|
21
|
+
def test_formatMessage_sanity(self):
|
22
|
+
|
23
|
+
formatter = JsonFormatter({"message": "msg"})
|
24
|
+
|
25
|
+
record = LogRecord(
|
26
|
+
level="INFO",
|
27
|
+
name="test",
|
28
|
+
pathname="test",
|
29
|
+
lineno=0,
|
30
|
+
message="test_message",
|
31
|
+
msg="test_message",
|
32
|
+
args=None,
|
33
|
+
exc_info=None,
|
34
|
+
)
|
35
|
+
|
36
|
+
result = formatter.formatMessage(record)
|
37
|
+
|
38
|
+
self.assertEqual({"message": "test_message"}, result)
|
39
|
+
|
40
|
+
def test_format_sanity(self):
|
41
|
+
formatter = JsonFormatter({"message": "msg"})
|
42
|
+
|
43
|
+
record = LogRecord(
|
44
|
+
level="INFO",
|
45
|
+
name="test",
|
46
|
+
pathname="test",
|
47
|
+
lineno=0,
|
48
|
+
message="test_message",
|
49
|
+
msg="test_message",
|
50
|
+
args=None,
|
51
|
+
exc_info=None,
|
52
|
+
)
|
53
|
+
|
54
|
+
result = formatter.format(record)
|
55
|
+
|
56
|
+
self.assertEqual({"message": "test_message"}, json.loads(result))
|
57
|
+
self.assertFalse(ray.is_initialized())
|
58
|
+
self.assertNotIn("ray_runtime_context", json.loads(result))
|
59
|
+
|
60
|
+
def test_format_when_ray_initialized(self):
|
61
|
+
ray.init(local_mode=True, ignore_reinit_error=True)
|
62
|
+
|
63
|
+
formatter = JsonFormatter({"message": "msg"})
|
64
|
+
|
65
|
+
record = LogRecord(
|
66
|
+
level="INFO",
|
67
|
+
name="test",
|
68
|
+
pathname="test",
|
69
|
+
lineno=0,
|
70
|
+
message="test_message",
|
71
|
+
msg="test_message",
|
72
|
+
args=None,
|
73
|
+
exc_info=None,
|
74
|
+
)
|
75
|
+
|
76
|
+
result = formatter.format(record)
|
77
|
+
result = json.loads(result)
|
78
|
+
|
79
|
+
self.assertEqual("test_message", result["message"])
|
80
|
+
self.assertTrue(ray.is_initialized())
|
81
|
+
self.assertIn("ray_runtime_context", result)
|
82
|
+
self.assertIn("job_id", result["ray_runtime_context"])
|
83
|
+
self.assertIn("node_id", result["ray_runtime_context"])
|
84
|
+
self.assertIn("worker_id", result["ray_runtime_context"])
|
85
|
+
self.assertNotIn(
|
86
|
+
"task_id",
|
87
|
+
result["ray_runtime_context"],
|
88
|
+
"We expect task ID not be present outside a remote task",
|
89
|
+
)
|
90
|
+
ray.shutdown()
|
91
|
+
|
92
|
+
def test_format_when_ray_initialized_in_task(self):
|
93
|
+
# worker mode is only true when local_mode is False
|
94
|
+
ray.init(local_mode=False, ignore_reinit_error=True)
|
95
|
+
|
96
|
+
@ray.remote
|
97
|
+
def ray_remote_task():
|
98
|
+
formatter = JsonFormatter({"message": "msg"})
|
99
|
+
|
100
|
+
record = LogRecord(
|
101
|
+
level="INFO",
|
102
|
+
name="test",
|
103
|
+
pathname="test",
|
104
|
+
lineno=0,
|
105
|
+
message="test_message",
|
106
|
+
msg="test_message",
|
107
|
+
args=None,
|
108
|
+
exc_info=None,
|
109
|
+
)
|
110
|
+
|
111
|
+
result = formatter.format(record)
|
112
|
+
result = json.loads(result)
|
113
|
+
return result
|
114
|
+
|
115
|
+
result = ray.get(ray_remote_task.remote())
|
116
|
+
self.assertEqual("test_message", result["message"])
|
117
|
+
self.assertTrue(ray.is_initialized())
|
118
|
+
self.assertIn("ray_runtime_context", result)
|
119
|
+
self.assertIn("job_id", result["ray_runtime_context"])
|
120
|
+
self.assertIn("node_id", result["ray_runtime_context"])
|
121
|
+
self.assertIn("worker_id", result["ray_runtime_context"])
|
122
|
+
self.assertIn(
|
123
|
+
"task_id",
|
124
|
+
result["ray_runtime_context"],
|
125
|
+
"We expect task ID to be present inside a remote task",
|
126
|
+
)
|
127
|
+
ray.shutdown()
|
@@ -1,13 +1,11 @@
|
|
1
1
|
import unittest
|
2
2
|
from unittest.mock import MagicMock, ANY, call
|
3
|
-
import ray
|
4
3
|
from deltacat.utils.metrics import (
|
5
4
|
metrics,
|
6
5
|
success_metric,
|
7
6
|
failure_metric,
|
8
7
|
latency_metric,
|
9
|
-
|
10
|
-
METRICS_CONFIG_ACTOR_NAME,
|
8
|
+
MetricsConfigCache,
|
11
9
|
MetricsConfig,
|
12
10
|
MetricsTarget,
|
13
11
|
METRICS_TARGET_TO_EMITTER_DICT,
|
@@ -43,11 +41,8 @@ class TestMetricsAnnotation(unittest.TestCase):
|
|
43
41
|
def test_metrics_annotation_sanity(self):
|
44
42
|
mock, mock_target = MagicMock(), MagicMock()
|
45
43
|
METRICS_TARGET_TO_EMITTER_DICT[MetricsTarget.NOOP] = mock_target
|
46
|
-
metrics_actor = MetricsActor.options(
|
47
|
-
name=METRICS_CONFIG_ACTOR_NAME, get_if_exists=True
|
48
|
-
).remote()
|
49
44
|
config = MetricsConfig("us-east-1", MetricsTarget.NOOP)
|
50
|
-
|
45
|
+
MetricsConfigCache.metrics_config = config
|
51
46
|
|
52
47
|
# action
|
53
48
|
metrics_annotated_method(mock)
|
@@ -73,11 +68,8 @@ class TestMetricsAnnotation(unittest.TestCase):
|
|
73
68
|
def test_metrics_annotation_when_error(self):
|
74
69
|
mock, mock_target = MagicMock(), MagicMock()
|
75
70
|
METRICS_TARGET_TO_EMITTER_DICT[MetricsTarget.NOOP] = mock_target
|
76
|
-
metrics_actor = MetricsActor.options(
|
77
|
-
name=METRICS_CONFIG_ACTOR_NAME, get_if_exists=True
|
78
|
-
).remote()
|
79
71
|
config = MetricsConfig("us-east-1", MetricsTarget.NOOP)
|
80
|
-
|
72
|
+
MetricsConfigCache.metrics_config = config
|
81
73
|
|
82
74
|
# action
|
83
75
|
self.assertRaises(ValueError, lambda: metrics_annotated_method_error(mock))
|
@@ -108,11 +100,8 @@ class TestMetricsAnnotation(unittest.TestCase):
|
|
108
100
|
def test_metrics_with_prefix_annotation_sanity(self):
|
109
101
|
mock, mock_target = MagicMock(), MagicMock()
|
110
102
|
METRICS_TARGET_TO_EMITTER_DICT[MetricsTarget.NOOP] = mock_target
|
111
|
-
metrics_actor = MetricsActor.options(
|
112
|
-
name=METRICS_CONFIG_ACTOR_NAME, get_if_exists=True
|
113
|
-
).remote()
|
114
103
|
config = MetricsConfig("us-east-1", MetricsTarget.NOOP)
|
115
|
-
|
104
|
+
MetricsConfigCache.metrics_config = config
|
116
105
|
|
117
106
|
# action
|
118
107
|
metrics_with_prefix_annotated_method(mock)
|
@@ -134,11 +123,8 @@ class TestMetricsAnnotation(unittest.TestCase):
|
|
134
123
|
def test_metrics_annotation_performance(self):
|
135
124
|
mock, mock_target = MagicMock(), MagicMock()
|
136
125
|
METRICS_TARGET_TO_EMITTER_DICT[MetricsTarget.NOOP] = mock_target
|
137
|
-
metrics_actor = MetricsActor.options(
|
138
|
-
name=METRICS_CONFIG_ACTOR_NAME, get_if_exists=True
|
139
|
-
).remote()
|
140
126
|
config = MetricsConfig("us-east-1", MetricsTarget.NOOP)
|
141
|
-
|
127
|
+
MetricsConfigCache.metrics_config = config
|
142
128
|
|
143
129
|
# action with annotation
|
144
130
|
_, actual_latency = timed_invocation(metrics_annotated_method, mock)
|
@@ -155,11 +141,8 @@ class TestMetricsAnnotation(unittest.TestCase):
|
|
155
141
|
def test_metrics_with_prefix_annotation_when_error(self):
|
156
142
|
mock, mock_target = MagicMock(), MagicMock()
|
157
143
|
METRICS_TARGET_TO_EMITTER_DICT[MetricsTarget.NOOP] = mock_target
|
158
|
-
metrics_actor = MetricsActor.options(
|
159
|
-
name=METRICS_CONFIG_ACTOR_NAME, get_if_exists=True
|
160
|
-
).remote()
|
161
144
|
config = MetricsConfig("us-east-1", MetricsTarget.NOOP)
|
162
|
-
|
145
|
+
MetricsConfigCache.metrics_config = config
|
163
146
|
|
164
147
|
# action
|
165
148
|
self.assertRaises(
|
@@ -185,15 +168,10 @@ class TestMetricsAnnotation(unittest.TestCase):
|
|
185
168
|
any_order=True,
|
186
169
|
)
|
187
170
|
|
188
|
-
def
|
171
|
+
def test_metrics_with_prefix_annotation_without_config(self):
|
189
172
|
mock, mock_target = MagicMock(), MagicMock()
|
190
173
|
METRICS_TARGET_TO_EMITTER_DICT[MetricsTarget.NOOP] = mock_target
|
191
|
-
|
192
|
-
name=METRICS_CONFIG_ACTOR_NAME, get_if_exists=True
|
193
|
-
).remote()
|
194
|
-
|
195
|
-
# explicitly making sure actor is killed
|
196
|
-
ray.kill(metrics_actor)
|
174
|
+
MetricsConfigCache.metrics_config = None
|
197
175
|
|
198
176
|
# action
|
199
177
|
self.assertRaises(
|
@@ -228,11 +206,8 @@ class TestLatencyMetricAnnotation(unittest.TestCase):
|
|
228
206
|
def test_annotation_sanity(self):
|
229
207
|
mock, mock_target = MagicMock(), MagicMock()
|
230
208
|
METRICS_TARGET_TO_EMITTER_DICT[MetricsTarget.NOOP] = mock_target
|
231
|
-
metrics_actor = MetricsActor.options(
|
232
|
-
name=METRICS_CONFIG_ACTOR_NAME, get_if_exists=True
|
233
|
-
).remote()
|
234
209
|
config = MetricsConfig("us-east-1", MetricsTarget.NOOP)
|
235
|
-
|
210
|
+
MetricsConfigCache.metrics_config = config
|
236
211
|
|
237
212
|
# action
|
238
213
|
latency_metric_annotated_method(mock)
|
@@ -253,11 +228,8 @@ class TestLatencyMetricAnnotation(unittest.TestCase):
|
|
253
228
|
def test_annotation_when_error(self):
|
254
229
|
mock, mock_target = MagicMock(), MagicMock()
|
255
230
|
METRICS_TARGET_TO_EMITTER_DICT[MetricsTarget.NOOP] = mock_target
|
256
|
-
metrics_actor = MetricsActor.options(
|
257
|
-
name=METRICS_CONFIG_ACTOR_NAME, get_if_exists=True
|
258
|
-
).remote()
|
259
231
|
config = MetricsConfig("us-east-1", MetricsTarget.NOOP)
|
260
|
-
|
232
|
+
MetricsConfigCache.metrics_config = config
|
261
233
|
|
262
234
|
# action
|
263
235
|
self.assertRaises(
|
@@ -280,11 +252,8 @@ class TestLatencyMetricAnnotation(unittest.TestCase):
|
|
280
252
|
def test_annotation_with_args_sanity(self):
|
281
253
|
mock, mock_target = MagicMock(), MagicMock()
|
282
254
|
METRICS_TARGET_TO_EMITTER_DICT[MetricsTarget.NOOP] = mock_target
|
283
|
-
metrics_actor = MetricsActor.options(
|
284
|
-
name=METRICS_CONFIG_ACTOR_NAME, get_if_exists=True
|
285
|
-
).remote()
|
286
255
|
config = MetricsConfig("us-east-1", MetricsTarget.NOOP)
|
287
|
-
|
256
|
+
MetricsConfigCache.metrics_config = config
|
288
257
|
|
289
258
|
# action
|
290
259
|
latency_metric_with_name_annotated_method(mock)
|
@@ -298,11 +267,8 @@ class TestLatencyMetricAnnotation(unittest.TestCase):
|
|
298
267
|
def test_annotation_with_args_when_error(self):
|
299
268
|
mock, mock_target = MagicMock(), MagicMock()
|
300
269
|
METRICS_TARGET_TO_EMITTER_DICT[MetricsTarget.NOOP] = mock_target
|
301
|
-
metrics_actor = MetricsActor.options(
|
302
|
-
name=METRICS_CONFIG_ACTOR_NAME, get_if_exists=True
|
303
|
-
).remote()
|
304
270
|
config = MetricsConfig("us-east-1", MetricsTarget.NOOP)
|
305
|
-
|
271
|
+
MetricsConfigCache.metrics_config = config
|
306
272
|
|
307
273
|
# action
|
308
274
|
self.assertRaises(
|
@@ -315,15 +281,10 @@ class TestLatencyMetricAnnotation(unittest.TestCase):
|
|
315
281
|
[call(metrics_name="test", metrics_config=ANY, value=ANY)], any_order=True
|
316
282
|
)
|
317
283
|
|
318
|
-
def
|
284
|
+
def test_annotation_without_config(self):
|
319
285
|
mock, mock_target = MagicMock(), MagicMock()
|
320
286
|
METRICS_TARGET_TO_EMITTER_DICT[MetricsTarget.NOOP] = mock_target
|
321
|
-
|
322
|
-
name=METRICS_CONFIG_ACTOR_NAME, get_if_exists=True
|
323
|
-
).remote()
|
324
|
-
|
325
|
-
# explicitly making sure actor is killed
|
326
|
-
ray.kill(metrics_actor)
|
287
|
+
MetricsConfigCache.metrics_config = None
|
327
288
|
|
328
289
|
# action
|
329
290
|
self.assertRaises(
|
@@ -358,11 +319,8 @@ class TestSuccessMetricAnnotation(unittest.TestCase):
|
|
358
319
|
def test_annotation_sanity(self):
|
359
320
|
mock, mock_target = MagicMock(), MagicMock()
|
360
321
|
METRICS_TARGET_TO_EMITTER_DICT[MetricsTarget.NOOP] = mock_target
|
361
|
-
metrics_actor = MetricsActor.options(
|
362
|
-
name=METRICS_CONFIG_ACTOR_NAME, get_if_exists=True
|
363
|
-
).remote()
|
364
322
|
config = MetricsConfig("us-east-1", MetricsTarget.NOOP)
|
365
|
-
|
323
|
+
MetricsConfigCache.metrics_config = config
|
366
324
|
|
367
325
|
# action
|
368
326
|
success_metric_annotated_method(mock)
|
@@ -383,11 +341,8 @@ class TestSuccessMetricAnnotation(unittest.TestCase):
|
|
383
341
|
def test_annotation_when_error(self):
|
384
342
|
mock, mock_target = MagicMock(), MagicMock()
|
385
343
|
METRICS_TARGET_TO_EMITTER_DICT[MetricsTarget.NOOP] = mock_target
|
386
|
-
metrics_actor = MetricsActor.options(
|
387
|
-
name=METRICS_CONFIG_ACTOR_NAME, get_if_exists=True
|
388
|
-
).remote()
|
389
344
|
config = MetricsConfig("us-east-1", MetricsTarget.NOOP)
|
390
|
-
|
345
|
+
MetricsConfigCache.metrics_config = config
|
391
346
|
|
392
347
|
# action
|
393
348
|
self.assertRaises(
|
@@ -400,11 +355,8 @@ class TestSuccessMetricAnnotation(unittest.TestCase):
|
|
400
355
|
def test_annotation_with_args_sanity(self):
|
401
356
|
mock, mock_target = MagicMock(), MagicMock()
|
402
357
|
METRICS_TARGET_TO_EMITTER_DICT[MetricsTarget.NOOP] = mock_target
|
403
|
-
metrics_actor = MetricsActor.options(
|
404
|
-
name=METRICS_CONFIG_ACTOR_NAME, get_if_exists=True
|
405
|
-
).remote()
|
406
358
|
config = MetricsConfig("us-east-1", MetricsTarget.NOOP)
|
407
|
-
|
359
|
+
MetricsConfigCache.metrics_config = config
|
408
360
|
|
409
361
|
# action
|
410
362
|
success_metric_with_name_annotated_method(mock)
|
@@ -418,11 +370,8 @@ class TestSuccessMetricAnnotation(unittest.TestCase):
|
|
418
370
|
def test_annotation_with_args_when_error(self):
|
419
371
|
mock, mock_target = MagicMock(), MagicMock()
|
420
372
|
METRICS_TARGET_TO_EMITTER_DICT[MetricsTarget.NOOP] = mock_target
|
421
|
-
metrics_actor = MetricsActor.options(
|
422
|
-
name=METRICS_CONFIG_ACTOR_NAME, get_if_exists=True
|
423
|
-
).remote()
|
424
373
|
config = MetricsConfig("us-east-1", MetricsTarget.NOOP)
|
425
|
-
|
374
|
+
MetricsConfigCache.metrics_config = config
|
426
375
|
|
427
376
|
# action
|
428
377
|
self.assertRaises(
|
@@ -432,15 +381,10 @@ class TestSuccessMetricAnnotation(unittest.TestCase):
|
|
432
381
|
mock.assert_not_called()
|
433
382
|
mock_target.assert_not_called()
|
434
383
|
|
435
|
-
def
|
384
|
+
def test_annotation_without_config(self):
|
436
385
|
mock, mock_target = MagicMock(), MagicMock()
|
437
386
|
METRICS_TARGET_TO_EMITTER_DICT[MetricsTarget.NOOP] = mock_target
|
438
|
-
|
439
|
-
name=METRICS_CONFIG_ACTOR_NAME, get_if_exists=True
|
440
|
-
).remote()
|
441
|
-
|
442
|
-
# explicitly making sure actor is killed
|
443
|
-
ray.kill(metrics_actor)
|
387
|
+
MetricsConfigCache.metrics_config = None
|
444
388
|
|
445
389
|
# action
|
446
390
|
success_metric_annotated_method(mock)
|
@@ -473,11 +417,8 @@ class TestFailureMetricAnnotation(unittest.TestCase):
|
|
473
417
|
def test_annotation_sanity(self):
|
474
418
|
mock, mock_target = MagicMock(), MagicMock()
|
475
419
|
METRICS_TARGET_TO_EMITTER_DICT[MetricsTarget.NOOP] = mock_target
|
476
|
-
metrics_actor = MetricsActor.options(
|
477
|
-
name=METRICS_CONFIG_ACTOR_NAME, get_if_exists=True
|
478
|
-
).remote()
|
479
420
|
config = MetricsConfig("us-east-1", MetricsTarget.NOOP)
|
480
|
-
|
421
|
+
MetricsConfigCache.metrics_config = config
|
481
422
|
|
482
423
|
# action
|
483
424
|
failure_metric_annotated_method(mock)
|
@@ -488,11 +429,8 @@ class TestFailureMetricAnnotation(unittest.TestCase):
|
|
488
429
|
def test_annotation_when_error(self):
|
489
430
|
mock, mock_target = MagicMock(), MagicMock()
|
490
431
|
METRICS_TARGET_TO_EMITTER_DICT[MetricsTarget.NOOP] = mock_target
|
491
|
-
metrics_actor = MetricsActor.options(
|
492
|
-
name=METRICS_CONFIG_ACTOR_NAME, get_if_exists=True
|
493
|
-
).remote()
|
494
432
|
config = MetricsConfig("us-east-1", MetricsTarget.NOOP)
|
495
|
-
|
433
|
+
MetricsConfigCache.metrics_config = config
|
496
434
|
|
497
435
|
# action
|
498
436
|
self.assertRaises(
|
@@ -520,11 +458,8 @@ class TestFailureMetricAnnotation(unittest.TestCase):
|
|
520
458
|
def test_annotation_with_args_sanity(self):
|
521
459
|
mock, mock_target = MagicMock(), MagicMock()
|
522
460
|
METRICS_TARGET_TO_EMITTER_DICT[MetricsTarget.NOOP] = mock_target
|
523
|
-
metrics_actor = MetricsActor.options(
|
524
|
-
name=METRICS_CONFIG_ACTOR_NAME, get_if_exists=True
|
525
|
-
).remote()
|
526
461
|
config = MetricsConfig("us-east-1", MetricsTarget.NOOP)
|
527
|
-
|
462
|
+
MetricsConfigCache.metrics_config = config
|
528
463
|
|
529
464
|
# action
|
530
465
|
failure_metric_with_name_annotated_method(mock)
|
@@ -535,11 +470,8 @@ class TestFailureMetricAnnotation(unittest.TestCase):
|
|
535
470
|
def test_annotation_with_args_when_error(self):
|
536
471
|
mock, mock_target = MagicMock(), MagicMock()
|
537
472
|
METRICS_TARGET_TO_EMITTER_DICT[MetricsTarget.NOOP] = mock_target
|
538
|
-
metrics_actor = MetricsActor.options(
|
539
|
-
name=METRICS_CONFIG_ACTOR_NAME, get_if_exists=True
|
540
|
-
).remote()
|
541
473
|
config = MetricsConfig("us-east-1", MetricsTarget.NOOP)
|
542
|
-
|
474
|
+
MetricsConfigCache.metrics_config = config
|
543
475
|
|
544
476
|
# action
|
545
477
|
self.assertRaises(
|
@@ -556,15 +488,10 @@ class TestFailureMetricAnnotation(unittest.TestCase):
|
|
556
488
|
any_order=True,
|
557
489
|
)
|
558
490
|
|
559
|
-
def
|
491
|
+
def test_annotation_without_config(self):
|
560
492
|
mock, mock_target = MagicMock(), MagicMock()
|
561
493
|
METRICS_TARGET_TO_EMITTER_DICT[MetricsTarget.NOOP] = mock_target
|
562
|
-
|
563
|
-
name=METRICS_CONFIG_ACTOR_NAME, get_if_exists=True
|
564
|
-
).remote()
|
565
|
-
|
566
|
-
# explicitly making sure actor is killed
|
567
|
-
ray.kill(metrics_actor)
|
494
|
+
MetricsConfigCache.metrics_config = None
|
568
495
|
|
569
496
|
# action
|
570
497
|
self.assertRaises(
|
@@ -0,0 +1,25 @@
|
|
1
|
+
import unittest
|
2
|
+
import ray
|
3
|
+
from deltacat.utils.placement import (
|
4
|
+
PlacementGroupManager,
|
5
|
+
_get_available_resources_per_node,
|
6
|
+
)
|
7
|
+
|
8
|
+
|
9
|
+
class TestPlacementGroupManager(unittest.TestCase):
|
10
|
+
@classmethod
|
11
|
+
def setUpClass(cls):
|
12
|
+
super().setUpClass()
|
13
|
+
ray.init(local_mode=True, ignore_reinit_error=True)
|
14
|
+
|
15
|
+
def test_placement_group_manager_sanity(self):
|
16
|
+
|
17
|
+
pgm = PlacementGroupManager(1, 1, 1)
|
18
|
+
|
19
|
+
self.assertIsNotNone(pgm)
|
20
|
+
|
21
|
+
def test_ray_state_api_returns_correctly(self):
|
22
|
+
|
23
|
+
result = _get_available_resources_per_node()
|
24
|
+
|
25
|
+
self.assertIsNotNone(result)
|
deltacat/utils/metrics.py
CHANGED
@@ -2,7 +2,6 @@ from dataclasses import dataclass
|
|
2
2
|
from typing import Optional
|
3
3
|
|
4
4
|
import logging
|
5
|
-
import ray
|
6
5
|
import time
|
7
6
|
import functools
|
8
7
|
|
@@ -22,7 +21,6 @@ logger = logs.configure_deltacat_logger(logging.getLogger(__name__))
|
|
22
21
|
DEFAULT_DELTACAT_METRICS_NAMESPACE = "ray-deltacat-metrics"
|
23
22
|
DEFAULT_DELTACAT_LOG_GROUP_NAME = "ray-deltacat-metrics-EMF-logs"
|
24
23
|
DEFAULT_DELTACAT_LOG_STREAM_CALLABLE = get_node_ip_address
|
25
|
-
METRICS_CONFIG_ACTOR_NAME = "metrics-config-actor"
|
26
24
|
|
27
25
|
|
28
26
|
class MetricsTarget(str, Enum):
|
@@ -187,23 +185,13 @@ METRICS_TARGET_TO_EMITTER_DICT: Dict[str, Callable] = {
|
|
187
185
|
}
|
188
186
|
|
189
187
|
|
190
|
-
|
191
|
-
class MetricsActor:
|
188
|
+
class MetricsConfigCache:
|
192
189
|
metrics_config: MetricsConfig = None
|
193
190
|
|
194
|
-
def set_metrics_config(self, config: MetricsConfig) -> None:
|
195
|
-
self.metrics_config = config
|
196
|
-
|
197
|
-
def get_metrics_config(self) -> MetricsConfig:
|
198
|
-
return self.metrics_config
|
199
|
-
|
200
191
|
|
201
192
|
def _emit_ignore_exceptions(name: Optional[str], value: Any):
|
202
193
|
try:
|
203
|
-
|
204
|
-
name=METRICS_CONFIG_ACTOR_NAME, get_if_exists=True
|
205
|
-
).remote()
|
206
|
-
config = ray.get(config_cache.get_metrics_config.remote())
|
194
|
+
config = MetricsConfigCache.metrics_config
|
207
195
|
if config:
|
208
196
|
_emit_metrics(metrics_name=name, value=value, metrics_config=config)
|
209
197
|
except BaseException as ex:
|
@@ -222,7 +210,14 @@ def emit_timer_metrics(metrics_name, value, metrics_config, **kwargs):
|
|
222
210
|
def latency_metric(original_func=None, name: Optional[str] = None):
|
223
211
|
"""
|
224
212
|
A decorator that emits latency metrics of a function
|
225
|
-
based on configured metrics config.
|
213
|
+
based on configured metrics config. Hence, make sure to set it in all worker processes:
|
214
|
+
|
215
|
+
def setup_cache():
|
216
|
+
from deltacat.utils.metrics import MetricsConfigCache
|
217
|
+
MetricsConfigCache.metrics_config = metrics_config
|
218
|
+
|
219
|
+
setup_cache();
|
220
|
+
ray.init(address="auto", runtime_env={"worker_process_setup_hook": setup_cache})
|
226
221
|
"""
|
227
222
|
|
228
223
|
def _decorate(func):
|
@@ -248,7 +243,14 @@ def latency_metric(original_func=None, name: Optional[str] = None):
|
|
248
243
|
def success_metric(original_func=None, name: Optional[str] = None):
|
249
244
|
"""
|
250
245
|
A decorator that emits success metrics of a function
|
251
|
-
based on configured metrics config.
|
246
|
+
based on configured metrics config. Hence, make sure to set it in all worker processes:
|
247
|
+
|
248
|
+
def setup_cache():
|
249
|
+
from deltacat.utils.metrics import MetricsConfigCache
|
250
|
+
MetricsConfigCache.metrics_config = metrics_config
|
251
|
+
|
252
|
+
setup_cache();
|
253
|
+
ray.init(address="auto", runtime_env={"worker_process_setup_hook": setup_cache})
|
252
254
|
"""
|
253
255
|
|
254
256
|
def _decorate(func):
|
@@ -271,7 +273,14 @@ def success_metric(original_func=None, name: Optional[str] = None):
|
|
271
273
|
def failure_metric(original_func=None, name: Optional[str] = None):
|
272
274
|
"""
|
273
275
|
A decorator that emits failure metrics of a function
|
274
|
-
based on configured metrics config.
|
276
|
+
based on configured metrics config. Hence, make sure to set it in all worker processes:
|
277
|
+
|
278
|
+
def setup_cache():
|
279
|
+
from deltacat.utils.metrics import MetricsConfigCache
|
280
|
+
MetricsConfigCache.metrics_config = metrics_config
|
281
|
+
|
282
|
+
setup_cache();
|
283
|
+
ray.init(address="auto", runtime_env={"worker_process_setup_hook": setup_cache})
|
275
284
|
"""
|
276
285
|
|
277
286
|
def _decorate(func):
|
@@ -301,7 +310,15 @@ def failure_metric(original_func=None, name: Optional[str] = None):
|
|
301
310
|
|
302
311
|
def metrics(original_func=None, prefix: Optional[str] = None):
|
303
312
|
"""
|
304
|
-
A decorator that emits all metrics for a function.
|
313
|
+
A decorator that emits all metrics for a function. This decorator depends
|
314
|
+
on a metrics config. Hence, make sure to set it in all worker processes:
|
315
|
+
|
316
|
+
def setup_cache():
|
317
|
+
from deltacat.utils.metrics import MetricsConfigCache
|
318
|
+
MetricsConfigCache.metrics_config = metrics_config
|
319
|
+
|
320
|
+
setup_cache();
|
321
|
+
ray.init(address="auto", runtime_env={"worker_process_setup_hook": setup_cache})
|
305
322
|
"""
|
306
323
|
|
307
324
|
def _decorate(func):
|
deltacat/utils/placement.py
CHANGED
@@ -2,6 +2,7 @@ import logging
|
|
2
2
|
import re
|
3
3
|
import time
|
4
4
|
from dataclasses import dataclass
|
5
|
+
from packaging.version import Version
|
5
6
|
from typing import Any, Dict, List, Optional, Tuple, Union
|
6
7
|
|
7
8
|
import ray
|
@@ -19,6 +20,16 @@ logger = logs.configure_deltacat_logger(logging.getLogger(__name__))
|
|
19
20
|
# Issue: https://github.com/ray-project/ray/issues/29959
|
20
21
|
|
21
22
|
|
23
|
+
def _get_available_resources_per_node():
|
24
|
+
# This API changed after this commit
|
25
|
+
# https://github.com/ray-project/ray/pull/43252
|
26
|
+
# TODO: Use this method from a durable State API once it's available
|
27
|
+
if Version(ray.__version__) >= Version("2.10.0"):
|
28
|
+
return ray._private.state.available_resources_per_node()
|
29
|
+
else:
|
30
|
+
return ray._private.state.state._available_resources_per_node()
|
31
|
+
|
32
|
+
|
22
33
|
@dataclass
|
23
34
|
class PlacementGroupConfig:
|
24
35
|
def __init__(self, opts, resource, node_ips):
|
@@ -90,9 +101,7 @@ class NodeGroupManager:
|
|
90
101
|
Returns:
|
91
102
|
group_res: a dict of resources, e.g., {'CPU':0,'memory':0,'object_store_memory':0}
|
92
103
|
"""
|
93
|
-
all_available_resources = (
|
94
|
-
ray._private.state.state._available_resources_per_node()
|
95
|
-
)
|
104
|
+
all_available_resources = _get_available_resources_per_node()
|
96
105
|
group_keys = [x[0] for x in self.init_groups]
|
97
106
|
group_res = {}
|
98
107
|
for k in group_keys:
|
@@ -127,9 +136,7 @@ class NodeGroupManager:
|
|
127
136
|
Returns:
|
128
137
|
group_res: dict of updated resource(cpu, memory, object store memory) for a given group
|
129
138
|
"""
|
130
|
-
all_available_resources = (
|
131
|
-
ray._private.state.state._available_resources_per_node()
|
132
|
-
)
|
139
|
+
all_available_resources = _get_available_resources_per_node()
|
133
140
|
group_res = {"CPU": 0, "memory": 0, "object_store_memory": 0, "node_id": []}
|
134
141
|
for v in all_available_resources.values():
|
135
142
|
keys = v.keys()
|
@@ -285,7 +292,7 @@ def _config(
|
|
285
292
|
for bd in bundles:
|
286
293
|
node_ids.append(bd["node_id"])
|
287
294
|
# query available resources given list of node id
|
288
|
-
all_nodes_available_res =
|
295
|
+
all_nodes_available_res = _get_available_resources_per_node()
|
289
296
|
pg_res = {"CPU": 0, "memory": 0, "object_store_memory": 0}
|
290
297
|
node_ips = []
|
291
298
|
for node_id in node_ids:
|
@@ -1,11 +1,11 @@
|
|
1
|
-
deltacat/__init__.py,sha256=
|
1
|
+
deltacat/__init__.py,sha256=bZ2r6PnxfaWRxylN1GFZYEkxvWqx381U-7XuK3NEjq0,1777
|
2
2
|
deltacat/constants.py,sha256=_6oRI-3yp5c8J1qKGQZrt89I9-ttT_gSSvVsJ0h8Duc,1939
|
3
3
|
deltacat/exceptions.py,sha256=xqZf8CwysNYP2d39pf27OnXGStPREgBgIM-e2Tts-TI,199
|
4
|
-
deltacat/logs.py,sha256=
|
4
|
+
deltacat/logs.py,sha256=6g16VkEFidbaMjgenAjggE1r2l664drMVhreRs8B1IQ,8438
|
5
5
|
deltacat/aws/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
6
6
|
deltacat/aws/clients.py,sha256=VgddlV3AEjlBGIFmhhHxokYzwJ-lXnmHAeprVyADduI,6948
|
7
|
-
deltacat/aws/constants.py,sha256=
|
8
|
-
deltacat/aws/s3u.py,sha256=
|
7
|
+
deltacat/aws/constants.py,sha256=aAhOKeLVgtpekA3h9otHUrHqY2bLDWs2QlL7GrdI63g,352
|
8
|
+
deltacat/aws/s3u.py,sha256=lgoE6es6N4xfzwyydxmVspROP1hrNfanB6JqjyBoRb4,24859
|
9
9
|
deltacat/aws/redshift/__init__.py,sha256=7SvjG-dqox8zZUhFicTsUvpG5vXYDl_QQ3ohlHOgTKc,342
|
10
10
|
deltacat/aws/redshift/model/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
11
11
|
deltacat/aws/redshift/model/manifest.py,sha256=ThgpdwzaWz493Zz9e8HSWwuxEheA1nDuypM3pe4vozk,12987
|
@@ -46,12 +46,12 @@ deltacat/compute/compactor/steps/repartition.py,sha256=_ITw4yvvnNv3wwOYxprzlIz5J
|
|
46
46
|
deltacat/compute/compactor/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
47
47
|
deltacat/compute/compactor/utils/io.py,sha256=S-JZdjETP_tHblK4j860jLHyX9S6A87BPz3Rl0jGbRM,17303
|
48
48
|
deltacat/compute/compactor/utils/primary_key_index.py,sha256=ay2-7t4mP9I_l5gKkrv5h5_r8Icts8mBcbH7OJBknrY,2435
|
49
|
-
deltacat/compute/compactor/utils/round_completion_file.py,sha256
|
49
|
+
deltacat/compute/compactor/utils/round_completion_file.py,sha256=-j6ZzhJBDrJ6Vz6WKEC-yKcNElkKRfO6S0P2JdJDQD0,2345
|
50
50
|
deltacat/compute/compactor/utils/sort_key.py,sha256=oK6otg-CSsma6zlGPaKg-KNEvcZRG2NqBlCw1X3_FBc,2397
|
51
51
|
deltacat/compute/compactor/utils/system_columns.py,sha256=CNIgAGos0xAGEpdaQIH7KfbSRrGZgjRbItXMararqXQ,9399
|
52
52
|
deltacat/compute/compactor_v2/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
53
|
-
deltacat/compute/compactor_v2/compaction_session.py,sha256=
|
54
|
-
deltacat/compute/compactor_v2/constants.py,sha256=
|
53
|
+
deltacat/compute/compactor_v2/compaction_session.py,sha256=hC0zde_3jq9W9bO8Z1XwsziK33qGeCFfyqFp1ZRWBJI,25193
|
54
|
+
deltacat/compute/compactor_v2/constants.py,sha256=jGLEK5uS7AcnoVjPGUDIO4ljDbBYZlqzQleKJRKvnZM,2118
|
55
55
|
deltacat/compute/compactor_v2/deletes/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
56
56
|
deltacat/compute/compactor_v2/deletes/delete_file_envelope.py,sha256=AeuH9JRMwp6mvQf6P2cqL92hUEtResQq6qUTS0kIKac,3111
|
57
57
|
deltacat/compute/compactor_v2/deletes/delete_strategy.py,sha256=SMEJOxR-5r92kvKNqtu2w6HmwtmhljcZX1wcNEuS-4w,2833
|
@@ -72,7 +72,7 @@ deltacat/compute/compactor_v2/utils/content_type_params.py,sha256=rNKZisxGrLQOkw
|
|
72
72
|
deltacat/compute/compactor_v2/utils/dedupe.py,sha256=62tFCY2iRP7I3-45GCIYs6_SJsQl8C5lBEr8gbNfbsw,1932
|
73
73
|
deltacat/compute/compactor_v2/utils/delta.py,sha256=8hjkDeIIkSX-gAQ2utQSp2sZcO2tWZHMTxpFusZwBHw,3635
|
74
74
|
deltacat/compute/compactor_v2/utils/io.py,sha256=autXlE3uHICdCCuJoS7mfdeJbRRiz2_xlz-3izlccB4,5264
|
75
|
-
deltacat/compute/compactor_v2/utils/merge.py,sha256=
|
75
|
+
deltacat/compute/compactor_v2/utils/merge.py,sha256=hK4Y7acrtgfvWWTz-fAGznEg6qn6dBYu8blQUQVHhs0,5244
|
76
76
|
deltacat/compute/compactor_v2/utils/primary_key_index.py,sha256=MAscmL35WfwN7Is72aFlD_cGhxtZgjRwwR5kS9Yn2uU,11393
|
77
77
|
deltacat/compute/compactor_v2/utils/task_options.py,sha256=MCY0Sz5NCgNMaY92W8p87FvvDB91mnPQ4AhL8ix3BiA,13780
|
78
78
|
deltacat/compute/merge_on_read/__init__.py,sha256=ckbgngmqPjYBYz_NySsR1vNTOb_hNpeL1sYkZKvBI9M,214
|
@@ -133,8 +133,10 @@ deltacat/storage/model/table.py,sha256=IOu1ZOrdRkVDB-FOxYMRvnNf5TukIDfbdHWTqHYN_
|
|
133
133
|
deltacat/storage/model/table_version.py,sha256=cOM9dN-YB_Hhi4h1CzFbldC5qRkm4C1rQ3rpKIZzCNs,7413
|
134
134
|
deltacat/storage/model/types.py,sha256=hj7MmjjVmKT-R9sMUulOWG-FByGZKKaYXNnOWW32mP0,1608
|
135
135
|
deltacat/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
136
|
+
deltacat/tests/test_logs.py,sha256=6BEMw8VApFg2msFwCAVosz8NWJYATtX5furHyz8UluM,3828
|
136
137
|
deltacat/tests/aws/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
137
138
|
deltacat/tests/aws/test_clients.py,sha256=23GMWfz27WWBDXSqphG9mfputsyS7j3I5P_HRk4YoKE,3790
|
139
|
+
deltacat/tests/aws/test_s3u.py,sha256=QflXbR94o7WobGBm6jhQDK5lJJD2Pd9z2uvi4J7WEJg,437
|
138
140
|
deltacat/tests/catalog/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
139
141
|
deltacat/tests/catalog/test_default_catalog_impl.py,sha256=9srCU5yQ159oZ9_PoJ_mWMzVUW5bKV0mnmPJc5zKCQQ,3125
|
140
142
|
deltacat/tests/compute/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -174,7 +176,8 @@ deltacat/tests/test_utils/utils.py,sha256=a32qEwcSSd1lvRi0aJJ4ZLnc1ZyXmoQF_K95za
|
|
174
176
|
deltacat/tests/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
175
177
|
deltacat/tests/utils/test_cloudpickle.py,sha256=J0pnBY3-PxlUh6MamZAN1PuquKQPr2iyzjiJ7-Rcl0o,1506
|
176
178
|
deltacat/tests/utils/test_daft.py,sha256=Xal84zR42rXsWQI3lImdDYWOzewomKmhmiUQ59m67V0,6488
|
177
|
-
deltacat/tests/utils/test_metrics.py,sha256=
|
179
|
+
deltacat/tests/utils/test_metrics.py,sha256=Ym9nOz1EtB180pLmvugihj1sDTNDMb5opIjjr5Nmcls,16339
|
180
|
+
deltacat/tests/utils/test_placement.py,sha256=g61wVOMkHe4YJeR9Oxg_BOVQ6bhHHbC3IBYv8YhUu94,597
|
178
181
|
deltacat/tests/utils/test_pyarrow.py,sha256=eZAuYp9MUf8lmpIilH57JkURuNsTGZ3IAGC4Gm5hdrM,17307
|
179
182
|
deltacat/tests/utils/test_record_batch_tables.py,sha256=AkG1WyljQmjnl-AxhbFWyo5LnMIKRyLScfgC2B_ES-s,11321
|
180
183
|
deltacat/tests/utils/test_resources.py,sha256=HtpvDrfPZQNtGDXUlsIzc_yd7Vf1cDscZ3YbN0oTvO8,2560
|
@@ -188,11 +191,11 @@ deltacat/utils/arguments.py,sha256=5y1Xz4HSAD8M8Jt83i6gOEKoYjy_fMQe1V43IhIE4hY,1
|
|
188
191
|
deltacat/utils/cloudpickle.py,sha256=XE7YDmQe56ksfl3NdYZkzOAhbHSuhNcBZGOehQpgZr0,1187
|
189
192
|
deltacat/utils/common.py,sha256=RG_-enXNpLKaYrqyx1ne2lL10lxN9vK7F631oJP6SE8,1375
|
190
193
|
deltacat/utils/daft.py,sha256=heg6J8NHnTI1UbcjXvsjGBbFKU6f7mvAio-KZuTSuFI,5506
|
191
|
-
deltacat/utils/metrics.py,sha256=
|
194
|
+
deltacat/utils/metrics.py,sha256=HYKyZSrtVLu8gXezg_TMNUKJp4h1WWI0VEzn0Xlzf-I,10778
|
192
195
|
deltacat/utils/numpy.py,sha256=ZiGREobTVT6IZXgPxkSUpLJFN2Hn8KEZcrqybLDXCIA,2027
|
193
196
|
deltacat/utils/pandas.py,sha256=GfwjYb8FUSEeoBdXZI1_NJkdjxPMbCCUhlyRfGbDkn8,9562
|
194
197
|
deltacat/utils/performance.py,sha256=7ZLaMkS1ehPSIhT5uOQVBHvjC70iKHzoFquFo-KL0PI,645
|
195
|
-
deltacat/utils/placement.py,sha256=
|
198
|
+
deltacat/utils/placement.py,sha256=Lj20fb-eq8rgMdm_M2MBMfDLwhDM1sS1nJj2DvIK56s,12060
|
196
199
|
deltacat/utils/pyarrow.py,sha256=gYcoRhQoBoAFo69WNijMobrLGta4VASg8VarWPiB34Y,28979
|
197
200
|
deltacat/utils/resources.py,sha256=Ax1OgLLbZI4oYpp4Ki27OLaST-7I-AJgZwU87FVfY8g,8253
|
198
201
|
deltacat/utils/s3fs.py,sha256=PmUJ5Fm1WmD-_zp_M6yd9VbXvIoJuBeK6ApOdJJApLE,662
|
@@ -203,8 +206,8 @@ deltacat/utils/ray_utils/concurrency.py,sha256=JDVwMiQWrmuSlyCWAoiq9ctoJ0XADEfDD
|
|
203
206
|
deltacat/utils/ray_utils/dataset.py,sha256=SIljK3UkSqQ6Ntit_iSiYt9yYjN_gGrCTX6_72XdQ3w,3244
|
204
207
|
deltacat/utils/ray_utils/performance.py,sha256=d7JFM7vTXHzkGx9qNQcZzUWajnqINvYRwaM088_FpsE,464
|
205
208
|
deltacat/utils/ray_utils/runtime.py,sha256=5eaBWTDm0IXVoc5Y6aacoVB-f0Mnv-K2ewyTSjHKHwM,5009
|
206
|
-
deltacat-1.1.
|
207
|
-
deltacat-1.1.
|
208
|
-
deltacat-1.1.
|
209
|
-
deltacat-1.1.
|
210
|
-
deltacat-1.1.
|
209
|
+
deltacat-1.1.4.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
210
|
+
deltacat-1.1.4.dist-info/METADATA,sha256=q6kOOCDYRqloN7Fz1n87rkl3LlVRoJR32c1a5dBAkhQ,1780
|
211
|
+
deltacat-1.1.4.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
|
212
|
+
deltacat-1.1.4.dist-info/top_level.txt,sha256=RWdIcid4Bv2i2ozLVh-70kJpyB61xEKXod9XXGpiono,9
|
213
|
+
deltacat-1.1.4.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|