mlrun 1.4.0rc25__py3-none-any.whl → 1.5.0rc2__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 +2 -35
- mlrun/__main__.py +3 -41
- mlrun/api/api/api.py +6 -0
- mlrun/api/api/endpoints/feature_store.py +0 -4
- mlrun/api/api/endpoints/files.py +14 -2
- mlrun/api/api/endpoints/frontend_spec.py +2 -1
- mlrun/api/api/endpoints/functions.py +95 -59
- mlrun/api/api/endpoints/grafana_proxy.py +9 -9
- mlrun/api/api/endpoints/logs.py +17 -3
- mlrun/api/api/endpoints/model_endpoints.py +3 -2
- mlrun/api/api/endpoints/pipelines.py +1 -5
- mlrun/api/api/endpoints/projects.py +88 -0
- mlrun/api/api/endpoints/runs.py +48 -6
- mlrun/api/api/endpoints/submit.py +2 -1
- mlrun/api/api/endpoints/workflows.py +355 -0
- mlrun/api/api/utils.py +3 -4
- mlrun/api/crud/__init__.py +1 -0
- mlrun/api/crud/client_spec.py +6 -2
- mlrun/api/crud/feature_store.py +5 -0
- mlrun/api/crud/model_monitoring/__init__.py +1 -0
- mlrun/api/crud/model_monitoring/deployment.py +497 -0
- mlrun/api/crud/model_monitoring/grafana.py +96 -42
- mlrun/api/crud/model_monitoring/helpers.py +159 -0
- mlrun/api/crud/model_monitoring/model_endpoints.py +202 -476
- mlrun/api/crud/notifications.py +9 -4
- mlrun/api/crud/pipelines.py +6 -11
- mlrun/api/crud/projects.py +2 -2
- mlrun/api/crud/runtime_resources.py +4 -3
- mlrun/api/crud/runtimes/nuclio/helpers.py +5 -1
- mlrun/api/crud/secrets.py +21 -0
- mlrun/api/crud/workflows.py +352 -0
- mlrun/api/db/base.py +16 -1
- mlrun/api/db/init_db.py +2 -4
- mlrun/api/db/session.py +1 -1
- mlrun/api/db/sqldb/db.py +129 -31
- mlrun/api/db/sqldb/models/models_mysql.py +15 -1
- mlrun/api/db/sqldb/models/models_sqlite.py +16 -2
- mlrun/api/launcher.py +38 -6
- mlrun/api/main.py +3 -2
- mlrun/api/rundb/__init__.py +13 -0
- mlrun/{db → api/rundb}/sqldb.py +36 -84
- mlrun/api/runtime_handlers/__init__.py +56 -0
- mlrun/api/runtime_handlers/base.py +1247 -0
- mlrun/api/runtime_handlers/daskjob.py +209 -0
- mlrun/api/runtime_handlers/kubejob.py +37 -0
- mlrun/api/runtime_handlers/mpijob.py +147 -0
- mlrun/api/runtime_handlers/remotesparkjob.py +29 -0
- mlrun/api/runtime_handlers/sparkjob.py +148 -0
- mlrun/api/schemas/__init__.py +17 -6
- mlrun/api/utils/builder.py +1 -4
- mlrun/api/utils/clients/chief.py +14 -0
- mlrun/api/utils/clients/iguazio.py +33 -33
- mlrun/api/utils/clients/nuclio.py +2 -2
- mlrun/api/utils/periodic.py +9 -2
- mlrun/api/utils/projects/follower.py +14 -7
- mlrun/api/utils/projects/leader.py +2 -1
- mlrun/api/utils/projects/remotes/nop_follower.py +2 -2
- mlrun/api/utils/projects/remotes/nop_leader.py +2 -2
- mlrun/api/utils/runtimes/__init__.py +14 -0
- mlrun/api/utils/runtimes/nuclio.py +43 -0
- mlrun/api/utils/scheduler.py +98 -15
- mlrun/api/utils/singletons/db.py +5 -1
- mlrun/api/utils/singletons/project_member.py +4 -1
- mlrun/api/utils/singletons/scheduler.py +1 -1
- mlrun/artifacts/base.py +6 -6
- mlrun/artifacts/dataset.py +4 -4
- mlrun/artifacts/manager.py +2 -3
- mlrun/artifacts/model.py +2 -2
- mlrun/artifacts/plots.py +8 -8
- mlrun/common/db/__init__.py +14 -0
- mlrun/common/helpers.py +37 -0
- mlrun/{mlutils → common/model_monitoring}/__init__.py +3 -2
- mlrun/common/model_monitoring/helpers.py +69 -0
- mlrun/common/schemas/__init__.py +13 -1
- mlrun/common/schemas/auth.py +4 -1
- mlrun/common/schemas/client_spec.py +1 -1
- mlrun/common/schemas/function.py +17 -0
- mlrun/common/schemas/model_monitoring/__init__.py +48 -0
- mlrun/common/{model_monitoring.py → schemas/model_monitoring/constants.py} +11 -23
- mlrun/common/schemas/model_monitoring/grafana.py +55 -0
- mlrun/common/schemas/{model_endpoints.py → model_monitoring/model_endpoints.py} +32 -65
- mlrun/common/schemas/notification.py +1 -0
- mlrun/common/schemas/object.py +4 -0
- mlrun/common/schemas/project.py +1 -0
- mlrun/common/schemas/regex.py +1 -1
- mlrun/common/schemas/runs.py +1 -8
- mlrun/common/schemas/schedule.py +1 -8
- mlrun/common/schemas/workflow.py +54 -0
- mlrun/config.py +45 -42
- mlrun/datastore/__init__.py +21 -0
- mlrun/datastore/base.py +1 -1
- mlrun/datastore/datastore.py +9 -0
- mlrun/datastore/dbfs_store.py +168 -0
- mlrun/datastore/helpers.py +18 -0
- mlrun/datastore/sources.py +1 -0
- mlrun/datastore/store_resources.py +2 -5
- mlrun/datastore/v3io.py +1 -2
- mlrun/db/__init__.py +4 -68
- mlrun/db/base.py +12 -0
- mlrun/db/factory.py +65 -0
- mlrun/db/httpdb.py +175 -20
- mlrun/db/nopdb.py +4 -2
- mlrun/execution.py +4 -2
- mlrun/feature_store/__init__.py +1 -0
- mlrun/feature_store/api.py +1 -2
- mlrun/feature_store/common.py +2 -1
- mlrun/feature_store/feature_set.py +1 -11
- mlrun/feature_store/feature_vector.py +340 -2
- mlrun/feature_store/ingestion.py +5 -10
- mlrun/feature_store/retrieval/base.py +118 -104
- mlrun/feature_store/retrieval/dask_merger.py +17 -10
- mlrun/feature_store/retrieval/job.py +4 -1
- mlrun/feature_store/retrieval/local_merger.py +18 -18
- mlrun/feature_store/retrieval/spark_merger.py +21 -14
- mlrun/feature_store/retrieval/storey_merger.py +22 -16
- mlrun/kfpops.py +3 -9
- mlrun/launcher/base.py +57 -53
- mlrun/launcher/client.py +5 -4
- mlrun/launcher/factory.py +24 -13
- mlrun/launcher/local.py +6 -6
- mlrun/launcher/remote.py +4 -4
- mlrun/lists.py +0 -11
- mlrun/model.py +11 -17
- mlrun/model_monitoring/__init__.py +2 -22
- mlrun/model_monitoring/features_drift_table.py +1 -1
- mlrun/model_monitoring/helpers.py +22 -210
- mlrun/model_monitoring/model_endpoint.py +1 -1
- mlrun/model_monitoring/model_monitoring_batch.py +127 -50
- mlrun/model_monitoring/prometheus.py +219 -0
- mlrun/model_monitoring/stores/__init__.py +16 -11
- mlrun/model_monitoring/stores/kv_model_endpoint_store.py +95 -23
- mlrun/model_monitoring/stores/models/mysql.py +47 -29
- mlrun/model_monitoring/stores/models/sqlite.py +47 -29
- mlrun/model_monitoring/stores/sql_model_endpoint_store.py +31 -19
- mlrun/model_monitoring/{stream_processing_fs.py → stream_processing.py} +206 -64
- mlrun/model_monitoring/tracking_policy.py +104 -0
- mlrun/package/packager.py +6 -8
- mlrun/package/packagers/default_packager.py +121 -10
- mlrun/package/packagers/numpy_packagers.py +1 -1
- mlrun/platforms/__init__.py +0 -2
- mlrun/platforms/iguazio.py +0 -56
- mlrun/projects/pipelines.py +53 -159
- mlrun/projects/project.py +10 -37
- mlrun/render.py +1 -1
- mlrun/run.py +8 -124
- mlrun/runtimes/__init__.py +6 -42
- mlrun/runtimes/base.py +29 -1249
- mlrun/runtimes/daskjob.py +2 -198
- mlrun/runtimes/funcdoc.py +0 -9
- mlrun/runtimes/function.py +25 -29
- mlrun/runtimes/kubejob.py +5 -29
- mlrun/runtimes/local.py +1 -1
- mlrun/runtimes/mpijob/__init__.py +2 -2
- mlrun/runtimes/mpijob/abstract.py +10 -1
- mlrun/runtimes/mpijob/v1.py +0 -76
- mlrun/runtimes/mpijob/v1alpha1.py +1 -74
- mlrun/runtimes/nuclio.py +3 -2
- mlrun/runtimes/pod.py +28 -18
- mlrun/runtimes/remotesparkjob.py +1 -15
- mlrun/runtimes/serving.py +14 -6
- mlrun/runtimes/sparkjob/__init__.py +0 -1
- mlrun/runtimes/sparkjob/abstract.py +4 -131
- mlrun/runtimes/utils.py +0 -26
- mlrun/serving/routers.py +7 -7
- mlrun/serving/server.py +11 -8
- mlrun/serving/states.py +7 -1
- mlrun/serving/v2_serving.py +6 -6
- mlrun/utils/helpers.py +23 -42
- mlrun/utils/notifications/notification/__init__.py +4 -0
- mlrun/utils/notifications/notification/webhook.py +61 -0
- mlrun/utils/notifications/notification_pusher.py +5 -25
- mlrun/utils/regex.py +7 -2
- mlrun/utils/version/version.json +2 -2
- {mlrun-1.4.0rc25.dist-info → mlrun-1.5.0rc2.dist-info}/METADATA +26 -25
- {mlrun-1.4.0rc25.dist-info → mlrun-1.5.0rc2.dist-info}/RECORD +180 -158
- {mlrun-1.4.0rc25.dist-info → mlrun-1.5.0rc2.dist-info}/WHEEL +1 -1
- mlrun/mlutils/data.py +0 -160
- mlrun/mlutils/models.py +0 -78
- mlrun/mlutils/plots.py +0 -902
- mlrun/utils/model_monitoring.py +0 -249
- /mlrun/{api/db/sqldb/session.py → common/db/sql_session.py} +0 -0
- {mlrun-1.4.0rc25.dist-info → mlrun-1.5.0rc2.dist-info}/LICENSE +0 -0
- {mlrun-1.4.0rc25.dist-info → mlrun-1.5.0rc2.dist-info}/entry_points.txt +0 -0
- {mlrun-1.4.0rc25.dist-info → mlrun-1.5.0rc2.dist-info}/top_level.txt +0 -0
|
@@ -20,14 +20,12 @@ import pandas as pd
|
|
|
20
20
|
from fastapi.concurrency import run_in_threadpool
|
|
21
21
|
from sqlalchemy.orm import Session
|
|
22
22
|
|
|
23
|
-
import mlrun.api.crud
|
|
24
23
|
import mlrun.api.utils.auth.verifier
|
|
25
|
-
import mlrun.common.model_monitoring
|
|
26
24
|
import mlrun.common.schemas
|
|
27
25
|
from mlrun.api.utils.singletons.project_member import get_project_member
|
|
26
|
+
from mlrun.common.model_monitoring.helpers import parse_model_endpoint_store_prefix
|
|
28
27
|
from mlrun.errors import MLRunBadRequestError
|
|
29
28
|
from mlrun.utils import config, logger
|
|
30
|
-
from mlrun.utils.model_monitoring import parse_model_endpoint_store_prefix
|
|
31
29
|
from mlrun.utils.v3io_clients import get_frames_client
|
|
32
30
|
|
|
33
31
|
|
|
@@ -62,7 +60,7 @@ async def grafana_list_endpoints(
|
|
|
62
60
|
body: Dict[str, Any],
|
|
63
61
|
query_parameters: Dict[str, str],
|
|
64
62
|
auth_info: mlrun.common.schemas.AuthInfo,
|
|
65
|
-
) -> List[mlrun.common.schemas.GrafanaTable]:
|
|
63
|
+
) -> List[mlrun.common.schemas.model_monitoring.grafana.GrafanaTable]:
|
|
66
64
|
project = query_parameters.get("project")
|
|
67
65
|
|
|
68
66
|
# Filters
|
|
@@ -111,27 +109,47 @@ async def grafana_list_endpoints(
|
|
|
111
109
|
endpoint_list.endpoints = allowed_endpoints
|
|
112
110
|
|
|
113
111
|
columns = [
|
|
114
|
-
mlrun.common.schemas.GrafanaColumn(
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
mlrun.common.schemas.GrafanaColumn(
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
mlrun.common.schemas.GrafanaColumn(
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
mlrun.common.schemas.GrafanaColumn(
|
|
112
|
+
mlrun.common.schemas.model_monitoring.grafana.GrafanaColumn(
|
|
113
|
+
text="endpoint_id", type="string"
|
|
114
|
+
),
|
|
115
|
+
mlrun.common.schemas.model_monitoring.grafana.GrafanaColumn(
|
|
116
|
+
text="endpoint_function", type="string"
|
|
117
|
+
),
|
|
118
|
+
mlrun.common.schemas.model_monitoring.grafana.GrafanaColumn(
|
|
119
|
+
text="endpoint_model", type="string"
|
|
120
|
+
),
|
|
121
|
+
mlrun.common.schemas.model_monitoring.grafana.GrafanaColumn(
|
|
122
|
+
text="endpoint_model_class", type="string"
|
|
123
|
+
),
|
|
124
|
+
mlrun.common.schemas.model_monitoring.grafana.GrafanaColumn(
|
|
125
|
+
text="first_request", type="time"
|
|
126
|
+
),
|
|
127
|
+
mlrun.common.schemas.model_monitoring.grafana.GrafanaColumn(
|
|
128
|
+
text="last_request", type="time"
|
|
129
|
+
),
|
|
130
|
+
mlrun.common.schemas.model_monitoring.grafana.GrafanaColumn(
|
|
131
|
+
text="accuracy", type="number"
|
|
132
|
+
),
|
|
133
|
+
mlrun.common.schemas.model_monitoring.grafana.GrafanaColumn(
|
|
134
|
+
text="error_count", type="number"
|
|
135
|
+
),
|
|
136
|
+
mlrun.common.schemas.model_monitoring.grafana.GrafanaColumn(
|
|
137
|
+
text="drift_status", type="number"
|
|
138
|
+
),
|
|
139
|
+
mlrun.common.schemas.model_monitoring.grafana.GrafanaColumn(
|
|
124
140
|
text="predictions_per_second", type="number"
|
|
125
141
|
),
|
|
126
|
-
mlrun.common.schemas.GrafanaColumn(
|
|
142
|
+
mlrun.common.schemas.model_monitoring.grafana.GrafanaColumn(
|
|
143
|
+
text="latency_avg_1h", type="number"
|
|
144
|
+
),
|
|
127
145
|
]
|
|
128
146
|
|
|
129
|
-
table = mlrun.common.schemas.GrafanaTable(columns=columns)
|
|
147
|
+
table = mlrun.common.schemas.model_monitoring.grafana.GrafanaTable(columns=columns)
|
|
130
148
|
for endpoint in endpoint_list.endpoints:
|
|
131
149
|
if (
|
|
132
150
|
filter_router
|
|
133
151
|
and endpoint.status.endpoint_type
|
|
134
|
-
== mlrun.common.model_monitoring.EndpointType.ROUTER
|
|
152
|
+
== mlrun.common.schemas.model_monitoring.EndpointType.ROUTER
|
|
135
153
|
):
|
|
136
154
|
continue
|
|
137
155
|
row = [
|
|
@@ -148,19 +166,21 @@ async def grafana_list_endpoints(
|
|
|
148
166
|
|
|
149
167
|
if (
|
|
150
168
|
endpoint.status.metrics
|
|
151
|
-
and mlrun.common.model_monitoring.EventKeyMetrics.GENERIC
|
|
169
|
+
and mlrun.common.schemas.model_monitoring.EventKeyMetrics.GENERIC
|
|
152
170
|
in endpoint.status.metrics
|
|
153
171
|
):
|
|
154
172
|
row.extend(
|
|
155
173
|
[
|
|
156
174
|
endpoint.status.metrics[
|
|
157
|
-
mlrun.common.model_monitoring.EventKeyMetrics.GENERIC
|
|
175
|
+
mlrun.common.schemas.model_monitoring.EventKeyMetrics.GENERIC
|
|
158
176
|
][
|
|
159
|
-
mlrun.common.model_monitoring.EventLiveStats.PREDICTIONS_PER_SECOND
|
|
177
|
+
mlrun.common.schemas.model_monitoring.EventLiveStats.PREDICTIONS_PER_SECOND
|
|
160
178
|
],
|
|
161
179
|
endpoint.status.metrics[
|
|
162
|
-
mlrun.common.model_monitoring.EventKeyMetrics.GENERIC
|
|
163
|
-
][
|
|
180
|
+
mlrun.common.schemas.model_monitoring.EventKeyMetrics.GENERIC
|
|
181
|
+
][
|
|
182
|
+
mlrun.common.schemas.model_monitoring.EventLiveStats.LATENCY_AVG_1H
|
|
183
|
+
],
|
|
164
184
|
]
|
|
165
185
|
)
|
|
166
186
|
|
|
@@ -197,18 +217,38 @@ async def grafana_individual_feature_analysis(
|
|
|
197
217
|
current_stats = endpoint.status.current_stats or {}
|
|
198
218
|
drift_measures = endpoint.status.drift_measures or {}
|
|
199
219
|
|
|
200
|
-
table = mlrun.common.schemas.GrafanaTable(
|
|
220
|
+
table = mlrun.common.schemas.model_monitoring.grafana.GrafanaTable(
|
|
201
221
|
columns=[
|
|
202
|
-
mlrun.common.schemas.GrafanaColumn(
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
mlrun.common.schemas.GrafanaColumn(
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
mlrun.common.schemas.GrafanaColumn(
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
mlrun.common.schemas.GrafanaColumn(
|
|
222
|
+
mlrun.common.schemas.model_monitoring.grafana.GrafanaColumn(
|
|
223
|
+
text="feature_name", type="string"
|
|
224
|
+
),
|
|
225
|
+
mlrun.common.schemas.model_monitoring.grafana.GrafanaColumn(
|
|
226
|
+
text="actual_min", type="number"
|
|
227
|
+
),
|
|
228
|
+
mlrun.common.schemas.model_monitoring.grafana.GrafanaColumn(
|
|
229
|
+
text="actual_mean", type="number"
|
|
230
|
+
),
|
|
231
|
+
mlrun.common.schemas.model_monitoring.grafana.GrafanaColumn(
|
|
232
|
+
text="actual_max", type="number"
|
|
233
|
+
),
|
|
234
|
+
mlrun.common.schemas.model_monitoring.grafana.GrafanaColumn(
|
|
235
|
+
text="expected_min", type="number"
|
|
236
|
+
),
|
|
237
|
+
mlrun.common.schemas.model_monitoring.grafana.GrafanaColumn(
|
|
238
|
+
text="expected_mean", type="number"
|
|
239
|
+
),
|
|
240
|
+
mlrun.common.schemas.model_monitoring.grafana.GrafanaColumn(
|
|
241
|
+
text="expected_max", type="number"
|
|
242
|
+
),
|
|
243
|
+
mlrun.common.schemas.model_monitoring.grafana.GrafanaColumn(
|
|
244
|
+
text="tvd", type="number"
|
|
245
|
+
),
|
|
246
|
+
mlrun.common.schemas.model_monitoring.grafana.GrafanaColumn(
|
|
247
|
+
text="hellinger", type="number"
|
|
248
|
+
),
|
|
249
|
+
mlrun.common.schemas.model_monitoring.grafana.GrafanaColumn(
|
|
250
|
+
text="kld", type="number"
|
|
251
|
+
),
|
|
212
252
|
]
|
|
213
253
|
)
|
|
214
254
|
|
|
@@ -254,14 +294,26 @@ async def grafana_overall_feature_analysis(
|
|
|
254
294
|
feature_analysis=True,
|
|
255
295
|
)
|
|
256
296
|
|
|
257
|
-
table = mlrun.common.schemas.GrafanaTable(
|
|
297
|
+
table = mlrun.common.schemas.model_monitoring.grafana.GrafanaTable(
|
|
258
298
|
columns=[
|
|
259
|
-
mlrun.common.schemas.GrafanaNumberColumn(
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
mlrun.common.schemas.GrafanaNumberColumn(
|
|
263
|
-
|
|
264
|
-
|
|
299
|
+
mlrun.common.schemas.model_monitoring.grafana.GrafanaNumberColumn(
|
|
300
|
+
text="tvd_sum"
|
|
301
|
+
),
|
|
302
|
+
mlrun.common.schemas.model_monitoring.grafana.GrafanaNumberColumn(
|
|
303
|
+
text="tvd_mean"
|
|
304
|
+
),
|
|
305
|
+
mlrun.common.schemas.model_monitoring.grafana.GrafanaNumberColumn(
|
|
306
|
+
text="hellinger_sum"
|
|
307
|
+
),
|
|
308
|
+
mlrun.common.schemas.model_monitoring.grafana.GrafanaNumberColumn(
|
|
309
|
+
text="hellinger_mean"
|
|
310
|
+
),
|
|
311
|
+
mlrun.common.schemas.model_monitoring.grafana.GrafanaNumberColumn(
|
|
312
|
+
text="kld_sum"
|
|
313
|
+
),
|
|
314
|
+
mlrun.common.schemas.model_monitoring.grafana.GrafanaNumberColumn(
|
|
315
|
+
text="kld_mean"
|
|
316
|
+
),
|
|
265
317
|
]
|
|
266
318
|
)
|
|
267
319
|
|
|
@@ -339,9 +391,11 @@ async def grafana_incoming_features(
|
|
|
339
391
|
data.index = data.index.astype(np.int64) // 10**6
|
|
340
392
|
|
|
341
393
|
for feature, indexed_values in data.to_dict().items():
|
|
342
|
-
target = mlrun.common.schemas.GrafanaTimeSeriesTarget(
|
|
394
|
+
target = mlrun.common.schemas.model_monitoring.grafana.GrafanaTimeSeriesTarget(
|
|
395
|
+
target=feature
|
|
396
|
+
)
|
|
343
397
|
for index, value in indexed_values.items():
|
|
344
|
-
data_point = mlrun.common.schemas.GrafanaDataPoint(
|
|
398
|
+
data_point = mlrun.common.schemas.model_monitoring.grafana.GrafanaDataPoint(
|
|
345
399
|
value=float(value), timestamp=index
|
|
346
400
|
)
|
|
347
401
|
target.add_data_point(data_point)
|
|
@@ -0,0 +1,159 @@
|
|
|
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 json
|
|
16
|
+
import math
|
|
17
|
+
import typing
|
|
18
|
+
|
|
19
|
+
import sqlalchemy.orm
|
|
20
|
+
|
|
21
|
+
import mlrun.api
|
|
22
|
+
import mlrun.common
|
|
23
|
+
import mlrun.common.model_monitoring.helpers
|
|
24
|
+
import mlrun.common.schemas.schedule
|
|
25
|
+
import mlrun.errors
|
|
26
|
+
|
|
27
|
+
Seconds = typing.NewType("Seconds", int)
|
|
28
|
+
Minutes = typing.NewType("Minutes", int)
|
|
29
|
+
|
|
30
|
+
_SECONDS_IN_MINUTE: Seconds = Seconds(60)
|
|
31
|
+
_MINUTES_IN_HOUR: Minutes = Minutes(60)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def seconds2minutes(seconds: Seconds) -> Minutes:
|
|
35
|
+
return Minutes(math.ceil(seconds / _SECONDS_IN_MINUTE))
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def get_batching_interval_param(intervals_list: typing.List):
|
|
39
|
+
"""Convert each value in the intervals list into a float number. None
|
|
40
|
+
Values will be converted into 0.0.
|
|
41
|
+
|
|
42
|
+
param intervals_list: A list of values based on the ScheduleCronTrigger expression. Note that at the moment
|
|
43
|
+
it supports minutes, hours, and days. e.g. [0, '*/1', None] represents on the hour
|
|
44
|
+
every hour.
|
|
45
|
+
|
|
46
|
+
:return: A tuple of:
|
|
47
|
+
[0] = minutes interval as a float
|
|
48
|
+
[1] = hours interval as a float
|
|
49
|
+
[2] = days interval as a float
|
|
50
|
+
"""
|
|
51
|
+
return tuple(
|
|
52
|
+
[
|
|
53
|
+
0.0
|
|
54
|
+
if isinstance(interval, (float, int)) or interval is None
|
|
55
|
+
else float(f"0{interval.partition('/')[-1]}")
|
|
56
|
+
for interval in intervals_list
|
|
57
|
+
]
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def _add_minutes_offset(
|
|
62
|
+
minute: typing.Optional[typing.Union[int, str]],
|
|
63
|
+
offset: Minutes,
|
|
64
|
+
) -> typing.Optional[typing.Union[int, str]]:
|
|
65
|
+
"""
|
|
66
|
+
:param minute: the minute specification in the cron schedule, e.g. "0".
|
|
67
|
+
:param offset: the offset in minutes to add to the cron minute specification.
|
|
68
|
+
:return: the minute cron with the offset applied (if supported).
|
|
69
|
+
"""
|
|
70
|
+
if minute and (
|
|
71
|
+
(isinstance(minute, str) and str.isdigit(minute)) or isinstance(minute, int)
|
|
72
|
+
):
|
|
73
|
+
minute = (int(minute) + offset) % _MINUTES_IN_HOUR
|
|
74
|
+
return minute
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def convert_to_cron_string(
|
|
78
|
+
cron_trigger: mlrun.common.schemas.schedule.ScheduleCronTrigger,
|
|
79
|
+
minute_delay: Minutes = Minutes(0),
|
|
80
|
+
) -> str:
|
|
81
|
+
"""Convert the batch interval `ScheduleCronTrigger` into a cron trigger expression"""
|
|
82
|
+
return "{} {} {} * *".format(
|
|
83
|
+
_add_minutes_offset(cron_trigger.minute, minute_delay),
|
|
84
|
+
cron_trigger.hour,
|
|
85
|
+
cron_trigger.day,
|
|
86
|
+
).replace("None", "*")
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def clean_feature_name(feature_name):
|
|
90
|
+
return feature_name.replace(" ", "_").replace("(", "").replace(")", "")
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def json_loads_if_not_none(field: typing.Any) -> typing.Any:
|
|
94
|
+
return (
|
|
95
|
+
json.loads(field) if field and field != "null" and field is not None else None
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def get_access_key(auth_info: mlrun.common.schemas.AuthInfo):
|
|
100
|
+
"""
|
|
101
|
+
Get access key from the current data session. This method is usually used to verify that the session
|
|
102
|
+
is valid and contains an access key.
|
|
103
|
+
|
|
104
|
+
param auth_info: The auth info of the request.
|
|
105
|
+
|
|
106
|
+
:return: Access key as a string.
|
|
107
|
+
"""
|
|
108
|
+
access_key = auth_info.data_session
|
|
109
|
+
if not access_key:
|
|
110
|
+
raise mlrun.errors.MLRunBadRequestError("Data session is missing")
|
|
111
|
+
return access_key
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def get_monitoring_parquet_path(
|
|
115
|
+
db_session: sqlalchemy.orm.Session, project: str
|
|
116
|
+
) -> str:
|
|
117
|
+
"""Get model monitoring parquet target for the current project. The parquet target path is based on the
|
|
118
|
+
project artifact path. If project artifact path is not defined, the parquet target path will be based on MLRun
|
|
119
|
+
artifact path.
|
|
120
|
+
|
|
121
|
+
:param db_session: A session that manages the current dialog with the database. Will be used in this function
|
|
122
|
+
to get the project record from DB.
|
|
123
|
+
:param project: Project name.
|
|
124
|
+
|
|
125
|
+
:return: Monitoring parquet target path.
|
|
126
|
+
"""
|
|
127
|
+
|
|
128
|
+
# Get the artifact path from the project record that was stored in the DB
|
|
129
|
+
project_obj = mlrun.api.crud.projects.Projects().get_project(
|
|
130
|
+
session=db_session, name=project
|
|
131
|
+
)
|
|
132
|
+
artifact_path = project_obj.spec.artifact_path
|
|
133
|
+
# Generate monitoring parquet path value
|
|
134
|
+
parquet_path = mlrun.mlconf.get_model_monitoring_file_target_path(
|
|
135
|
+
project=project,
|
|
136
|
+
kind=mlrun.common.schemas.model_monitoring.FileTargetKind.PARQUET,
|
|
137
|
+
target="offline",
|
|
138
|
+
artifact_path=artifact_path,
|
|
139
|
+
)
|
|
140
|
+
return parquet_path
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
def get_stream_path(project: str = None):
|
|
144
|
+
"""Get stream path from the project secret. If wasn't set, take it from the system configurations"""
|
|
145
|
+
|
|
146
|
+
stream_uri = mlrun.api.crud.secrets.Secrets().get_project_secret(
|
|
147
|
+
project=project,
|
|
148
|
+
provider=mlrun.common.schemas.secret.SecretProviderName.kubernetes,
|
|
149
|
+
allow_secrets_from_k8s=True,
|
|
150
|
+
secret_key=mlrun.common.schemas.model_monitoring.ProjectSecretKeys.STREAM_PATH,
|
|
151
|
+
) or mlrun.mlconf.get_model_monitoring_file_target_path(
|
|
152
|
+
project=project,
|
|
153
|
+
kind=mlrun.common.schemas.model_monitoring.FileTargetKind.STREAM,
|
|
154
|
+
target="online",
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
return mlrun.common.model_monitoring.helpers.parse_monitoring_stream_path(
|
|
158
|
+
stream_uri=stream_uri, project=project
|
|
159
|
+
)
|