mlrun 1.7.2__py3-none-any.whl → 1.8.0rc1__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.
Potentially problematic release.
This version of mlrun might be problematic. Click here for more details.
- mlrun/__init__.py +14 -12
- mlrun/__main__.py +3 -3
- mlrun/alerts/alert.py +19 -12
- mlrun/artifacts/__init__.py +0 -2
- mlrun/artifacts/base.py +34 -11
- mlrun/artifacts/dataset.py +16 -16
- mlrun/artifacts/manager.py +13 -13
- mlrun/artifacts/model.py +66 -53
- mlrun/common/constants.py +6 -0
- mlrun/common/formatters/__init__.py +1 -0
- mlrun/common/formatters/feature_set.py +1 -0
- mlrun/common/formatters/function.py +1 -0
- mlrun/common/formatters/model_endpoint.py +30 -0
- mlrun/common/formatters/pipeline.py +1 -2
- mlrun/common/model_monitoring/__init__.py +0 -3
- mlrun/common/model_monitoring/helpers.py +1 -1
- mlrun/common/runtimes/constants.py +1 -2
- mlrun/common/schemas/__init__.py +4 -2
- mlrun/common/schemas/artifact.py +0 -6
- mlrun/common/schemas/common.py +50 -0
- mlrun/common/schemas/model_monitoring/__init__.py +8 -1
- mlrun/common/schemas/model_monitoring/constants.py +62 -12
- mlrun/common/schemas/model_monitoring/model_endpoint_v2.py +149 -0
- mlrun/common/schemas/model_monitoring/model_endpoints.py +21 -5
- mlrun/common/schemas/partition.py +122 -0
- mlrun/config.py +43 -15
- mlrun/data_types/__init__.py +0 -2
- mlrun/data_types/data_types.py +0 -1
- mlrun/data_types/infer.py +3 -1
- mlrun/data_types/spark.py +4 -4
- mlrun/data_types/to_pandas.py +2 -11
- mlrun/datastore/__init__.py +0 -2
- mlrun/datastore/alibaba_oss.py +4 -1
- mlrun/datastore/azure_blob.py +4 -1
- mlrun/datastore/base.py +12 -4
- mlrun/datastore/datastore.py +9 -3
- mlrun/datastore/datastore_profile.py +1 -1
- mlrun/datastore/dbfs_store.py +4 -1
- mlrun/datastore/filestore.py +4 -1
- mlrun/datastore/google_cloud_storage.py +4 -1
- mlrun/datastore/hdfs.py +4 -1
- mlrun/datastore/inmem.py +4 -1
- mlrun/datastore/redis.py +4 -1
- mlrun/datastore/s3.py +4 -1
- mlrun/datastore/sources.py +51 -49
- mlrun/datastore/store_resources.py +0 -2
- mlrun/datastore/targets.py +22 -23
- mlrun/datastore/utils.py +2 -2
- mlrun/datastore/v3io.py +4 -1
- mlrun/datastore/wasbfs/fs.py +13 -12
- mlrun/db/base.py +126 -62
- mlrun/db/factory.py +3 -0
- mlrun/db/httpdb.py +767 -231
- mlrun/db/nopdb.py +126 -57
- mlrun/errors.py +2 -2
- mlrun/execution.py +55 -29
- mlrun/feature_store/__init__.py +0 -2
- mlrun/feature_store/api.py +40 -40
- mlrun/feature_store/common.py +9 -9
- mlrun/feature_store/feature_set.py +20 -18
- mlrun/feature_store/feature_vector.py +27 -24
- mlrun/feature_store/retrieval/base.py +14 -9
- mlrun/feature_store/retrieval/job.py +2 -1
- mlrun/feature_store/steps.py +2 -2
- mlrun/features.py +30 -13
- mlrun/frameworks/__init__.py +1 -2
- mlrun/frameworks/_common/__init__.py +1 -2
- mlrun/frameworks/_common/artifacts_library.py +2 -2
- mlrun/frameworks/_common/mlrun_interface.py +10 -6
- mlrun/frameworks/_common/model_handler.py +29 -27
- mlrun/frameworks/_common/producer.py +3 -1
- mlrun/frameworks/_dl_common/__init__.py +1 -2
- mlrun/frameworks/_dl_common/loggers/__init__.py +1 -2
- mlrun/frameworks/_dl_common/loggers/mlrun_logger.py +4 -4
- mlrun/frameworks/_dl_common/loggers/tensorboard_logger.py +3 -3
- mlrun/frameworks/_ml_common/__init__.py +1 -2
- mlrun/frameworks/_ml_common/loggers/__init__.py +1 -2
- mlrun/frameworks/_ml_common/model_handler.py +21 -21
- mlrun/frameworks/_ml_common/plans/__init__.py +1 -2
- mlrun/frameworks/_ml_common/plans/confusion_matrix_plan.py +3 -1
- mlrun/frameworks/_ml_common/plans/dataset_plan.py +3 -3
- mlrun/frameworks/_ml_common/plans/roc_curve_plan.py +4 -4
- mlrun/frameworks/auto_mlrun/__init__.py +1 -2
- mlrun/frameworks/auto_mlrun/auto_mlrun.py +22 -15
- mlrun/frameworks/huggingface/__init__.py +1 -2
- mlrun/frameworks/huggingface/model_server.py +9 -9
- mlrun/frameworks/lgbm/__init__.py +47 -44
- mlrun/frameworks/lgbm/callbacks/__init__.py +1 -2
- mlrun/frameworks/lgbm/callbacks/logging_callback.py +4 -2
- mlrun/frameworks/lgbm/callbacks/mlrun_logging_callback.py +4 -2
- mlrun/frameworks/lgbm/mlrun_interfaces/__init__.py +1 -2
- mlrun/frameworks/lgbm/mlrun_interfaces/mlrun_interface.py +5 -5
- mlrun/frameworks/lgbm/model_handler.py +15 -11
- mlrun/frameworks/lgbm/model_server.py +11 -7
- mlrun/frameworks/lgbm/utils.py +2 -2
- mlrun/frameworks/onnx/__init__.py +1 -2
- mlrun/frameworks/onnx/dataset.py +3 -3
- mlrun/frameworks/onnx/mlrun_interface.py +2 -2
- mlrun/frameworks/onnx/model_handler.py +7 -5
- mlrun/frameworks/onnx/model_server.py +8 -6
- mlrun/frameworks/parallel_coordinates.py +11 -11
- mlrun/frameworks/pytorch/__init__.py +22 -23
- mlrun/frameworks/pytorch/callbacks/__init__.py +1 -2
- mlrun/frameworks/pytorch/callbacks/callback.py +2 -1
- mlrun/frameworks/pytorch/callbacks/logging_callback.py +15 -8
- mlrun/frameworks/pytorch/callbacks/mlrun_logging_callback.py +19 -12
- mlrun/frameworks/pytorch/callbacks/tensorboard_logging_callback.py +22 -15
- mlrun/frameworks/pytorch/callbacks_handler.py +36 -30
- mlrun/frameworks/pytorch/mlrun_interface.py +17 -17
- mlrun/frameworks/pytorch/model_handler.py +21 -17
- mlrun/frameworks/pytorch/model_server.py +13 -9
- mlrun/frameworks/sklearn/__init__.py +19 -18
- mlrun/frameworks/sklearn/estimator.py +2 -2
- mlrun/frameworks/sklearn/metric.py +3 -3
- mlrun/frameworks/sklearn/metrics_library.py +8 -6
- mlrun/frameworks/sklearn/mlrun_interface.py +3 -2
- mlrun/frameworks/sklearn/model_handler.py +4 -3
- mlrun/frameworks/tf_keras/__init__.py +11 -12
- mlrun/frameworks/tf_keras/callbacks/__init__.py +1 -2
- mlrun/frameworks/tf_keras/callbacks/logging_callback.py +17 -14
- mlrun/frameworks/tf_keras/callbacks/mlrun_logging_callback.py +15 -12
- mlrun/frameworks/tf_keras/callbacks/tensorboard_logging_callback.py +21 -18
- mlrun/frameworks/tf_keras/model_handler.py +17 -13
- mlrun/frameworks/tf_keras/model_server.py +12 -8
- mlrun/frameworks/xgboost/__init__.py +19 -18
- mlrun/frameworks/xgboost/model_handler.py +13 -9
- mlrun/launcher/base.py +3 -4
- mlrun/launcher/local.py +1 -1
- mlrun/launcher/remote.py +1 -1
- mlrun/lists.py +4 -3
- mlrun/model.py +108 -44
- mlrun/model_monitoring/__init__.py +1 -2
- mlrun/model_monitoring/api.py +6 -6
- mlrun/model_monitoring/applications/_application_steps.py +13 -15
- mlrun/model_monitoring/applications/histogram_data_drift.py +41 -15
- mlrun/model_monitoring/applications/results.py +55 -3
- mlrun/model_monitoring/controller.py +185 -223
- mlrun/model_monitoring/db/_schedules.py +156 -0
- mlrun/model_monitoring/db/_stats.py +189 -0
- mlrun/model_monitoring/db/stores/__init__.py +1 -1
- mlrun/model_monitoring/db/stores/base/store.py +6 -65
- mlrun/model_monitoring/db/stores/sqldb/models/__init__.py +0 -25
- mlrun/model_monitoring/db/stores/sqldb/models/base.py +0 -97
- mlrun/model_monitoring/db/stores/sqldb/models/mysql.py +2 -58
- mlrun/model_monitoring/db/stores/sqldb/models/sqlite.py +0 -15
- mlrun/model_monitoring/db/stores/sqldb/sql_store.py +6 -257
- mlrun/model_monitoring/db/stores/v3io_kv/kv_store.py +9 -271
- mlrun/model_monitoring/db/tsdb/base.py +74 -22
- mlrun/model_monitoring/db/tsdb/tdengine/schemas.py +66 -35
- mlrun/model_monitoring/db/tsdb/tdengine/stream_graph_steps.py +33 -0
- mlrun/model_monitoring/db/tsdb/tdengine/tdengine_connector.py +284 -51
- mlrun/model_monitoring/db/tsdb/v3io/stream_graph_steps.py +1 -0
- mlrun/model_monitoring/db/tsdb/v3io/v3io_connector.py +35 -17
- mlrun/model_monitoring/helpers.py +97 -1
- mlrun/model_monitoring/model_endpoint.py +4 -2
- mlrun/model_monitoring/stream_processing.py +2 -2
- mlrun/model_monitoring/tracking_policy.py +10 -3
- mlrun/model_monitoring/writer.py +47 -26
- mlrun/package/__init__.py +3 -6
- mlrun/package/context_handler.py +1 -1
- mlrun/package/packager.py +12 -9
- mlrun/package/packagers/__init__.py +0 -2
- mlrun/package/packagers/default_packager.py +14 -11
- mlrun/package/packagers/numpy_packagers.py +16 -7
- mlrun/package/packagers/pandas_packagers.py +18 -18
- mlrun/package/packagers/python_standard_library_packagers.py +25 -11
- mlrun/package/packagers_manager.py +31 -14
- mlrun/package/utils/__init__.py +0 -3
- mlrun/package/utils/_pickler.py +6 -6
- mlrun/platforms/__init__.py +3 -3
- mlrun/platforms/iguazio.py +4 -1
- mlrun/projects/__init__.py +1 -6
- mlrun/projects/operations.py +27 -27
- mlrun/projects/pipelines.py +85 -215
- mlrun/projects/project.py +444 -158
- mlrun/run.py +9 -9
- mlrun/runtimes/__init__.py +1 -3
- mlrun/runtimes/base.py +13 -10
- mlrun/runtimes/daskjob.py +9 -9
- mlrun/runtimes/generators.py +2 -1
- mlrun/runtimes/kubejob.py +4 -5
- mlrun/runtimes/mpijob/__init__.py +0 -2
- mlrun/runtimes/mpijob/abstract.py +7 -6
- mlrun/runtimes/nuclio/api_gateway.py +7 -7
- mlrun/runtimes/nuclio/application/application.py +11 -11
- mlrun/runtimes/nuclio/function.py +14 -14
- mlrun/runtimes/nuclio/serving.py +9 -9
- mlrun/runtimes/pod.py +74 -29
- mlrun/runtimes/remotesparkjob.py +3 -2
- mlrun/runtimes/sparkjob/__init__.py +0 -2
- mlrun/runtimes/sparkjob/spark3job.py +21 -11
- mlrun/runtimes/utils.py +6 -5
- mlrun/serving/merger.py +6 -4
- mlrun/serving/remote.py +18 -17
- mlrun/serving/routers.py +27 -27
- mlrun/serving/server.py +1 -1
- mlrun/serving/states.py +76 -71
- mlrun/serving/utils.py +13 -2
- mlrun/serving/v1_serving.py +3 -2
- mlrun/serving/v2_serving.py +4 -4
- mlrun/track/__init__.py +1 -1
- mlrun/track/tracker.py +2 -2
- mlrun/track/trackers/mlflow_tracker.py +6 -5
- mlrun/utils/async_http.py +1 -1
- mlrun/utils/helpers.py +72 -28
- mlrun/utils/logger.py +104 -2
- mlrun/utils/notifications/notification/base.py +23 -4
- mlrun/utils/notifications/notification/console.py +1 -1
- mlrun/utils/notifications/notification/git.py +6 -6
- mlrun/utils/notifications/notification/ipython.py +5 -4
- mlrun/utils/notifications/notification/slack.py +1 -1
- mlrun/utils/notifications/notification/webhook.py +13 -17
- mlrun/utils/notifications/notification_pusher.py +23 -19
- mlrun/utils/regex.py +1 -1
- mlrun/utils/version/version.json +2 -2
- {mlrun-1.7.2.dist-info → mlrun-1.8.0rc1.dist-info}/METADATA +187 -199
- mlrun-1.8.0rc1.dist-info/RECORD +356 -0
- {mlrun-1.7.2.dist-info → mlrun-1.8.0rc1.dist-info}/WHEEL +1 -1
- mlrun-1.7.2.dist-info/RECORD +0 -351
- {mlrun-1.7.2.dist-info → mlrun-1.8.0rc1.dist-info}/LICENSE +0 -0
- {mlrun-1.7.2.dist-info → mlrun-1.8.0rc1.dist-info}/entry_points.txt +0 -0
- {mlrun-1.7.2.dist-info → mlrun-1.8.0rc1.dist-info}/top_level.txt +0 -0
mlrun/utils/logger.py
CHANGED
|
@@ -11,9 +11,11 @@
|
|
|
11
11
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
|
-
|
|
14
|
+
import datetime
|
|
15
15
|
import logging
|
|
16
16
|
import os
|
|
17
|
+
import string
|
|
18
|
+
import sys
|
|
17
19
|
import typing
|
|
18
20
|
from enum import Enum
|
|
19
21
|
from functools import cached_property
|
|
@@ -24,6 +26,7 @@ from typing import IO, Optional, Union
|
|
|
24
26
|
import orjson
|
|
25
27
|
import pydantic
|
|
26
28
|
|
|
29
|
+
from mlrun import errors
|
|
27
30
|
from mlrun.config import config
|
|
28
31
|
|
|
29
32
|
|
|
@@ -93,6 +96,98 @@ class HumanReadableFormatter(_BaseFormatter):
|
|
|
93
96
|
return record_with
|
|
94
97
|
|
|
95
98
|
|
|
99
|
+
class CustomFormatter(HumanReadableFormatter):
|
|
100
|
+
"""
|
|
101
|
+
To enable custom logger formatter, configure MLRun with the following env variables:
|
|
102
|
+
1. "MLRUN_LOG_FORMATTER" = "custom" - change the default log formatter.
|
|
103
|
+
2. "MLRUN_LOG_FORMAT_OVERRIDE" = "> {timestamp} [{level}] Running module: {module} {message} {more}" - logger format
|
|
104
|
+
* Note that your custom format must include those 4 fields - timestamp, level, message and more
|
|
105
|
+
If the custom format is not configured properly , MLRun will use the default logger (human format).
|
|
106
|
+
"""
|
|
107
|
+
|
|
108
|
+
# This attribute is used to solve an issue
|
|
109
|
+
# that causes the warning to be written numerous times(for any log generation).
|
|
110
|
+
# We want to print the errors just once, not for each logger generation.
|
|
111
|
+
fail_on_format_configuration = False # for issues that relates to unrecognized keys
|
|
112
|
+
fail_on_missing_default_keys_key = (
|
|
113
|
+
False # for issues that relates to missing default keys
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
def format(self, record) -> str:
|
|
117
|
+
more = self._resolve_more(record)
|
|
118
|
+
custom_format = config.log_format_override
|
|
119
|
+
_custom_format = None
|
|
120
|
+
current_time = datetime.datetime.now()
|
|
121
|
+
formatted_time = current_time.strftime("%Y-%m-%d %H:%M:%S,%f")[:-3]
|
|
122
|
+
try:
|
|
123
|
+
if custom_format:
|
|
124
|
+
default_keys = ["timestamp", "level", "message", "more"]
|
|
125
|
+
formatter = string.Formatter()
|
|
126
|
+
custom_format_keys = [
|
|
127
|
+
key
|
|
128
|
+
for _, key, _, _ in formatter.parse(custom_format)
|
|
129
|
+
if key is not None
|
|
130
|
+
]
|
|
131
|
+
missing_default_flags = list(
|
|
132
|
+
set(default_keys) - set(custom_format_keys)
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
if (
|
|
136
|
+
missing_default_flags
|
|
137
|
+
and not CustomFormatter.fail_on_missing_default_keys_key
|
|
138
|
+
):
|
|
139
|
+
print(
|
|
140
|
+
f'> {formatted_time} [warning] Custom loggers must '
|
|
141
|
+
f'include those keys within the logger format, {", ".join(default_keys)} '
|
|
142
|
+
f'your format is missing: {", ".join(missing_default_flags)}',
|
|
143
|
+
file=sys.stderr,
|
|
144
|
+
)
|
|
145
|
+
CustomFormatter.fail_on_missing_default_keys_key = True
|
|
146
|
+
record_dict = record.__dict__
|
|
147
|
+
missing_format_configuraiton_keys = list(
|
|
148
|
+
set(custom_format_keys)
|
|
149
|
+
- set(default_keys)
|
|
150
|
+
- set(record_dict.keys())
|
|
151
|
+
)
|
|
152
|
+
if missing_format_configuraiton_keys:
|
|
153
|
+
if not CustomFormatter.fail_on_format_configuration:
|
|
154
|
+
print(
|
|
155
|
+
f"> {formatted_time} [warning] Failed to create custom logger due "
|
|
156
|
+
f'to missing format key in the log record: {", ".join(missing_format_configuraiton_keys)}',
|
|
157
|
+
file=sys.stderr,
|
|
158
|
+
)
|
|
159
|
+
CustomFormatter.fail_on_format_configuration = True
|
|
160
|
+
_format = (
|
|
161
|
+
f"> {self.formatTime(record, self.datefmt)} "
|
|
162
|
+
f"[{record.levelname.lower()}] "
|
|
163
|
+
f"{record.getMessage().rstrip()}"
|
|
164
|
+
f"{more}"
|
|
165
|
+
)
|
|
166
|
+
_custom_format = custom_format.format(
|
|
167
|
+
timestamp=self.formatTime(record, self.datefmt),
|
|
168
|
+
level=record.levelname.lower(),
|
|
169
|
+
message=record.getMessage().rstrip(),
|
|
170
|
+
more=more or "",
|
|
171
|
+
**record_dict,
|
|
172
|
+
)
|
|
173
|
+
CustomFormatter.fail_on_format_configuration = True
|
|
174
|
+
except Exception as e:
|
|
175
|
+
if not CustomFormatter.fail_on_format_configuration:
|
|
176
|
+
print(
|
|
177
|
+
f"> {formatted_time} [warning] Failed to create custom logger, "
|
|
178
|
+
f"see Exception: {errors.err_to_str(e)}",
|
|
179
|
+
file=sys.stderr,
|
|
180
|
+
)
|
|
181
|
+
CustomFormatter.fail_on_format_configuration = True
|
|
182
|
+
_format = _custom_format or (
|
|
183
|
+
f"> {self.formatTime(record, self.datefmt)} "
|
|
184
|
+
f"[{record.levelname.lower()}] "
|
|
185
|
+
f"{record.getMessage().rstrip()}"
|
|
186
|
+
f"{more}"
|
|
187
|
+
)
|
|
188
|
+
return _format
|
|
189
|
+
|
|
190
|
+
|
|
96
191
|
class HumanReadableExtendedFormatter(HumanReadableFormatter):
|
|
97
192
|
_colors = {
|
|
98
193
|
logging.NOTSET: "",
|
|
@@ -272,17 +367,24 @@ class FormatterKinds(Enum):
|
|
|
272
367
|
HUMAN = "human"
|
|
273
368
|
HUMAN_EXTENDED = "human_extended"
|
|
274
369
|
JSON = "json"
|
|
370
|
+
CUSTOM = "custom"
|
|
275
371
|
|
|
276
372
|
|
|
277
373
|
def resolve_formatter_by_kind(
|
|
278
374
|
formatter_kind: FormatterKinds,
|
|
279
375
|
) -> type[
|
|
280
|
-
typing.Union[
|
|
376
|
+
typing.Union[
|
|
377
|
+
HumanReadableFormatter,
|
|
378
|
+
HumanReadableExtendedFormatter,
|
|
379
|
+
JSONFormatter,
|
|
380
|
+
CustomFormatter,
|
|
381
|
+
]
|
|
281
382
|
]:
|
|
282
383
|
return {
|
|
283
384
|
FormatterKinds.HUMAN: HumanReadableFormatter,
|
|
284
385
|
FormatterKinds.HUMAN_EXTENDED: HumanReadableExtendedFormatter,
|
|
285
386
|
FormatterKinds.JSON: JSONFormatter,
|
|
387
|
+
FormatterKinds.CUSTOM: CustomFormatter,
|
|
286
388
|
}[formatter_kind]
|
|
287
389
|
|
|
288
390
|
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
|
|
15
15
|
import asyncio
|
|
16
16
|
import typing
|
|
17
|
+
from copy import deepcopy
|
|
17
18
|
|
|
18
19
|
import mlrun.common.schemas
|
|
19
20
|
import mlrun.lists
|
|
@@ -22,11 +23,20 @@ import mlrun.lists
|
|
|
22
23
|
class NotificationBase:
|
|
23
24
|
def __init__(
|
|
24
25
|
self,
|
|
25
|
-
name: str = None,
|
|
26
|
-
params: dict[str, str] = None,
|
|
26
|
+
name: typing.Optional[str] = None,
|
|
27
|
+
params: typing.Optional[dict[str, str]] = None,
|
|
28
|
+
default_params: typing.Optional[dict[str, str]] = None,
|
|
27
29
|
):
|
|
30
|
+
"""
|
|
31
|
+
NotificationBase is the base class for all notification types.
|
|
32
|
+
|
|
33
|
+
:param name: The name of the notification.
|
|
34
|
+
:param params: The parameters of the notification.
|
|
35
|
+
:param default_params: The default parameters of the notification. Used for server-side enrichment purposes.
|
|
36
|
+
"""
|
|
28
37
|
self.name = name
|
|
29
38
|
self.params = params or {}
|
|
39
|
+
self.params = self.enrich_default_params(self.params, default_params)
|
|
30
40
|
|
|
31
41
|
@classmethod
|
|
32
42
|
def validate_params(cls, params):
|
|
@@ -47,7 +57,7 @@ class NotificationBase:
|
|
|
47
57
|
mlrun.common.schemas.NotificationSeverity, str
|
|
48
58
|
] = mlrun.common.schemas.NotificationSeverity.INFO,
|
|
49
59
|
runs: typing.Union[mlrun.lists.RunList, list] = None,
|
|
50
|
-
custom_html: str = None,
|
|
60
|
+
custom_html: typing.Optional[str] = None,
|
|
51
61
|
alert: mlrun.common.schemas.AlertConfig = None,
|
|
52
62
|
event_data: mlrun.common.schemas.Event = None,
|
|
53
63
|
):
|
|
@@ -59,6 +69,15 @@ class NotificationBase:
|
|
|
59
69
|
) -> None:
|
|
60
70
|
self.params = params or {}
|
|
61
71
|
|
|
72
|
+
@classmethod
|
|
73
|
+
def enrich_default_params(
|
|
74
|
+
cls, params: dict, default_params: typing.Optional[dict] = None
|
|
75
|
+
) -> dict:
|
|
76
|
+
default_params = default_params or {}
|
|
77
|
+
returned_params = deepcopy(default_params)
|
|
78
|
+
returned_params.update(params)
|
|
79
|
+
return returned_params
|
|
80
|
+
|
|
62
81
|
def _get_html(
|
|
63
82
|
self,
|
|
64
83
|
message: str,
|
|
@@ -66,7 +85,7 @@ class NotificationBase:
|
|
|
66
85
|
mlrun.common.schemas.NotificationSeverity, str
|
|
67
86
|
] = mlrun.common.schemas.NotificationSeverity.INFO,
|
|
68
87
|
runs: typing.Union[mlrun.lists.RunList, list] = None,
|
|
69
|
-
custom_html: str = None,
|
|
88
|
+
custom_html: typing.Optional[str] = None,
|
|
70
89
|
alert: mlrun.common.schemas.AlertConfig = None,
|
|
71
90
|
event_data: mlrun.common.schemas.Event = None,
|
|
72
91
|
) -> str:
|
|
@@ -35,7 +35,7 @@ class ConsoleNotification(NotificationBase):
|
|
|
35
35
|
mlrun.common.schemas.NotificationSeverity, str
|
|
36
36
|
] = mlrun.common.schemas.NotificationSeverity.INFO,
|
|
37
37
|
runs: typing.Union[mlrun.lists.RunList, list] = None,
|
|
38
|
-
custom_html: str = None,
|
|
38
|
+
custom_html: typing.Optional[str] = None,
|
|
39
39
|
alert: mlrun.common.schemas.AlertConfig = None,
|
|
40
40
|
event_data: mlrun.common.schemas.Event = None,
|
|
41
41
|
):
|
|
@@ -58,7 +58,7 @@ class GitNotification(NotificationBase):
|
|
|
58
58
|
mlrun.common.schemas.NotificationSeverity, str
|
|
59
59
|
] = mlrun.common.schemas.NotificationSeverity.INFO,
|
|
60
60
|
runs: typing.Union[mlrun.lists.RunList, list] = None,
|
|
61
|
-
custom_html: str = None,
|
|
61
|
+
custom_html: typing.Optional[str] = None,
|
|
62
62
|
alert: mlrun.common.schemas.AlertConfig = None,
|
|
63
63
|
event_data: mlrun.common.schemas.Event = None,
|
|
64
64
|
):
|
|
@@ -85,11 +85,11 @@ class GitNotification(NotificationBase):
|
|
|
85
85
|
@staticmethod
|
|
86
86
|
async def _pr_comment(
|
|
87
87
|
message: str,
|
|
88
|
-
repo: str = None,
|
|
89
|
-
issue: int = None,
|
|
90
|
-
merge_request: int = None,
|
|
91
|
-
token: str = None,
|
|
92
|
-
server: str = None,
|
|
88
|
+
repo: typing.Optional[str] = None,
|
|
89
|
+
issue: typing.Optional[int] = None,
|
|
90
|
+
merge_request: typing.Optional[int] = None,
|
|
91
|
+
token: typing.Optional[str] = None,
|
|
92
|
+
server: typing.Optional[str] = None,
|
|
93
93
|
gitlab: bool = False,
|
|
94
94
|
) -> str:
|
|
95
95
|
"""push comment message to Git system PR/issue
|
|
@@ -28,10 +28,11 @@ class IPythonNotification(NotificationBase):
|
|
|
28
28
|
|
|
29
29
|
def __init__(
|
|
30
30
|
self,
|
|
31
|
-
name: str = None,
|
|
32
|
-
params: dict[str, str] = None,
|
|
31
|
+
name: typing.Optional[str] = None,
|
|
32
|
+
params: typing.Optional[dict[str, str]] = None,
|
|
33
|
+
default_params: typing.Optional[dict[str, str]] = None,
|
|
33
34
|
):
|
|
34
|
-
super().__init__(name, params)
|
|
35
|
+
super().__init__(name, params, default_params)
|
|
35
36
|
self._ipython = None
|
|
36
37
|
try:
|
|
37
38
|
import IPython
|
|
@@ -52,7 +53,7 @@ class IPythonNotification(NotificationBase):
|
|
|
52
53
|
mlrun.common.schemas.NotificationSeverity, str
|
|
53
54
|
] = mlrun.common.schemas.NotificationSeverity.INFO,
|
|
54
55
|
runs: typing.Union[mlrun.lists.RunList, list] = None,
|
|
55
|
-
custom_html: str = None,
|
|
56
|
+
custom_html: typing.Optional[str] = None,
|
|
56
57
|
alert: mlrun.common.schemas.AlertConfig = None,
|
|
57
58
|
event_data: mlrun.common.schemas.Event = None,
|
|
58
59
|
):
|
|
@@ -50,7 +50,7 @@ class SlackNotification(NotificationBase):
|
|
|
50
50
|
mlrun.common.schemas.NotificationSeverity, str
|
|
51
51
|
] = mlrun.common.schemas.NotificationSeverity.INFO,
|
|
52
52
|
runs: typing.Union[mlrun.lists.RunList, list] = None,
|
|
53
|
-
custom_html: str = None,
|
|
53
|
+
custom_html: typing.Optional[str] = None,
|
|
54
54
|
alert: mlrun.common.schemas.AlertConfig = None,
|
|
55
55
|
event_data: mlrun.common.schemas.Event = None,
|
|
56
56
|
):
|
|
@@ -12,7 +12,6 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
-
import re
|
|
16
15
|
import typing
|
|
17
16
|
|
|
18
17
|
import aiohttp
|
|
@@ -42,7 +41,7 @@ class WebhookNotification(NotificationBase):
|
|
|
42
41
|
mlrun.common.schemas.NotificationSeverity, str
|
|
43
42
|
] = mlrun.common.schemas.NotificationSeverity.INFO,
|
|
44
43
|
runs: typing.Union[mlrun.lists.RunList, list] = None,
|
|
45
|
-
custom_html: str = None,
|
|
44
|
+
custom_html: typing.Optional[str] = None,
|
|
46
45
|
alert: mlrun.common.schemas.AlertConfig = None,
|
|
47
46
|
event_data: mlrun.common.schemas.Event = None,
|
|
48
47
|
):
|
|
@@ -94,6 +93,7 @@ class WebhookNotification(NotificationBase):
|
|
|
94
93
|
|
|
95
94
|
@staticmethod
|
|
96
95
|
def _serialize_runs_in_request_body(override_body, runs):
|
|
96
|
+
str_parsed_runs = ""
|
|
97
97
|
runs = runs or []
|
|
98
98
|
|
|
99
99
|
def parse_runs():
|
|
@@ -105,26 +105,22 @@ class WebhookNotification(NotificationBase):
|
|
|
105
105
|
parsed_run = {
|
|
106
106
|
"project": run["metadata"]["project"],
|
|
107
107
|
"name": run["metadata"]["name"],
|
|
108
|
+
"host": run["metadata"]["labels"]["host"],
|
|
108
109
|
"status": {"state": run["status"]["state"]},
|
|
109
110
|
}
|
|
110
|
-
if
|
|
111
|
-
parsed_run["
|
|
112
|
-
|
|
113
|
-
parsed_run["status"]["
|
|
114
|
-
elif results := run["status"].get("results"):
|
|
115
|
-
parsed_run["status"]["results"] = results
|
|
111
|
+
if run["status"].get("error", None):
|
|
112
|
+
parsed_run["status"]["error"] = run["status"]["error"]
|
|
113
|
+
elif run["status"].get("results", None):
|
|
114
|
+
parsed_run["status"]["results"] = run["status"]["results"]
|
|
116
115
|
parsed_runs.append(parsed_run)
|
|
117
116
|
return str(parsed_runs)
|
|
118
117
|
|
|
119
118
|
if isinstance(override_body, dict):
|
|
120
119
|
for key, value in override_body.items():
|
|
121
|
-
if
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
r"{{\s*runs\s*}}", str_parsed_runs, value
|
|
128
|
-
)
|
|
129
|
-
|
|
120
|
+
if "{{ runs }}" or "{{runs}}" in value:
|
|
121
|
+
if not str_parsed_runs:
|
|
122
|
+
str_parsed_runs = parse_runs()
|
|
123
|
+
override_body[key] = value.replace(
|
|
124
|
+
"{{ runs }}", str_parsed_runs
|
|
125
|
+
).replace("{{runs}}", str_parsed_runs)
|
|
130
126
|
return override_body
|
|
@@ -20,10 +20,6 @@ import traceback
|
|
|
20
20
|
import typing
|
|
21
21
|
from concurrent.futures import ThreadPoolExecutor
|
|
22
22
|
|
|
23
|
-
import mlrun_pipelines.common.ops
|
|
24
|
-
import mlrun_pipelines.models
|
|
25
|
-
import mlrun_pipelines.utils
|
|
26
|
-
|
|
27
23
|
import mlrun.common.constants as mlrun_constants
|
|
28
24
|
import mlrun.common.runtimes.constants
|
|
29
25
|
import mlrun.common.schemas
|
|
@@ -33,6 +29,9 @@ import mlrun.errors
|
|
|
33
29
|
import mlrun.lists
|
|
34
30
|
import mlrun.model
|
|
35
31
|
import mlrun.utils.helpers
|
|
32
|
+
import mlrun_pipelines.common.ops
|
|
33
|
+
import mlrun_pipelines.models
|
|
34
|
+
import mlrun_pipelines.utils
|
|
36
35
|
from mlrun.utils import logger
|
|
37
36
|
from mlrun.utils.condition_evaluator import evaluate_condition_in_separate_process
|
|
38
37
|
|
|
@@ -100,8 +99,13 @@ class NotificationPusher(_NotificationPusherBase):
|
|
|
100
99
|
"aborted": "{resource} aborted",
|
|
101
100
|
}
|
|
102
101
|
|
|
103
|
-
def __init__(
|
|
102
|
+
def __init__(
|
|
103
|
+
self,
|
|
104
|
+
runs: typing.Union[mlrun.lists.RunList, list],
|
|
105
|
+
default_params: typing.Optional[dict] = None,
|
|
106
|
+
):
|
|
104
107
|
self._runs = runs
|
|
108
|
+
self._default_params = default_params or {}
|
|
105
109
|
self._sync_notifications: list[
|
|
106
110
|
tuple[NotificationBase, mlrun.model.RunObject, mlrun.model.Notification]
|
|
107
111
|
] = []
|
|
@@ -168,11 +172,6 @@ class NotificationPusher(_NotificationPusherBase):
|
|
|
168
172
|
logger.warning(
|
|
169
173
|
"Failed to push notification async",
|
|
170
174
|
error=mlrun.errors.err_to_str(result),
|
|
171
|
-
traceback=traceback.format_exception(
|
|
172
|
-
etype=type(result),
|
|
173
|
-
value=result,
|
|
174
|
-
tb=result.__traceback__,
|
|
175
|
-
),
|
|
176
175
|
)
|
|
177
176
|
|
|
178
177
|
logger.debug(
|
|
@@ -225,7 +224,10 @@ class NotificationPusher(_NotificationPusherBase):
|
|
|
225
224
|
params = {}
|
|
226
225
|
params.update(notification_object.secret_params)
|
|
227
226
|
params.update(notification_object.params)
|
|
228
|
-
|
|
227
|
+
default_params = self._default_params.get(notification_type.value, {})
|
|
228
|
+
notification = notification_type.get_notification()(
|
|
229
|
+
name, params, default_params
|
|
230
|
+
)
|
|
229
231
|
if notification.is_async:
|
|
230
232
|
self._async_notifications.append((notification, run, notification_object))
|
|
231
233
|
else:
|
|
@@ -366,7 +368,7 @@ class NotificationPusher(_NotificationPusherBase):
|
|
|
366
368
|
run_uid: str,
|
|
367
369
|
project: str,
|
|
368
370
|
notification: mlrun.model.Notification,
|
|
369
|
-
status: str = None,
|
|
371
|
+
status: typing.Optional[str] = None,
|
|
370
372
|
sent_time: typing.Optional[datetime.datetime] = None,
|
|
371
373
|
reason: typing.Optional[str] = None,
|
|
372
374
|
):
|
|
@@ -521,7 +523,7 @@ class NotificationPusher(_NotificationPusherBase):
|
|
|
521
523
|
|
|
522
524
|
|
|
523
525
|
class CustomNotificationPusher(_NotificationPusherBase):
|
|
524
|
-
def __init__(self, notification_types: list[str] = None):
|
|
526
|
+
def __init__(self, notification_types: typing.Optional[list[str]] = None):
|
|
525
527
|
notifications = {
|
|
526
528
|
notification_type: NotificationTypes(notification_type).get_notification()()
|
|
527
529
|
for notification_type in notification_types
|
|
@@ -550,7 +552,7 @@ class CustomNotificationPusher(_NotificationPusherBase):
|
|
|
550
552
|
mlrun.common.schemas.NotificationSeverity, str
|
|
551
553
|
] = mlrun.common.schemas.NotificationSeverity.INFO,
|
|
552
554
|
runs: typing.Union[mlrun.lists.RunList, list] = None,
|
|
553
|
-
custom_html: str = None,
|
|
555
|
+
custom_html: typing.Optional[str] = None,
|
|
554
556
|
):
|
|
555
557
|
def sync_push():
|
|
556
558
|
for notification_type, notification in self._sync_notifications.items():
|
|
@@ -572,7 +574,7 @@ class CustomNotificationPusher(_NotificationPusherBase):
|
|
|
572
574
|
def add_notification(
|
|
573
575
|
self,
|
|
574
576
|
notification_type: str,
|
|
575
|
-
params: dict[str, str] = None,
|
|
577
|
+
params: typing.Optional[dict[str, str]] = None,
|
|
576
578
|
):
|
|
577
579
|
if notification_type in self._async_notifications:
|
|
578
580
|
self._async_notifications[notification_type].load_notification(params)
|
|
@@ -597,7 +599,9 @@ class CustomNotificationPusher(_NotificationPusherBase):
|
|
|
597
599
|
else:
|
|
598
600
|
logger.warning(f"No notification of type {notification_type} in project")
|
|
599
601
|
|
|
600
|
-
def edit_notification(
|
|
602
|
+
def edit_notification(
|
|
603
|
+
self, notification_type: str, params: typing.Optional[dict[str, str]] = None
|
|
604
|
+
):
|
|
601
605
|
self.remove_notification(notification_type)
|
|
602
606
|
self.add_notification(notification_type, params)
|
|
603
607
|
|
|
@@ -627,8 +631,8 @@ class CustomNotificationPusher(_NotificationPusherBase):
|
|
|
627
631
|
def push_pipeline_start_message(
|
|
628
632
|
self,
|
|
629
633
|
project: str,
|
|
630
|
-
commit_id: str = None,
|
|
631
|
-
pipeline_id: str = None,
|
|
634
|
+
commit_id: typing.Optional[str] = None,
|
|
635
|
+
pipeline_id: typing.Optional[str] = None,
|
|
632
636
|
has_workflow_url: bool = False,
|
|
633
637
|
):
|
|
634
638
|
message = f"Workflow started in project {project}"
|
|
@@ -656,7 +660,7 @@ class CustomNotificationPusher(_NotificationPusherBase):
|
|
|
656
660
|
self,
|
|
657
661
|
runs: typing.Union[mlrun.lists.RunList, list],
|
|
658
662
|
push_all: bool = False,
|
|
659
|
-
state: str = None,
|
|
663
|
+
state: typing.Optional[str] = None,
|
|
660
664
|
):
|
|
661
665
|
"""
|
|
662
666
|
push a structured table with run results to notification targets
|
mlrun/utils/regex.py
CHANGED
mlrun/utils/version/version.json
CHANGED