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
|
@@ -1,310 +0,0 @@
|
|
|
1
|
-
# Copyright 2023 Iguazio
|
|
2
|
-
#
|
|
3
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
-
# you may not use this file except in compliance with the License.
|
|
5
|
-
# You may obtain a copy of the License at
|
|
6
|
-
#
|
|
7
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
-
#
|
|
9
|
-
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
-
# See the License for the specific language governing permissions and
|
|
13
|
-
# limitations under the License.
|
|
14
|
-
|
|
15
|
-
import dataclasses
|
|
16
|
-
import json
|
|
17
|
-
import re
|
|
18
|
-
from abc import ABC, abstractmethod
|
|
19
|
-
from typing import Any, Optional, Union
|
|
20
|
-
|
|
21
|
-
import numpy as np
|
|
22
|
-
import pandas as pd
|
|
23
|
-
|
|
24
|
-
import mlrun.common.helpers
|
|
25
|
-
import mlrun.common.schemas.model_monitoring
|
|
26
|
-
import mlrun.common.schemas.model_monitoring.constants as mm_constant
|
|
27
|
-
import mlrun.utils.v3io_clients
|
|
28
|
-
from mlrun.datastore import get_stream_pusher
|
|
29
|
-
from mlrun.datastore.targets import ParquetTarget
|
|
30
|
-
from mlrun.model_monitoring.helpers import get_stream_path
|
|
31
|
-
from mlrun.serving.utils import StepToDict
|
|
32
|
-
from mlrun.utils import logger
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
@dataclasses.dataclass
|
|
36
|
-
class ModelMonitoringApplicationResult:
|
|
37
|
-
"""
|
|
38
|
-
Class representing the result of a custom model monitoring application.
|
|
39
|
-
|
|
40
|
-
:param name: (str) Name of the application result. This name must be
|
|
41
|
-
unique for each metric in a single application
|
|
42
|
-
(name must be of the format [a-zA-Z_][a-zA-Z0-9_]*).
|
|
43
|
-
:param value: (float) Value of the application result.
|
|
44
|
-
:param kind: (ResultKindApp) Kind of application result.
|
|
45
|
-
:param status: (ResultStatusApp) Status of the application result.
|
|
46
|
-
:param extra_data: (dict) Extra data associated with the application result.
|
|
47
|
-
"""
|
|
48
|
-
|
|
49
|
-
name: str
|
|
50
|
-
value: float
|
|
51
|
-
kind: mm_constant.ResultKindApp
|
|
52
|
-
status: mm_constant.ResultStatusApp
|
|
53
|
-
extra_data: dict = dataclasses.field(default_factory=dict)
|
|
54
|
-
|
|
55
|
-
def __post_init__(self):
|
|
56
|
-
pat = re.compile(r"[a-zA-Z_][a-zA-Z0-9_]*")
|
|
57
|
-
if not re.fullmatch(pat, self.name):
|
|
58
|
-
raise mlrun.errors.MLRunInvalidArgumentError(
|
|
59
|
-
"Attribute name must be of the format [a-zA-Z_][a-zA-Z0-9_]*"
|
|
60
|
-
)
|
|
61
|
-
|
|
62
|
-
def to_dict(self):
|
|
63
|
-
"""
|
|
64
|
-
Convert the object to a dictionary format suitable for writing.
|
|
65
|
-
|
|
66
|
-
:returns: (dict) Dictionary representation of the result.
|
|
67
|
-
"""
|
|
68
|
-
return {
|
|
69
|
-
mm_constant.WriterEvent.RESULT_NAME: self.name,
|
|
70
|
-
mm_constant.WriterEvent.RESULT_VALUE: self.value,
|
|
71
|
-
mm_constant.WriterEvent.RESULT_KIND: self.kind,
|
|
72
|
-
mm_constant.WriterEvent.RESULT_STATUS: self.status,
|
|
73
|
-
mm_constant.WriterEvent.RESULT_EXTRA_DATA: json.dumps(self.extra_data),
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
class ModelMonitoringApplicationBase(StepToDict, ABC):
|
|
78
|
-
"""
|
|
79
|
-
A base class for a model monitoring application.
|
|
80
|
-
Inherit from this class to create a custom model monitoring application.
|
|
81
|
-
|
|
82
|
-
example for very simple custom application::
|
|
83
|
-
# mlrun: start-code
|
|
84
|
-
class MyApp(ApplicationBase):
|
|
85
|
-
def do_tracking(
|
|
86
|
-
self,
|
|
87
|
-
sample_df_stats: pd.DataFrame,
|
|
88
|
-
feature_stats: pd.DataFrame,
|
|
89
|
-
start_infer_time: pd.Timestamp,
|
|
90
|
-
end_infer_time: pd.Timestamp,
|
|
91
|
-
schedule_time: pd.Timestamp,
|
|
92
|
-
latest_request: pd.Timestamp,
|
|
93
|
-
endpoint_id: str,
|
|
94
|
-
output_stream_uri: str,
|
|
95
|
-
) -> ModelMonitoringApplicationResult:
|
|
96
|
-
self.context.log_artifact(TableArtifact("sample_df_stats", df=sample_df_stats))
|
|
97
|
-
return ModelMonitoringApplicationResult(
|
|
98
|
-
name="data_drift_test",
|
|
99
|
-
value=0.5,
|
|
100
|
-
kind=mm_constant.ResultKindApp.data_drift,
|
|
101
|
-
status=mm_constant.ResultStatusApp.detected,
|
|
102
|
-
)
|
|
103
|
-
|
|
104
|
-
# mlrun: end-code
|
|
105
|
-
"""
|
|
106
|
-
|
|
107
|
-
kind = "monitoring_application"
|
|
108
|
-
|
|
109
|
-
def do(
|
|
110
|
-
self, event: dict[str, Any]
|
|
111
|
-
) -> tuple[list[ModelMonitoringApplicationResult], dict]:
|
|
112
|
-
"""
|
|
113
|
-
Process the monitoring event and return application results.
|
|
114
|
-
|
|
115
|
-
:param event: (dict) The monitoring event to process.
|
|
116
|
-
:returns: (list[ModelMonitoringApplicationResult], dict) The application results
|
|
117
|
-
and the original event for the application.
|
|
118
|
-
"""
|
|
119
|
-
resolved_event = self._resolve_event(event)
|
|
120
|
-
if not (
|
|
121
|
-
hasattr(self, "context") and isinstance(self.context, mlrun.MLClientCtx)
|
|
122
|
-
):
|
|
123
|
-
self._lazy_init(app_name=resolved_event[0])
|
|
124
|
-
results = self.do_tracking(*resolved_event)
|
|
125
|
-
results = results if isinstance(results, list) else [results]
|
|
126
|
-
return results, event
|
|
127
|
-
|
|
128
|
-
def _lazy_init(self, app_name: str):
|
|
129
|
-
self.context = self._create_context_for_logging(app_name=app_name)
|
|
130
|
-
|
|
131
|
-
@abstractmethod
|
|
132
|
-
def do_tracking(
|
|
133
|
-
self,
|
|
134
|
-
application_name: str,
|
|
135
|
-
sample_df_stats: pd.DataFrame,
|
|
136
|
-
feature_stats: pd.DataFrame,
|
|
137
|
-
sample_df: pd.DataFrame,
|
|
138
|
-
start_infer_time: pd.Timestamp,
|
|
139
|
-
end_infer_time: pd.Timestamp,
|
|
140
|
-
latest_request: pd.Timestamp,
|
|
141
|
-
endpoint_id: str,
|
|
142
|
-
output_stream_uri: str,
|
|
143
|
-
) -> Union[
|
|
144
|
-
ModelMonitoringApplicationResult, list[ModelMonitoringApplicationResult]
|
|
145
|
-
]:
|
|
146
|
-
"""
|
|
147
|
-
Implement this method with your custom monitoring logic.
|
|
148
|
-
|
|
149
|
-
:param application_name: (str) the app name
|
|
150
|
-
:param sample_df_stats: (pd.DataFrame) The new sample distribution DataFrame.
|
|
151
|
-
:param feature_stats: (pd.DataFrame) The train sample distribution DataFrame.
|
|
152
|
-
:param sample_df: (pd.DataFrame) The new sample DataFrame.
|
|
153
|
-
:param start_infer_time: (pd.Timestamp) Start time of the monitoring schedule.
|
|
154
|
-
:param end_infer_time: (pd.Timestamp) End time of the monitoring schedule.
|
|
155
|
-
:param latest_request: (pd.Timestamp) Timestamp of the latest request on this endpoint_id.
|
|
156
|
-
:param endpoint_id: (str) ID of the monitored model endpoint
|
|
157
|
-
:param output_stream_uri: (str) URI of the output stream for results
|
|
158
|
-
|
|
159
|
-
:returns: (ModelMonitoringApplicationResult) or
|
|
160
|
-
(list[ModelMonitoringApplicationResult]) of the application results.
|
|
161
|
-
"""
|
|
162
|
-
raise NotImplementedError
|
|
163
|
-
|
|
164
|
-
@classmethod
|
|
165
|
-
def _resolve_event(
|
|
166
|
-
cls,
|
|
167
|
-
event: dict[str, Any],
|
|
168
|
-
) -> tuple[
|
|
169
|
-
str,
|
|
170
|
-
pd.DataFrame,
|
|
171
|
-
pd.DataFrame,
|
|
172
|
-
pd.DataFrame,
|
|
173
|
-
pd.Timestamp,
|
|
174
|
-
pd.Timestamp,
|
|
175
|
-
pd.Timestamp,
|
|
176
|
-
str,
|
|
177
|
-
str,
|
|
178
|
-
]:
|
|
179
|
-
"""
|
|
180
|
-
Converting the event into a single tuple that will be used for passing the event arguments to the running
|
|
181
|
-
application
|
|
182
|
-
|
|
183
|
-
:param event: dictionary with all the incoming data
|
|
184
|
-
|
|
185
|
-
:return: A tuple of:
|
|
186
|
-
[0] = (str) application name
|
|
187
|
-
[1] = (pd.DataFrame) current input statistics
|
|
188
|
-
[2] = (pd.DataFrame) train statistics
|
|
189
|
-
[3] = (pd.DataFrame) current input data
|
|
190
|
-
[4] = (pd.Timestamp) start time of the monitoring schedule
|
|
191
|
-
[5] = (pd.Timestamp) end time of the monitoring schedule
|
|
192
|
-
[6] = (pd.Timestamp) timestamp of the latest request
|
|
193
|
-
[7] = (str) endpoint id
|
|
194
|
-
[8] = (str) output stream uri
|
|
195
|
-
"""
|
|
196
|
-
start_time = pd.Timestamp(event[mm_constant.ApplicationEvent.START_INFER_TIME])
|
|
197
|
-
end_time = pd.Timestamp(event[mm_constant.ApplicationEvent.END_INFER_TIME])
|
|
198
|
-
return (
|
|
199
|
-
event[mm_constant.ApplicationEvent.APPLICATION_NAME],
|
|
200
|
-
cls._dict_to_histogram(
|
|
201
|
-
json.loads(event[mm_constant.ApplicationEvent.CURRENT_STATS])
|
|
202
|
-
),
|
|
203
|
-
cls._dict_to_histogram(
|
|
204
|
-
json.loads(event[mm_constant.ApplicationEvent.FEATURE_STATS])
|
|
205
|
-
),
|
|
206
|
-
ParquetTarget(
|
|
207
|
-
path=event[mm_constant.ApplicationEvent.SAMPLE_PARQUET_PATH]
|
|
208
|
-
).as_df(start_time=start_time, end_time=end_time, time_column="timestamp"),
|
|
209
|
-
start_time,
|
|
210
|
-
end_time,
|
|
211
|
-
pd.Timestamp(event[mm_constant.ApplicationEvent.LAST_REQUEST]),
|
|
212
|
-
event[mm_constant.ApplicationEvent.ENDPOINT_ID],
|
|
213
|
-
event[mm_constant.ApplicationEvent.OUTPUT_STREAM_URI],
|
|
214
|
-
)
|
|
215
|
-
|
|
216
|
-
@staticmethod
|
|
217
|
-
def _create_context_for_logging(app_name: str):
|
|
218
|
-
context = mlrun.get_or_create_ctx(
|
|
219
|
-
f"{app_name}-logger",
|
|
220
|
-
upload_artifacts=True,
|
|
221
|
-
labels={"workflow": "model-monitoring-app-logger"},
|
|
222
|
-
)
|
|
223
|
-
return context
|
|
224
|
-
|
|
225
|
-
@staticmethod
|
|
226
|
-
def _dict_to_histogram(histogram_dict: dict[str, dict[str, Any]]) -> pd.DataFrame:
|
|
227
|
-
"""
|
|
228
|
-
Convert histogram dictionary to pandas DataFrame with feature histograms as columns
|
|
229
|
-
|
|
230
|
-
:param histogram_dict: Histogram dictionary
|
|
231
|
-
|
|
232
|
-
:returns: Histogram dataframe
|
|
233
|
-
"""
|
|
234
|
-
|
|
235
|
-
# Create a dictionary with feature histograms as values
|
|
236
|
-
histograms = {}
|
|
237
|
-
for feature, stats in histogram_dict.items():
|
|
238
|
-
if "hist" in stats:
|
|
239
|
-
# Normalize to probability distribution of each feature
|
|
240
|
-
histograms[feature] = np.array(stats["hist"][0]) / stats["count"]
|
|
241
|
-
|
|
242
|
-
# Convert the dictionary to pandas DataFrame
|
|
243
|
-
histograms = pd.DataFrame(histograms)
|
|
244
|
-
|
|
245
|
-
return histograms
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
class PushToMonitoringWriter(StepToDict):
|
|
249
|
-
kind = "monitoring_application_stream_pusher"
|
|
250
|
-
|
|
251
|
-
def __init__(
|
|
252
|
-
self,
|
|
253
|
-
project: Optional[str] = None,
|
|
254
|
-
writer_application_name: Optional[str] = None,
|
|
255
|
-
stream_uri: Optional[str] = None,
|
|
256
|
-
name: Optional[str] = None,
|
|
257
|
-
):
|
|
258
|
-
"""
|
|
259
|
-
Class for pushing application results to the monitoring writer stream.
|
|
260
|
-
|
|
261
|
-
:param project: Project name.
|
|
262
|
-
:param writer_application_name: Writer application name.
|
|
263
|
-
:param stream_uri: Stream URI for pushing results.
|
|
264
|
-
:param name: Name of the PushToMonitoringWriter
|
|
265
|
-
instance default to PushToMonitoringWriter.
|
|
266
|
-
"""
|
|
267
|
-
self.project = project
|
|
268
|
-
self.application_name_to_push = writer_application_name
|
|
269
|
-
self.stream_uri = stream_uri or get_stream_path(
|
|
270
|
-
project=self.project, function_name=self.application_name_to_push
|
|
271
|
-
)
|
|
272
|
-
self.output_stream = None
|
|
273
|
-
self.name = name or "PushToMonitoringWriter"
|
|
274
|
-
|
|
275
|
-
def do(self, event: tuple[list[ModelMonitoringApplicationResult], dict]) -> None:
|
|
276
|
-
"""
|
|
277
|
-
Push application results to the monitoring writer stream.
|
|
278
|
-
|
|
279
|
-
:param event: Monitoring result(s) to push and the original event from the controller.
|
|
280
|
-
"""
|
|
281
|
-
self._lazy_init()
|
|
282
|
-
application_results, application_event = event
|
|
283
|
-
metadata = {
|
|
284
|
-
mm_constant.WriterEvent.APPLICATION_NAME: application_event[
|
|
285
|
-
mm_constant.ApplicationEvent.APPLICATION_NAME
|
|
286
|
-
],
|
|
287
|
-
mm_constant.WriterEvent.ENDPOINT_ID: application_event[
|
|
288
|
-
mm_constant.ApplicationEvent.ENDPOINT_ID
|
|
289
|
-
],
|
|
290
|
-
mm_constant.WriterEvent.START_INFER_TIME: application_event[
|
|
291
|
-
mm_constant.ApplicationEvent.START_INFER_TIME
|
|
292
|
-
],
|
|
293
|
-
mm_constant.WriterEvent.END_INFER_TIME: application_event[
|
|
294
|
-
mm_constant.ApplicationEvent.END_INFER_TIME
|
|
295
|
-
],
|
|
296
|
-
mm_constant.WriterEvent.CURRENT_STATS: json.dumps(
|
|
297
|
-
application_event[mm_constant.ApplicationEvent.CURRENT_STATS]
|
|
298
|
-
),
|
|
299
|
-
}
|
|
300
|
-
for result in application_results:
|
|
301
|
-
data = result.to_dict()
|
|
302
|
-
data.update(metadata)
|
|
303
|
-
logger.info(f"Pushing data = {data} \n to stream = {self.stream_uri}")
|
|
304
|
-
self.output_stream.push([data])
|
|
305
|
-
|
|
306
|
-
def _lazy_init(self):
|
|
307
|
-
if self.output_stream is None:
|
|
308
|
-
self.output_stream = get_stream_pusher(
|
|
309
|
-
self.stream_uri,
|
|
310
|
-
)
|