mlrun 1.7.0rc5__py3-none-any.whl → 1.7.2__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 +11 -1
- mlrun/__main__.py +39 -121
- mlrun/{datastore/helpers.py → alerts/__init__.py} +2 -5
- mlrun/alerts/alert.py +248 -0
- mlrun/api/schemas/__init__.py +4 -3
- mlrun/artifacts/__init__.py +8 -3
- mlrun/artifacts/base.py +39 -254
- mlrun/artifacts/dataset.py +9 -190
- mlrun/artifacts/manager.py +73 -46
- mlrun/artifacts/model.py +30 -158
- mlrun/artifacts/plots.py +23 -380
- mlrun/common/constants.py +73 -2
- mlrun/common/db/sql_session.py +3 -2
- mlrun/common/formatters/__init__.py +21 -0
- mlrun/common/formatters/artifact.py +46 -0
- mlrun/common/formatters/base.py +113 -0
- mlrun/common/formatters/feature_set.py +44 -0
- mlrun/common/formatters/function.py +46 -0
- mlrun/common/formatters/pipeline.py +53 -0
- mlrun/common/formatters/project.py +51 -0
- mlrun/common/formatters/run.py +29 -0
- mlrun/common/helpers.py +11 -1
- mlrun/{runtimes → common/runtimes}/constants.py +32 -4
- mlrun/common/schemas/__init__.py +21 -4
- mlrun/common/schemas/alert.py +202 -0
- mlrun/common/schemas/api_gateway.py +113 -2
- mlrun/common/schemas/artifact.py +28 -1
- mlrun/common/schemas/auth.py +11 -0
- mlrun/common/schemas/client_spec.py +2 -1
- mlrun/common/schemas/common.py +7 -4
- mlrun/common/schemas/constants.py +3 -0
- mlrun/common/schemas/feature_store.py +58 -28
- mlrun/common/schemas/frontend_spec.py +8 -0
- mlrun/common/schemas/function.py +11 -0
- mlrun/common/schemas/hub.py +7 -9
- mlrun/common/schemas/model_monitoring/__init__.py +21 -4
- mlrun/common/schemas/model_monitoring/constants.py +136 -42
- mlrun/common/schemas/model_monitoring/grafana.py +9 -5
- mlrun/common/schemas/model_monitoring/model_endpoints.py +89 -41
- mlrun/common/schemas/notification.py +69 -12
- mlrun/{runtimes/mpijob/v1alpha1.py → common/schemas/pagination.py} +10 -13
- mlrun/common/schemas/pipeline.py +7 -0
- mlrun/common/schemas/project.py +67 -16
- mlrun/common/schemas/runs.py +17 -0
- mlrun/common/schemas/schedule.py +1 -1
- mlrun/common/schemas/workflow.py +10 -2
- mlrun/common/types.py +14 -1
- mlrun/config.py +224 -58
- mlrun/data_types/data_types.py +11 -1
- mlrun/data_types/spark.py +5 -4
- mlrun/data_types/to_pandas.py +75 -34
- mlrun/datastore/__init__.py +8 -10
- mlrun/datastore/alibaba_oss.py +131 -0
- mlrun/datastore/azure_blob.py +131 -43
- mlrun/datastore/base.py +107 -47
- mlrun/datastore/datastore.py +17 -7
- mlrun/datastore/datastore_profile.py +91 -7
- mlrun/datastore/dbfs_store.py +3 -7
- mlrun/datastore/filestore.py +1 -3
- mlrun/datastore/google_cloud_storage.py +92 -32
- mlrun/datastore/hdfs.py +5 -0
- mlrun/datastore/inmem.py +6 -3
- mlrun/datastore/redis.py +3 -2
- mlrun/datastore/s3.py +30 -12
- mlrun/datastore/snowflake_utils.py +45 -0
- mlrun/datastore/sources.py +274 -59
- mlrun/datastore/spark_utils.py +30 -0
- mlrun/datastore/store_resources.py +9 -7
- mlrun/datastore/storeytargets.py +151 -0
- mlrun/datastore/targets.py +374 -102
- mlrun/datastore/utils.py +68 -5
- mlrun/datastore/v3io.py +28 -50
- mlrun/db/auth_utils.py +152 -0
- mlrun/db/base.py +231 -22
- mlrun/db/factory.py +1 -4
- mlrun/db/httpdb.py +864 -228
- mlrun/db/nopdb.py +268 -16
- mlrun/errors.py +35 -5
- mlrun/execution.py +111 -38
- mlrun/feature_store/__init__.py +0 -2
- mlrun/feature_store/api.py +46 -53
- mlrun/feature_store/common.py +6 -11
- mlrun/feature_store/feature_set.py +48 -23
- mlrun/feature_store/feature_vector.py +13 -2
- mlrun/feature_store/ingestion.py +7 -6
- mlrun/feature_store/retrieval/base.py +9 -4
- mlrun/feature_store/retrieval/dask_merger.py +2 -0
- mlrun/feature_store/retrieval/job.py +13 -4
- mlrun/feature_store/retrieval/local_merger.py +2 -0
- mlrun/feature_store/retrieval/spark_merger.py +24 -32
- mlrun/feature_store/steps.py +38 -19
- mlrun/features.py +6 -14
- mlrun/frameworks/_common/plan.py +3 -3
- mlrun/frameworks/_dl_common/loggers/tensorboard_logger.py +7 -12
- mlrun/frameworks/_ml_common/plan.py +1 -1
- mlrun/frameworks/auto_mlrun/auto_mlrun.py +2 -2
- mlrun/frameworks/lgbm/__init__.py +1 -1
- mlrun/frameworks/lgbm/callbacks/callback.py +2 -4
- mlrun/frameworks/lgbm/model_handler.py +1 -1
- mlrun/frameworks/parallel_coordinates.py +4 -4
- mlrun/frameworks/pytorch/__init__.py +2 -2
- mlrun/frameworks/sklearn/__init__.py +1 -1
- mlrun/frameworks/sklearn/mlrun_interface.py +13 -3
- mlrun/frameworks/tf_keras/__init__.py +5 -2
- mlrun/frameworks/tf_keras/callbacks/logging_callback.py +1 -1
- mlrun/frameworks/tf_keras/mlrun_interface.py +2 -2
- mlrun/frameworks/xgboost/__init__.py +1 -1
- mlrun/k8s_utils.py +57 -12
- mlrun/launcher/__init__.py +1 -1
- mlrun/launcher/base.py +6 -5
- mlrun/launcher/client.py +13 -11
- mlrun/launcher/factory.py +1 -1
- mlrun/launcher/local.py +15 -5
- mlrun/launcher/remote.py +10 -3
- mlrun/lists.py +6 -2
- mlrun/model.py +297 -48
- mlrun/model_monitoring/__init__.py +1 -1
- mlrun/model_monitoring/api.py +152 -357
- mlrun/model_monitoring/applications/__init__.py +10 -0
- mlrun/model_monitoring/applications/_application_steps.py +190 -0
- mlrun/model_monitoring/applications/base.py +108 -0
- mlrun/model_monitoring/applications/context.py +341 -0
- mlrun/model_monitoring/{evidently_application.py → applications/evidently_base.py} +27 -22
- mlrun/model_monitoring/applications/histogram_data_drift.py +227 -91
- mlrun/model_monitoring/applications/results.py +99 -0
- mlrun/model_monitoring/controller.py +130 -303
- mlrun/model_monitoring/{stores/models/sqlite.py → db/__init__.py} +5 -10
- mlrun/model_monitoring/db/stores/__init__.py +136 -0
- mlrun/model_monitoring/db/stores/base/__init__.py +15 -0
- mlrun/model_monitoring/db/stores/base/store.py +213 -0
- mlrun/model_monitoring/db/stores/sqldb/__init__.py +13 -0
- mlrun/model_monitoring/db/stores/sqldb/models/__init__.py +71 -0
- mlrun/model_monitoring/db/stores/sqldb/models/base.py +190 -0
- mlrun/model_monitoring/db/stores/sqldb/models/mysql.py +103 -0
- mlrun/model_monitoring/{stores/models/mysql.py → db/stores/sqldb/models/sqlite.py} +19 -13
- mlrun/model_monitoring/db/stores/sqldb/sql_store.py +659 -0
- mlrun/model_monitoring/db/stores/v3io_kv/__init__.py +13 -0
- mlrun/model_monitoring/db/stores/v3io_kv/kv_store.py +726 -0
- mlrun/model_monitoring/db/tsdb/__init__.py +105 -0
- mlrun/model_monitoring/db/tsdb/base.py +448 -0
- mlrun/model_monitoring/db/tsdb/helpers.py +30 -0
- mlrun/model_monitoring/db/tsdb/tdengine/__init__.py +15 -0
- mlrun/model_monitoring/db/tsdb/tdengine/schemas.py +298 -0
- mlrun/model_monitoring/db/tsdb/tdengine/stream_graph_steps.py +42 -0
- mlrun/model_monitoring/db/tsdb/tdengine/tdengine_connector.py +522 -0
- mlrun/model_monitoring/db/tsdb/v3io/__init__.py +15 -0
- mlrun/model_monitoring/db/tsdb/v3io/stream_graph_steps.py +158 -0
- mlrun/model_monitoring/db/tsdb/v3io/v3io_connector.py +849 -0
- mlrun/model_monitoring/features_drift_table.py +34 -22
- mlrun/model_monitoring/helpers.py +177 -39
- mlrun/model_monitoring/model_endpoint.py +3 -2
- mlrun/model_monitoring/stream_processing.py +165 -398
- mlrun/model_monitoring/tracking_policy.py +7 -1
- mlrun/model_monitoring/writer.py +161 -125
- mlrun/package/packagers/default_packager.py +2 -2
- mlrun/package/packagers_manager.py +1 -0
- mlrun/package/utils/_formatter.py +2 -2
- mlrun/platforms/__init__.py +11 -10
- mlrun/platforms/iguazio.py +67 -228
- mlrun/projects/__init__.py +6 -1
- mlrun/projects/operations.py +47 -20
- mlrun/projects/pipelines.py +396 -249
- mlrun/projects/project.py +1125 -414
- mlrun/render.py +28 -22
- mlrun/run.py +207 -180
- mlrun/runtimes/__init__.py +76 -11
- mlrun/runtimes/base.py +40 -14
- mlrun/runtimes/daskjob.py +9 -2
- mlrun/runtimes/databricks_job/databricks_runtime.py +1 -0
- mlrun/runtimes/databricks_job/databricks_wrapper.py +1 -1
- mlrun/runtimes/funcdoc.py +1 -29
- mlrun/runtimes/kubejob.py +34 -128
- mlrun/runtimes/local.py +39 -10
- mlrun/runtimes/mpijob/__init__.py +0 -20
- mlrun/runtimes/mpijob/abstract.py +8 -8
- mlrun/runtimes/mpijob/v1.py +1 -1
- mlrun/runtimes/nuclio/api_gateway.py +646 -177
- mlrun/runtimes/nuclio/application/__init__.py +15 -0
- mlrun/runtimes/nuclio/application/application.py +758 -0
- mlrun/runtimes/nuclio/application/reverse_proxy.go +95 -0
- mlrun/runtimes/nuclio/function.py +188 -68
- mlrun/runtimes/nuclio/serving.py +57 -60
- mlrun/runtimes/pod.py +191 -58
- mlrun/runtimes/remotesparkjob.py +11 -8
- mlrun/runtimes/sparkjob/spark3job.py +17 -18
- mlrun/runtimes/utils.py +40 -73
- mlrun/secrets.py +6 -2
- mlrun/serving/__init__.py +8 -1
- mlrun/serving/remote.py +2 -3
- mlrun/serving/routers.py +89 -64
- mlrun/serving/server.py +54 -26
- mlrun/serving/states.py +187 -56
- mlrun/serving/utils.py +19 -11
- mlrun/serving/v2_serving.py +136 -63
- mlrun/track/tracker.py +2 -1
- mlrun/track/trackers/mlflow_tracker.py +5 -0
- mlrun/utils/async_http.py +26 -6
- mlrun/utils/db.py +18 -0
- mlrun/utils/helpers.py +375 -105
- mlrun/utils/http.py +2 -2
- mlrun/utils/logger.py +75 -9
- mlrun/utils/notifications/notification/__init__.py +14 -10
- mlrun/utils/notifications/notification/base.py +48 -0
- mlrun/utils/notifications/notification/console.py +2 -0
- mlrun/utils/notifications/notification/git.py +24 -1
- mlrun/utils/notifications/notification/ipython.py +2 -0
- mlrun/utils/notifications/notification/slack.py +96 -21
- mlrun/utils/notifications/notification/webhook.py +63 -2
- mlrun/utils/notifications/notification_pusher.py +146 -16
- mlrun/utils/regex.py +9 -0
- mlrun/utils/retryer.py +3 -2
- mlrun/utils/v3io_clients.py +2 -3
- mlrun/utils/version/version.json +2 -2
- mlrun-1.7.2.dist-info/METADATA +390 -0
- mlrun-1.7.2.dist-info/RECORD +351 -0
- {mlrun-1.7.0rc5.dist-info → mlrun-1.7.2.dist-info}/WHEEL +1 -1
- mlrun/feature_store/retrieval/conversion.py +0 -271
- mlrun/kfpops.py +0 -868
- mlrun/model_monitoring/application.py +0 -310
- mlrun/model_monitoring/batch.py +0 -974
- mlrun/model_monitoring/controller_handler.py +0 -37
- mlrun/model_monitoring/prometheus.py +0 -216
- mlrun/model_monitoring/stores/__init__.py +0 -111
- mlrun/model_monitoring/stores/kv_model_endpoint_store.py +0 -574
- mlrun/model_monitoring/stores/model_endpoint_store.py +0 -145
- mlrun/model_monitoring/stores/models/__init__.py +0 -27
- mlrun/model_monitoring/stores/models/base.py +0 -84
- mlrun/model_monitoring/stores/sql_model_endpoint_store.py +0 -382
- mlrun/platforms/other.py +0 -305
- mlrun-1.7.0rc5.dist-info/METADATA +0 -269
- mlrun-1.7.0rc5.dist-info/RECORD +0 -323
- {mlrun-1.7.0rc5.dist-info → mlrun-1.7.2.dist-info}/LICENSE +0 -0
- {mlrun-1.7.0rc5.dist-info → mlrun-1.7.2.dist-info}/entry_points.txt +0 -0
- {mlrun-1.7.0rc5.dist-info → mlrun-1.7.2.dist-info}/top_level.txt +0 -0
|
@@ -11,8 +11,8 @@
|
|
|
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
|
-
#
|
|
15
14
|
|
|
15
|
+
import warnings
|
|
16
16
|
from typing import Union
|
|
17
17
|
|
|
18
18
|
import mlrun.common.schemas.schedule
|
|
@@ -55,6 +55,12 @@ class TrackingPolicy(mlrun.model.ModelObj):
|
|
|
55
55
|
writer function, which is a real time nuclio functino, will be deployed
|
|
56
56
|
with the same image. By default, the image is mlrun/mlrun.
|
|
57
57
|
"""
|
|
58
|
+
warnings.warn(
|
|
59
|
+
"The `TrackingPolicy` class is deprecated from version 1.7.0 and is not "
|
|
60
|
+
"used anymore. It will be removed in 1.9.0.",
|
|
61
|
+
FutureWarning,
|
|
62
|
+
)
|
|
63
|
+
|
|
58
64
|
if isinstance(default_batch_intervals, str):
|
|
59
65
|
default_batch_intervals = (
|
|
60
66
|
mlrun.common.schemas.schedule.ScheduleCronTrigger.from_crontab(
|
mlrun/model_monitoring/writer.py
CHANGED
|
@@ -12,29 +12,29 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
-
import datetime
|
|
16
15
|
import json
|
|
17
|
-
from
|
|
18
|
-
from typing import Any, NewType
|
|
19
|
-
|
|
20
|
-
import pandas as pd
|
|
21
|
-
from v3io.dataplane import Client as V3IOClient
|
|
22
|
-
from v3io_frames.client import ClientBase as V3IOFramesClient
|
|
23
|
-
from v3io_frames.errors import Error as V3IOFramesError
|
|
24
|
-
from v3io_frames.frames_pb2 import IGNORE
|
|
16
|
+
from typing import Any, Callable, NewType
|
|
25
17
|
|
|
26
18
|
import mlrun.common.model_monitoring
|
|
19
|
+
import mlrun.common.schemas
|
|
20
|
+
import mlrun.common.schemas.alert as alert_objects
|
|
27
21
|
import mlrun.model_monitoring
|
|
28
|
-
|
|
29
|
-
|
|
22
|
+
from mlrun.common.schemas.model_monitoring.constants import (
|
|
23
|
+
EventFieldType,
|
|
24
|
+
HistogramDataDriftApplicationConstants,
|
|
25
|
+
MetricData,
|
|
26
|
+
ResultData,
|
|
27
|
+
ResultKindApp,
|
|
28
|
+
ResultStatusApp,
|
|
29
|
+
WriterEvent,
|
|
30
|
+
WriterEventKind,
|
|
31
|
+
)
|
|
30
32
|
from mlrun.common.schemas.notification import NotificationKind, NotificationSeverity
|
|
33
|
+
from mlrun.model_monitoring.helpers import get_result_instance_fqn
|
|
31
34
|
from mlrun.serving.utils import StepToDict
|
|
32
35
|
from mlrun.utils import logger
|
|
33
36
|
from mlrun.utils.notifications.notification_pusher import CustomNotificationPusher
|
|
34
37
|
|
|
35
|
-
_TSDB_BE = "tsdb"
|
|
36
|
-
_TSDB_RATE = "1/s"
|
|
37
|
-
_TSDB_TABLE = "app-results"
|
|
38
38
|
_RawEvent = dict[str, Any]
|
|
39
39
|
_AppResultEvent = NewType("_AppResultEvent", _RawEvent)
|
|
40
40
|
|
|
@@ -69,20 +69,20 @@ class _Notifier:
|
|
|
69
69
|
self._severity = severity
|
|
70
70
|
|
|
71
71
|
def _should_send_event(self) -> bool:
|
|
72
|
-
return self._event[
|
|
72
|
+
return self._event[ResultData.RESULT_STATUS] >= ResultStatusApp.detected.value
|
|
73
73
|
|
|
74
74
|
def _generate_message(self) -> str:
|
|
75
75
|
return f"""\
|
|
76
76
|
The monitoring app `{self._event[WriterEvent.APPLICATION_NAME]}` \
|
|
77
|
-
of kind `{self._event[
|
|
77
|
+
of kind `{self._event[ResultData.RESULT_KIND]}` \
|
|
78
78
|
detected a problem in model endpoint ID `{self._event[WriterEvent.ENDPOINT_ID]}` \
|
|
79
79
|
at time `{self._event[WriterEvent.START_INFER_TIME]}`.
|
|
80
80
|
|
|
81
81
|
Result data:
|
|
82
|
-
Name: `{self._event[
|
|
83
|
-
Value: `{self._event[
|
|
84
|
-
Status: `{self._event[
|
|
85
|
-
Extra data: `{self._event[
|
|
82
|
+
Name: `{self._event[ResultData.RESULT_NAME]}`
|
|
83
|
+
Value: `{self._event[ResultData.RESULT_VALUE]}`
|
|
84
|
+
Status: `{self._event[ResultData.RESULT_STATUS]}`
|
|
85
|
+
Extra data: `{self._event[ResultData.RESULT_EXTRA_DATA]}`\
|
|
86
86
|
"""
|
|
87
87
|
|
|
88
88
|
def notify(self) -> None:
|
|
@@ -97,140 +97,176 @@ Extra data: `{self._event[WriterEvent.RESULT_EXTRA_DATA]}`\
|
|
|
97
97
|
|
|
98
98
|
class ModelMonitoringWriter(StepToDict):
|
|
99
99
|
"""
|
|
100
|
-
Write monitoring
|
|
100
|
+
Write monitoring application results to the target databases
|
|
101
101
|
"""
|
|
102
102
|
|
|
103
103
|
kind = "monitoring_application_stream_pusher"
|
|
104
104
|
|
|
105
|
-
def __init__(
|
|
105
|
+
def __init__(
|
|
106
|
+
self,
|
|
107
|
+
project: str,
|
|
108
|
+
secret_provider: Callable = None,
|
|
109
|
+
) -> None:
|
|
106
110
|
self.project = project
|
|
107
111
|
self.name = project # required for the deployment process
|
|
108
|
-
|
|
109
|
-
self._kv_client = self._get_v3io_client().kv
|
|
110
|
-
self._tsdb_client = self._get_v3io_frames_client(self._v3io_container)
|
|
112
|
+
|
|
111
113
|
self._custom_notifier = CustomNotificationPusher(
|
|
112
114
|
notification_types=[NotificationKind.slack]
|
|
113
115
|
)
|
|
114
|
-
self._create_tsdb_table()
|
|
115
|
-
self._kv_schemas = []
|
|
116
|
-
|
|
117
|
-
@staticmethod
|
|
118
|
-
def get_v3io_container(project_name: str) -> str:
|
|
119
|
-
return f"users/pipelines/{project_name}/monitoring-apps"
|
|
120
116
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
return mlrun.utils.v3io_clients.get_v3io_client(
|
|
124
|
-
endpoint=mlrun.mlconf.v3io_api,
|
|
117
|
+
self._app_result_store = mlrun.model_monitoring.get_store_object(
|
|
118
|
+
project=self.project, secret_provider=secret_provider
|
|
125
119
|
)
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
def _get_v3io_frames_client(v3io_container: str) -> V3IOFramesClient:
|
|
129
|
-
return mlrun.utils.v3io_clients.get_frames_client(
|
|
130
|
-
address=mlrun.mlconf.v3io_framesd,
|
|
131
|
-
container=v3io_container,
|
|
120
|
+
self._tsdb_connector = mlrun.model_monitoring.get_tsdb_connector(
|
|
121
|
+
project=self.project, secret_provider=secret_provider
|
|
132
122
|
)
|
|
123
|
+
self._endpoints_records = {}
|
|
133
124
|
|
|
134
|
-
def
|
|
135
|
-
self
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
125
|
+
def _generate_event_on_drift(
|
|
126
|
+
self,
|
|
127
|
+
entity_id: str,
|
|
128
|
+
result_status: int,
|
|
129
|
+
event_value: dict,
|
|
130
|
+
project_name: str,
|
|
131
|
+
result_kind: int,
|
|
132
|
+
) -> None:
|
|
133
|
+
entity = mlrun.common.schemas.alert.EventEntities(
|
|
134
|
+
kind=alert_objects.EventEntityKind.MODEL_ENDPOINT_RESULT,
|
|
135
|
+
project=project_name,
|
|
136
|
+
ids=[entity_id],
|
|
140
137
|
)
|
|
141
138
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
endpoint_id = event.pop(WriterEvent.ENDPOINT_ID)
|
|
145
|
-
app_name = event.pop(WriterEvent.APPLICATION_NAME)
|
|
146
|
-
metric_name = event.pop(WriterEvent.RESULT_NAME)
|
|
147
|
-
attributes = {metric_name: json.dumps(event)}
|
|
148
|
-
self._kv_client.update(
|
|
149
|
-
container=self._v3io_container,
|
|
150
|
-
table_path=endpoint_id,
|
|
151
|
-
key=app_name,
|
|
152
|
-
attributes=attributes,
|
|
139
|
+
event_kind = self._generate_alert_event_kind(
|
|
140
|
+
result_status=result_status, result_kind=result_kind
|
|
153
141
|
)
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
"""Generate V3IO KV schema file which will be used by the model monitoring applications dashboard in Grafana."""
|
|
160
|
-
fields = [
|
|
161
|
-
{"name": WriterEvent.RESULT_NAME, "type": "string", "nullable": False}
|
|
162
|
-
]
|
|
163
|
-
res = self._kv_client.create_schema(
|
|
164
|
-
container=self._v3io_container,
|
|
165
|
-
table_path=endpoint_id,
|
|
166
|
-
key=WriterEvent.APPLICATION_NAME,
|
|
167
|
-
fields=fields,
|
|
142
|
+
|
|
143
|
+
event_data = mlrun.common.schemas.Event(
|
|
144
|
+
kind=alert_objects.EventKind(value=event_kind),
|
|
145
|
+
entity=entity,
|
|
146
|
+
value_dict=event_value,
|
|
168
147
|
)
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
)
|
|
173
|
-
else:
|
|
174
|
-
logger.info(
|
|
175
|
-
"Generated V3IO KV schema successfully", endpoint_id=endpoint_id
|
|
176
|
-
)
|
|
177
|
-
self._kv_schemas.append(endpoint_id)
|
|
148
|
+
logger.info("Sending a drift event")
|
|
149
|
+
mlrun.get_run_db().generate_event(event_kind, event_data)
|
|
150
|
+
logger.info("Drift event sent successfully")
|
|
178
151
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
152
|
+
@staticmethod
|
|
153
|
+
def _generate_alert_event_kind(
|
|
154
|
+
result_kind: int, result_status: int
|
|
155
|
+
) -> alert_objects.EventKind:
|
|
156
|
+
"""Generate the required Event Kind format for the alerting system"""
|
|
157
|
+
event_kind = ResultKindApp(value=result_kind).name
|
|
158
|
+
|
|
159
|
+
if result_status == ResultStatusApp.detected.value:
|
|
160
|
+
event_kind = f"{event_kind}_detected"
|
|
161
|
+
else:
|
|
162
|
+
event_kind = f"{event_kind}_suspected"
|
|
163
|
+
return alert_objects.EventKind(
|
|
164
|
+
value=mlrun.utils.helpers.normalize_name(event_kind)
|
|
183
165
|
)
|
|
184
|
-
del event[WriterEvent.RESULT_EXTRA_DATA]
|
|
185
|
-
try:
|
|
186
|
-
self._tsdb_client.write(
|
|
187
|
-
backend=_TSDB_BE,
|
|
188
|
-
table=_TSDB_TABLE,
|
|
189
|
-
dfs=pd.DataFrame.from_records([event]),
|
|
190
|
-
index_cols=[
|
|
191
|
-
WriterEvent.END_INFER_TIME,
|
|
192
|
-
WriterEvent.ENDPOINT_ID,
|
|
193
|
-
WriterEvent.APPLICATION_NAME,
|
|
194
|
-
WriterEvent.RESULT_NAME,
|
|
195
|
-
],
|
|
196
|
-
)
|
|
197
|
-
logger.info("Updated V3IO TSDB successfully", table=_TSDB_TABLE)
|
|
198
|
-
except V3IOFramesError as err:
|
|
199
|
-
logger.warn(
|
|
200
|
-
"Could not write drift measures to TSDB",
|
|
201
|
-
err=err,
|
|
202
|
-
table=_TSDB_TABLE,
|
|
203
|
-
event=event,
|
|
204
|
-
)
|
|
205
166
|
|
|
206
167
|
@staticmethod
|
|
207
|
-
def _reconstruct_event(event: _RawEvent) -> _AppResultEvent:
|
|
168
|
+
def _reconstruct_event(event: _RawEvent) -> tuple[_AppResultEvent, WriterEventKind]:
|
|
208
169
|
"""
|
|
209
170
|
Modify the raw event into the expected monitoring application event
|
|
210
171
|
schema as defined in `mlrun.common.schemas.model_monitoring.constants.WriterEvent`
|
|
211
172
|
"""
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
173
|
+
if not isinstance(event, dict):
|
|
174
|
+
raise _WriterEventTypeError(
|
|
175
|
+
f"The event is of type: {type(event)}, expected a dictionary"
|
|
215
176
|
)
|
|
216
|
-
|
|
217
|
-
|
|
177
|
+
kind = event.pop(WriterEvent.EVENT_KIND, WriterEventKind.RESULT)
|
|
178
|
+
result_event = _AppResultEvent(json.loads(event.pop(WriterEvent.DATA, "{}")))
|
|
179
|
+
if not result_event: # BC for < 1.7.0, can be removed in 1.9.0
|
|
180
|
+
result_event = _AppResultEvent(event)
|
|
181
|
+
else:
|
|
182
|
+
result_event.update(_AppResultEvent(event))
|
|
183
|
+
|
|
184
|
+
expected_keys = list(
|
|
185
|
+
set(WriterEvent.list()).difference(
|
|
186
|
+
[WriterEvent.EVENT_KIND, WriterEvent.DATA]
|
|
218
187
|
)
|
|
219
|
-
|
|
220
|
-
|
|
188
|
+
)
|
|
189
|
+
if kind == WriterEventKind.METRIC:
|
|
190
|
+
expected_keys.extend(MetricData.list())
|
|
191
|
+
elif kind == WriterEventKind.RESULT:
|
|
192
|
+
expected_keys.extend(ResultData.list())
|
|
193
|
+
else:
|
|
221
194
|
raise _WriterEventValueError(
|
|
222
|
-
"
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
raise
|
|
227
|
-
f"The event
|
|
228
|
-
|
|
195
|
+
f"Unknown event kind: {kind}, expected one of: {WriterEventKind.list()}"
|
|
196
|
+
)
|
|
197
|
+
missing_keys = [key for key in expected_keys if key not in result_event]
|
|
198
|
+
if missing_keys:
|
|
199
|
+
raise _WriterEventValueError(
|
|
200
|
+
f"The received event misses some keys compared to the expected "
|
|
201
|
+
f"monitoring application event schema: {missing_keys}"
|
|
202
|
+
)
|
|
203
|
+
|
|
204
|
+
return result_event, kind
|
|
229
205
|
|
|
230
206
|
def do(self, event: _RawEvent) -> None:
|
|
231
|
-
event = self._reconstruct_event(event)
|
|
207
|
+
event, kind = self._reconstruct_event(event)
|
|
232
208
|
logger.info("Starting to write event", event=event)
|
|
233
|
-
self.
|
|
234
|
-
self.
|
|
235
|
-
|
|
209
|
+
self._tsdb_connector.write_application_event(event=event.copy(), kind=kind)
|
|
210
|
+
self._app_result_store.write_application_event(event=event.copy(), kind=kind)
|
|
211
|
+
|
|
236
212
|
logger.info("Completed event DB writes")
|
|
213
|
+
|
|
214
|
+
if kind == WriterEventKind.RESULT:
|
|
215
|
+
_Notifier(event=event, notification_pusher=self._custom_notifier).notify()
|
|
216
|
+
|
|
217
|
+
if (
|
|
218
|
+
mlrun.mlconf.alerts.mode == mlrun.common.schemas.alert.AlertsModes.enabled
|
|
219
|
+
and kind == WriterEventKind.RESULT
|
|
220
|
+
and (
|
|
221
|
+
event[ResultData.RESULT_STATUS] == ResultStatusApp.detected.value
|
|
222
|
+
or event[ResultData.RESULT_STATUS]
|
|
223
|
+
== ResultStatusApp.potential_detection.value
|
|
224
|
+
)
|
|
225
|
+
):
|
|
226
|
+
endpoint_id = event[WriterEvent.ENDPOINT_ID]
|
|
227
|
+
endpoint_record = self._endpoints_records.setdefault(
|
|
228
|
+
endpoint_id,
|
|
229
|
+
self._app_result_store.get_model_endpoint(endpoint_id=endpoint_id),
|
|
230
|
+
)
|
|
231
|
+
event_value = {
|
|
232
|
+
"app_name": event[WriterEvent.APPLICATION_NAME],
|
|
233
|
+
"model": endpoint_record.get(EventFieldType.MODEL),
|
|
234
|
+
"model_endpoint_id": event[WriterEvent.ENDPOINT_ID],
|
|
235
|
+
"result_name": event[ResultData.RESULT_NAME],
|
|
236
|
+
"result_value": event[ResultData.RESULT_VALUE],
|
|
237
|
+
}
|
|
238
|
+
self._generate_event_on_drift(
|
|
239
|
+
entity_id=get_result_instance_fqn(
|
|
240
|
+
event[WriterEvent.ENDPOINT_ID],
|
|
241
|
+
event[WriterEvent.APPLICATION_NAME],
|
|
242
|
+
event[ResultData.RESULT_NAME],
|
|
243
|
+
),
|
|
244
|
+
result_status=event[ResultData.RESULT_STATUS],
|
|
245
|
+
event_value=event_value,
|
|
246
|
+
project_name=self.project,
|
|
247
|
+
result_kind=event[ResultData.RESULT_KIND],
|
|
248
|
+
)
|
|
249
|
+
|
|
250
|
+
if (
|
|
251
|
+
kind == WriterEventKind.RESULT
|
|
252
|
+
and event[WriterEvent.APPLICATION_NAME]
|
|
253
|
+
== HistogramDataDriftApplicationConstants.NAME
|
|
254
|
+
and event[ResultData.RESULT_NAME]
|
|
255
|
+
== HistogramDataDriftApplicationConstants.GENERAL_RESULT_NAME
|
|
256
|
+
):
|
|
257
|
+
endpoint_id = event[WriterEvent.ENDPOINT_ID]
|
|
258
|
+
logger.info(
|
|
259
|
+
"Updating the model endpoint with metadata specific to the histogram "
|
|
260
|
+
"data drift app",
|
|
261
|
+
endpoint_id=endpoint_id,
|
|
262
|
+
)
|
|
263
|
+
attributes = json.loads(event[ResultData.RESULT_EXTRA_DATA])
|
|
264
|
+
attributes[EventFieldType.DRIFT_STATUS] = str(
|
|
265
|
+
attributes[EventFieldType.DRIFT_STATUS]
|
|
266
|
+
)
|
|
267
|
+
self._app_result_store.update_model_endpoint(
|
|
268
|
+
endpoint_id=endpoint_id,
|
|
269
|
+
attributes=attributes,
|
|
270
|
+
)
|
|
271
|
+
|
|
272
|
+
logger.info("Model monitoring writer finished handling event")
|
|
@@ -34,7 +34,7 @@ class _DefaultPackagerMeta(ABCMeta):
|
|
|
34
34
|
dynamically generated docstring that will include a summary of the packager.
|
|
35
35
|
"""
|
|
36
36
|
|
|
37
|
-
def __new__(
|
|
37
|
+
def __new__(cls, name: str, bases: tuple, namespace: dict, **kwargs):
|
|
38
38
|
"""
|
|
39
39
|
Create a new DefaultPackager metaclass that saves the original packager docstring to another attribute named
|
|
40
40
|
`_packager_doc`.
|
|
@@ -48,7 +48,7 @@ class _DefaultPackagerMeta(ABCMeta):
|
|
|
48
48
|
namespace["_packager_doc"] = namespace.get("__doc__", "")
|
|
49
49
|
|
|
50
50
|
# Continue creating the metaclass:
|
|
51
|
-
return super().__new__(
|
|
51
|
+
return super().__new__(cls, name, bases, namespace, **kwargs)
|
|
52
52
|
|
|
53
53
|
@property
|
|
54
54
|
def __doc__(cls: type["DefaultPackager"]) -> str:
|
|
@@ -142,11 +142,11 @@ class _YAMLFormatter(_Formatter):
|
|
|
142
142
|
|
|
143
143
|
:param obj: The object to write.
|
|
144
144
|
:param file_path: The file path to write to.
|
|
145
|
-
:param dump_kwargs: Additional keyword arguments to pass to the `yaml.
|
|
145
|
+
:param dump_kwargs: Additional keyword arguments to pass to the `yaml.safe_dump` method of the formatter in use.
|
|
146
146
|
"""
|
|
147
147
|
dump_kwargs = dump_kwargs or cls.DEFAULT_DUMP_KWARGS
|
|
148
148
|
with open(file_path, "w") as file:
|
|
149
|
-
yaml.
|
|
149
|
+
yaml.safe_dump(obj, file, **dump_kwargs)
|
|
150
150
|
|
|
151
151
|
@classmethod
|
|
152
152
|
def read(cls, file_path: str) -> Union[list, dict]:
|
mlrun/platforms/__init__.py
CHANGED
|
@@ -17,22 +17,23 @@ import json
|
|
|
17
17
|
from pprint import pprint
|
|
18
18
|
from time import sleep
|
|
19
19
|
|
|
20
|
-
from .
|
|
21
|
-
|
|
22
|
-
VolumeMount,
|
|
23
|
-
add_or_refresh_credentials,
|
|
24
|
-
is_iguazio_session_cookie,
|
|
25
|
-
mount_v3io,
|
|
26
|
-
v3io_cred,
|
|
27
|
-
)
|
|
28
|
-
from .other import (
|
|
20
|
+
from mlrun_pipelines.common.mounts import VolumeMount
|
|
21
|
+
from mlrun_pipelines.mounts import (
|
|
29
22
|
auto_mount,
|
|
30
23
|
mount_configmap,
|
|
31
24
|
mount_hostpath,
|
|
32
25
|
mount_pvc,
|
|
33
26
|
mount_s3,
|
|
34
27
|
mount_secret,
|
|
28
|
+
mount_v3io,
|
|
35
29
|
set_env_variables,
|
|
30
|
+
v3io_cred,
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
from .iguazio import (
|
|
34
|
+
V3ioStreamClient,
|
|
35
|
+
add_or_refresh_credentials,
|
|
36
|
+
is_iguazio_session_cookie,
|
|
36
37
|
)
|
|
37
38
|
|
|
38
39
|
|
|
@@ -48,7 +49,7 @@ def watch_stream(
|
|
|
48
49
|
|
|
49
50
|
example::
|
|
50
51
|
|
|
51
|
-
watch_stream(
|
|
52
|
+
watch_stream("v3io:///users/admin/mystream")
|
|
52
53
|
|
|
53
54
|
:param url: stream url
|
|
54
55
|
:param shard_ids: range or list of shard IDs
|