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.

Files changed (184) hide show
  1. mlrun/__init__.py +2 -35
  2. mlrun/__main__.py +3 -41
  3. mlrun/api/api/api.py +6 -0
  4. mlrun/api/api/endpoints/feature_store.py +0 -4
  5. mlrun/api/api/endpoints/files.py +14 -2
  6. mlrun/api/api/endpoints/frontend_spec.py +2 -1
  7. mlrun/api/api/endpoints/functions.py +95 -59
  8. mlrun/api/api/endpoints/grafana_proxy.py +9 -9
  9. mlrun/api/api/endpoints/logs.py +17 -3
  10. mlrun/api/api/endpoints/model_endpoints.py +3 -2
  11. mlrun/api/api/endpoints/pipelines.py +1 -5
  12. mlrun/api/api/endpoints/projects.py +88 -0
  13. mlrun/api/api/endpoints/runs.py +48 -6
  14. mlrun/api/api/endpoints/submit.py +2 -1
  15. mlrun/api/api/endpoints/workflows.py +355 -0
  16. mlrun/api/api/utils.py +3 -4
  17. mlrun/api/crud/__init__.py +1 -0
  18. mlrun/api/crud/client_spec.py +6 -2
  19. mlrun/api/crud/feature_store.py +5 -0
  20. mlrun/api/crud/model_monitoring/__init__.py +1 -0
  21. mlrun/api/crud/model_monitoring/deployment.py +497 -0
  22. mlrun/api/crud/model_monitoring/grafana.py +96 -42
  23. mlrun/api/crud/model_monitoring/helpers.py +159 -0
  24. mlrun/api/crud/model_monitoring/model_endpoints.py +202 -476
  25. mlrun/api/crud/notifications.py +9 -4
  26. mlrun/api/crud/pipelines.py +6 -11
  27. mlrun/api/crud/projects.py +2 -2
  28. mlrun/api/crud/runtime_resources.py +4 -3
  29. mlrun/api/crud/runtimes/nuclio/helpers.py +5 -1
  30. mlrun/api/crud/secrets.py +21 -0
  31. mlrun/api/crud/workflows.py +352 -0
  32. mlrun/api/db/base.py +16 -1
  33. mlrun/api/db/init_db.py +2 -4
  34. mlrun/api/db/session.py +1 -1
  35. mlrun/api/db/sqldb/db.py +129 -31
  36. mlrun/api/db/sqldb/models/models_mysql.py +15 -1
  37. mlrun/api/db/sqldb/models/models_sqlite.py +16 -2
  38. mlrun/api/launcher.py +38 -6
  39. mlrun/api/main.py +3 -2
  40. mlrun/api/rundb/__init__.py +13 -0
  41. mlrun/{db → api/rundb}/sqldb.py +36 -84
  42. mlrun/api/runtime_handlers/__init__.py +56 -0
  43. mlrun/api/runtime_handlers/base.py +1247 -0
  44. mlrun/api/runtime_handlers/daskjob.py +209 -0
  45. mlrun/api/runtime_handlers/kubejob.py +37 -0
  46. mlrun/api/runtime_handlers/mpijob.py +147 -0
  47. mlrun/api/runtime_handlers/remotesparkjob.py +29 -0
  48. mlrun/api/runtime_handlers/sparkjob.py +148 -0
  49. mlrun/api/schemas/__init__.py +17 -6
  50. mlrun/api/utils/builder.py +1 -4
  51. mlrun/api/utils/clients/chief.py +14 -0
  52. mlrun/api/utils/clients/iguazio.py +33 -33
  53. mlrun/api/utils/clients/nuclio.py +2 -2
  54. mlrun/api/utils/periodic.py +9 -2
  55. mlrun/api/utils/projects/follower.py +14 -7
  56. mlrun/api/utils/projects/leader.py +2 -1
  57. mlrun/api/utils/projects/remotes/nop_follower.py +2 -2
  58. mlrun/api/utils/projects/remotes/nop_leader.py +2 -2
  59. mlrun/api/utils/runtimes/__init__.py +14 -0
  60. mlrun/api/utils/runtimes/nuclio.py +43 -0
  61. mlrun/api/utils/scheduler.py +98 -15
  62. mlrun/api/utils/singletons/db.py +5 -1
  63. mlrun/api/utils/singletons/project_member.py +4 -1
  64. mlrun/api/utils/singletons/scheduler.py +1 -1
  65. mlrun/artifacts/base.py +6 -6
  66. mlrun/artifacts/dataset.py +4 -4
  67. mlrun/artifacts/manager.py +2 -3
  68. mlrun/artifacts/model.py +2 -2
  69. mlrun/artifacts/plots.py +8 -8
  70. mlrun/common/db/__init__.py +14 -0
  71. mlrun/common/helpers.py +37 -0
  72. mlrun/{mlutils → common/model_monitoring}/__init__.py +3 -2
  73. mlrun/common/model_monitoring/helpers.py +69 -0
  74. mlrun/common/schemas/__init__.py +13 -1
  75. mlrun/common/schemas/auth.py +4 -1
  76. mlrun/common/schemas/client_spec.py +1 -1
  77. mlrun/common/schemas/function.py +17 -0
  78. mlrun/common/schemas/model_monitoring/__init__.py +48 -0
  79. mlrun/common/{model_monitoring.py → schemas/model_monitoring/constants.py} +11 -23
  80. mlrun/common/schemas/model_monitoring/grafana.py +55 -0
  81. mlrun/common/schemas/{model_endpoints.py → model_monitoring/model_endpoints.py} +32 -65
  82. mlrun/common/schemas/notification.py +1 -0
  83. mlrun/common/schemas/object.py +4 -0
  84. mlrun/common/schemas/project.py +1 -0
  85. mlrun/common/schemas/regex.py +1 -1
  86. mlrun/common/schemas/runs.py +1 -8
  87. mlrun/common/schemas/schedule.py +1 -8
  88. mlrun/common/schemas/workflow.py +54 -0
  89. mlrun/config.py +45 -42
  90. mlrun/datastore/__init__.py +21 -0
  91. mlrun/datastore/base.py +1 -1
  92. mlrun/datastore/datastore.py +9 -0
  93. mlrun/datastore/dbfs_store.py +168 -0
  94. mlrun/datastore/helpers.py +18 -0
  95. mlrun/datastore/sources.py +1 -0
  96. mlrun/datastore/store_resources.py +2 -5
  97. mlrun/datastore/v3io.py +1 -2
  98. mlrun/db/__init__.py +4 -68
  99. mlrun/db/base.py +12 -0
  100. mlrun/db/factory.py +65 -0
  101. mlrun/db/httpdb.py +175 -20
  102. mlrun/db/nopdb.py +4 -2
  103. mlrun/execution.py +4 -2
  104. mlrun/feature_store/__init__.py +1 -0
  105. mlrun/feature_store/api.py +1 -2
  106. mlrun/feature_store/common.py +2 -1
  107. mlrun/feature_store/feature_set.py +1 -11
  108. mlrun/feature_store/feature_vector.py +340 -2
  109. mlrun/feature_store/ingestion.py +5 -10
  110. mlrun/feature_store/retrieval/base.py +118 -104
  111. mlrun/feature_store/retrieval/dask_merger.py +17 -10
  112. mlrun/feature_store/retrieval/job.py +4 -1
  113. mlrun/feature_store/retrieval/local_merger.py +18 -18
  114. mlrun/feature_store/retrieval/spark_merger.py +21 -14
  115. mlrun/feature_store/retrieval/storey_merger.py +22 -16
  116. mlrun/kfpops.py +3 -9
  117. mlrun/launcher/base.py +57 -53
  118. mlrun/launcher/client.py +5 -4
  119. mlrun/launcher/factory.py +24 -13
  120. mlrun/launcher/local.py +6 -6
  121. mlrun/launcher/remote.py +4 -4
  122. mlrun/lists.py +0 -11
  123. mlrun/model.py +11 -17
  124. mlrun/model_monitoring/__init__.py +2 -22
  125. mlrun/model_monitoring/features_drift_table.py +1 -1
  126. mlrun/model_monitoring/helpers.py +22 -210
  127. mlrun/model_monitoring/model_endpoint.py +1 -1
  128. mlrun/model_monitoring/model_monitoring_batch.py +127 -50
  129. mlrun/model_monitoring/prometheus.py +219 -0
  130. mlrun/model_monitoring/stores/__init__.py +16 -11
  131. mlrun/model_monitoring/stores/kv_model_endpoint_store.py +95 -23
  132. mlrun/model_monitoring/stores/models/mysql.py +47 -29
  133. mlrun/model_monitoring/stores/models/sqlite.py +47 -29
  134. mlrun/model_monitoring/stores/sql_model_endpoint_store.py +31 -19
  135. mlrun/model_monitoring/{stream_processing_fs.py → stream_processing.py} +206 -64
  136. mlrun/model_monitoring/tracking_policy.py +104 -0
  137. mlrun/package/packager.py +6 -8
  138. mlrun/package/packagers/default_packager.py +121 -10
  139. mlrun/package/packagers/numpy_packagers.py +1 -1
  140. mlrun/platforms/__init__.py +0 -2
  141. mlrun/platforms/iguazio.py +0 -56
  142. mlrun/projects/pipelines.py +53 -159
  143. mlrun/projects/project.py +10 -37
  144. mlrun/render.py +1 -1
  145. mlrun/run.py +8 -124
  146. mlrun/runtimes/__init__.py +6 -42
  147. mlrun/runtimes/base.py +29 -1249
  148. mlrun/runtimes/daskjob.py +2 -198
  149. mlrun/runtimes/funcdoc.py +0 -9
  150. mlrun/runtimes/function.py +25 -29
  151. mlrun/runtimes/kubejob.py +5 -29
  152. mlrun/runtimes/local.py +1 -1
  153. mlrun/runtimes/mpijob/__init__.py +2 -2
  154. mlrun/runtimes/mpijob/abstract.py +10 -1
  155. mlrun/runtimes/mpijob/v1.py +0 -76
  156. mlrun/runtimes/mpijob/v1alpha1.py +1 -74
  157. mlrun/runtimes/nuclio.py +3 -2
  158. mlrun/runtimes/pod.py +28 -18
  159. mlrun/runtimes/remotesparkjob.py +1 -15
  160. mlrun/runtimes/serving.py +14 -6
  161. mlrun/runtimes/sparkjob/__init__.py +0 -1
  162. mlrun/runtimes/sparkjob/abstract.py +4 -131
  163. mlrun/runtimes/utils.py +0 -26
  164. mlrun/serving/routers.py +7 -7
  165. mlrun/serving/server.py +11 -8
  166. mlrun/serving/states.py +7 -1
  167. mlrun/serving/v2_serving.py +6 -6
  168. mlrun/utils/helpers.py +23 -42
  169. mlrun/utils/notifications/notification/__init__.py +4 -0
  170. mlrun/utils/notifications/notification/webhook.py +61 -0
  171. mlrun/utils/notifications/notification_pusher.py +5 -25
  172. mlrun/utils/regex.py +7 -2
  173. mlrun/utils/version/version.json +2 -2
  174. {mlrun-1.4.0rc25.dist-info → mlrun-1.5.0rc2.dist-info}/METADATA +26 -25
  175. {mlrun-1.4.0rc25.dist-info → mlrun-1.5.0rc2.dist-info}/RECORD +180 -158
  176. {mlrun-1.4.0rc25.dist-info → mlrun-1.5.0rc2.dist-info}/WHEEL +1 -1
  177. mlrun/mlutils/data.py +0 -160
  178. mlrun/mlutils/models.py +0 -78
  179. mlrun/mlutils/plots.py +0 -902
  180. mlrun/utils/model_monitoring.py +0 -249
  181. /mlrun/{api/db/sqldb/session.py → common/db/sql_session.py} +0 -0
  182. {mlrun-1.4.0rc25.dist-info → mlrun-1.5.0rc2.dist-info}/LICENSE +0 -0
  183. {mlrun-1.4.0rc25.dist-info → mlrun-1.5.0rc2.dist-info}/entry_points.txt +0 -0
  184. {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(text="endpoint_id", type="string"),
115
- mlrun.common.schemas.GrafanaColumn(text="endpoint_function", type="string"),
116
- mlrun.common.schemas.GrafanaColumn(text="endpoint_model", type="string"),
117
- mlrun.common.schemas.GrafanaColumn(text="endpoint_model_class", type="string"),
118
- mlrun.common.schemas.GrafanaColumn(text="first_request", type="time"),
119
- mlrun.common.schemas.GrafanaColumn(text="last_request", type="time"),
120
- mlrun.common.schemas.GrafanaColumn(text="accuracy", type="number"),
121
- mlrun.common.schemas.GrafanaColumn(text="error_count", type="number"),
122
- mlrun.common.schemas.GrafanaColumn(text="drift_status", type="number"),
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(text="latency_avg_1h", type="number"),
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
- ][mlrun.common.model_monitoring.EventLiveStats.LATENCY_AVG_1H],
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(text="feature_name", type="string"),
203
- mlrun.common.schemas.GrafanaColumn(text="actual_min", type="number"),
204
- mlrun.common.schemas.GrafanaColumn(text="actual_mean", type="number"),
205
- mlrun.common.schemas.GrafanaColumn(text="actual_max", type="number"),
206
- mlrun.common.schemas.GrafanaColumn(text="expected_min", type="number"),
207
- mlrun.common.schemas.GrafanaColumn(text="expected_mean", type="number"),
208
- mlrun.common.schemas.GrafanaColumn(text="expected_max", type="number"),
209
- mlrun.common.schemas.GrafanaColumn(text="tvd", type="number"),
210
- mlrun.common.schemas.GrafanaColumn(text="hellinger", type="number"),
211
- mlrun.common.schemas.GrafanaColumn(text="kld", type="number"),
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(text="tvd_sum"),
260
- mlrun.common.schemas.GrafanaNumberColumn(text="tvd_mean"),
261
- mlrun.common.schemas.GrafanaNumberColumn(text="hellinger_sum"),
262
- mlrun.common.schemas.GrafanaNumberColumn(text="hellinger_mean"),
263
- mlrun.common.schemas.GrafanaNumberColumn(text="kld_sum"),
264
- mlrun.common.schemas.GrafanaNumberColumn(text="kld_mean"),
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(target=feature)
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
+ )