mlrun 1.3.3rc1__py3-none-any.whl → 1.4.0__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 (444) hide show
  1. mlrun/__init__.py +3 -3
  2. mlrun/__main__.py +79 -37
  3. mlrun/api/__init__.py +1 -1
  4. mlrun/api/api/__init__.py +1 -1
  5. mlrun/api/api/api.py +4 -4
  6. mlrun/api/api/deps.py +10 -21
  7. mlrun/api/api/endpoints/__init__.py +1 -1
  8. mlrun/api/api/endpoints/artifacts.py +64 -36
  9. mlrun/api/api/endpoints/auth.py +4 -4
  10. mlrun/api/api/endpoints/background_tasks.py +11 -11
  11. mlrun/api/api/endpoints/client_spec.py +5 -5
  12. mlrun/api/api/endpoints/clusterization_spec.py +6 -4
  13. mlrun/api/api/endpoints/feature_store.py +124 -115
  14. mlrun/api/api/endpoints/files.py +22 -14
  15. mlrun/api/api/endpoints/frontend_spec.py +28 -21
  16. mlrun/api/api/endpoints/functions.py +142 -87
  17. mlrun/api/api/endpoints/grafana_proxy.py +89 -442
  18. mlrun/api/api/endpoints/healthz.py +20 -7
  19. mlrun/api/api/endpoints/hub.py +320 -0
  20. mlrun/api/api/endpoints/internal/__init__.py +1 -1
  21. mlrun/api/api/endpoints/internal/config.py +1 -1
  22. mlrun/api/api/endpoints/internal/memory_reports.py +9 -9
  23. mlrun/api/api/endpoints/logs.py +11 -11
  24. mlrun/api/api/endpoints/model_endpoints.py +74 -70
  25. mlrun/api/api/endpoints/operations.py +13 -9
  26. mlrun/api/api/endpoints/pipelines.py +93 -88
  27. mlrun/api/api/endpoints/projects.py +35 -35
  28. mlrun/api/api/endpoints/runs.py +69 -27
  29. mlrun/api/api/endpoints/runtime_resources.py +28 -28
  30. mlrun/api/api/endpoints/schedules.py +98 -41
  31. mlrun/api/api/endpoints/secrets.py +37 -32
  32. mlrun/api/api/endpoints/submit.py +12 -12
  33. mlrun/api/api/endpoints/tags.py +20 -22
  34. mlrun/api/api/utils.py +251 -42
  35. mlrun/api/constants.py +1 -1
  36. mlrun/api/crud/__init__.py +18 -15
  37. mlrun/api/crud/artifacts.py +10 -10
  38. mlrun/api/crud/client_spec.py +4 -4
  39. mlrun/api/crud/clusterization_spec.py +3 -3
  40. mlrun/api/crud/feature_store.py +54 -46
  41. mlrun/api/crud/functions.py +3 -3
  42. mlrun/api/crud/hub.py +312 -0
  43. mlrun/api/crud/logs.py +11 -9
  44. mlrun/api/crud/model_monitoring/__init__.py +3 -3
  45. mlrun/api/crud/model_monitoring/grafana.py +435 -0
  46. mlrun/api/crud/model_monitoring/model_endpoints.py +352 -129
  47. mlrun/api/crud/notifications.py +149 -0
  48. mlrun/api/crud/pipelines.py +67 -52
  49. mlrun/api/crud/projects.py +51 -23
  50. mlrun/api/crud/runs.py +7 -5
  51. mlrun/api/crud/runtime_resources.py +13 -13
  52. mlrun/api/{db/filedb → crud/runtimes}/__init__.py +1 -1
  53. mlrun/api/crud/runtimes/nuclio/__init__.py +14 -0
  54. mlrun/api/crud/runtimes/nuclio/function.py +505 -0
  55. mlrun/api/crud/runtimes/nuclio/helpers.py +310 -0
  56. mlrun/api/crud/secrets.py +88 -46
  57. mlrun/api/crud/tags.py +5 -5
  58. mlrun/api/db/__init__.py +1 -1
  59. mlrun/api/db/base.py +102 -54
  60. mlrun/api/db/init_db.py +2 -3
  61. mlrun/api/db/session.py +4 -12
  62. mlrun/api/db/sqldb/__init__.py +1 -1
  63. mlrun/api/db/sqldb/db.py +439 -196
  64. mlrun/api/db/sqldb/helpers.py +1 -1
  65. mlrun/api/db/sqldb/models/__init__.py +3 -3
  66. mlrun/api/db/sqldb/models/models_mysql.py +82 -64
  67. mlrun/api/db/sqldb/models/models_sqlite.py +76 -64
  68. mlrun/api/db/sqldb/session.py +27 -20
  69. mlrun/api/initial_data.py +82 -24
  70. mlrun/api/launcher.py +196 -0
  71. mlrun/api/main.py +91 -22
  72. mlrun/api/middlewares.py +6 -5
  73. mlrun/api/migrations_mysql/env.py +1 -1
  74. mlrun/api/migrations_mysql/versions/28383af526f3_market_place_to_hub.py +40 -0
  75. mlrun/api/migrations_mysql/versions/32bae1b0e29c_increase_timestamp_fields_precision.py +1 -1
  76. mlrun/api/migrations_mysql/versions/4903aef6a91d_tag_foreign_key_and_cascades.py +1 -1
  77. mlrun/api/migrations_mysql/versions/5f1351c88a19_adding_background_tasks_table.py +1 -1
  78. mlrun/api/migrations_mysql/versions/88e656800d6a_add_requested_logs_column_and_index_to_.py +1 -1
  79. mlrun/api/migrations_mysql/versions/9d16de5f03a7_adding_data_versions_table.py +1 -1
  80. mlrun/api/migrations_mysql/versions/b86f5b53f3d7_adding_name_and_updated_to_runs_table.py +1 -1
  81. mlrun/api/migrations_mysql/versions/c4af40b0bf61_init.py +1 -1
  82. mlrun/api/migrations_mysql/versions/c905d15bd91d_notifications.py +72 -0
  83. mlrun/api/migrations_mysql/versions/ee041e8fdaa0_adding_next_run_time_column_to_schedule_.py +1 -1
  84. mlrun/api/migrations_sqlite/env.py +1 -1
  85. mlrun/api/migrations_sqlite/versions/11f8dd2dc9fe_init.py +1 -1
  86. mlrun/api/migrations_sqlite/versions/1c954f8cb32d_schedule_last_run_uri.py +1 -1
  87. mlrun/api/migrations_sqlite/versions/2b6d23c715aa_adding_feature_sets.py +1 -1
  88. mlrun/api/migrations_sqlite/versions/4acd9430b093_market_place_to_hub.py +77 -0
  89. mlrun/api/migrations_sqlite/versions/6401142f2d7c_adding_next_run_time_column_to_schedule_.py +1 -1
  90. mlrun/api/migrations_sqlite/versions/64d90a1a69bc_adding_background_tasks_table.py +1 -1
  91. mlrun/api/migrations_sqlite/versions/803438ecd005_add_requested_logs_column_to_runs.py +1 -1
  92. mlrun/api/migrations_sqlite/versions/863114f0c659_refactoring_feature_set.py +1 -1
  93. mlrun/api/migrations_sqlite/versions/959ae00528ad_notifications.py +63 -0
  94. mlrun/api/migrations_sqlite/versions/accf9fc83d38_adding_data_versions_table.py +1 -1
  95. mlrun/api/migrations_sqlite/versions/b68e8e897a28_schedule_labels.py +1 -1
  96. mlrun/api/migrations_sqlite/versions/bcd0c1f9720c_adding_project_labels.py +1 -1
  97. mlrun/api/migrations_sqlite/versions/cf21882f938e_schedule_id.py +1 -1
  98. mlrun/api/migrations_sqlite/versions/d781f58f607f_tag_object_name_string.py +1 -1
  99. mlrun/api/migrations_sqlite/versions/deac06871ace_adding_marketplace_sources_table.py +1 -1
  100. mlrun/api/migrations_sqlite/versions/e1dd5983c06b_schedule_concurrency_limit.py +1 -1
  101. mlrun/api/migrations_sqlite/versions/e5594ed3ab53_adding_name_and_updated_to_runs_table.py +1 -1
  102. mlrun/api/migrations_sqlite/versions/f4249b4ba6fa_adding_feature_vectors.py +1 -1
  103. mlrun/api/migrations_sqlite/versions/f7b5a1a03629_adding_feature_labels.py +1 -1
  104. mlrun/api/schemas/__init__.py +216 -138
  105. mlrun/api/utils/__init__.py +1 -1
  106. mlrun/api/utils/asyncio.py +1 -1
  107. mlrun/api/utils/auth/__init__.py +1 -1
  108. mlrun/api/utils/auth/providers/__init__.py +1 -1
  109. mlrun/api/utils/auth/providers/base.py +7 -7
  110. mlrun/api/utils/auth/providers/nop.py +6 -7
  111. mlrun/api/utils/auth/providers/opa.py +17 -17
  112. mlrun/api/utils/auth/verifier.py +36 -34
  113. mlrun/api/utils/background_tasks.py +24 -24
  114. mlrun/{builder.py → api/utils/builder.py} +216 -123
  115. mlrun/api/utils/clients/__init__.py +1 -1
  116. mlrun/api/utils/clients/chief.py +19 -4
  117. mlrun/api/utils/clients/iguazio.py +106 -60
  118. mlrun/api/utils/clients/log_collector.py +1 -1
  119. mlrun/api/utils/clients/nuclio.py +23 -23
  120. mlrun/api/utils/clients/protocols/grpc.py +2 -2
  121. mlrun/api/utils/db/__init__.py +1 -1
  122. mlrun/api/utils/db/alembic.py +1 -1
  123. mlrun/api/utils/db/backup.py +1 -1
  124. mlrun/api/utils/db/mysql.py +24 -25
  125. mlrun/api/utils/db/sql_collation.py +1 -1
  126. mlrun/api/utils/db/sqlite_migration.py +2 -2
  127. mlrun/api/utils/events/__init__.py +14 -0
  128. mlrun/api/utils/events/base.py +57 -0
  129. mlrun/api/utils/events/events_factory.py +41 -0
  130. mlrun/api/utils/events/iguazio.py +217 -0
  131. mlrun/api/utils/events/nop.py +55 -0
  132. mlrun/api/utils/helpers.py +16 -13
  133. mlrun/api/utils/memory_reports.py +1 -1
  134. mlrun/api/utils/periodic.py +6 -3
  135. mlrun/api/utils/projects/__init__.py +1 -1
  136. mlrun/api/utils/projects/follower.py +33 -33
  137. mlrun/api/utils/projects/leader.py +36 -34
  138. mlrun/api/utils/projects/member.py +27 -27
  139. mlrun/api/utils/projects/remotes/__init__.py +1 -1
  140. mlrun/api/utils/projects/remotes/follower.py +13 -13
  141. mlrun/api/utils/projects/remotes/leader.py +10 -10
  142. mlrun/api/utils/projects/remotes/nop_follower.py +27 -21
  143. mlrun/api/utils/projects/remotes/nop_leader.py +17 -16
  144. mlrun/api/utils/scheduler.py +140 -51
  145. mlrun/api/utils/singletons/__init__.py +1 -1
  146. mlrun/api/utils/singletons/db.py +9 -15
  147. mlrun/api/utils/singletons/k8s.py +677 -5
  148. mlrun/api/utils/singletons/logs_dir.py +1 -1
  149. mlrun/api/utils/singletons/project_member.py +1 -1
  150. mlrun/api/utils/singletons/scheduler.py +1 -1
  151. mlrun/artifacts/__init__.py +2 -2
  152. mlrun/artifacts/base.py +8 -2
  153. mlrun/artifacts/dataset.py +5 -3
  154. mlrun/artifacts/manager.py +7 -1
  155. mlrun/artifacts/model.py +15 -4
  156. mlrun/artifacts/plots.py +1 -1
  157. mlrun/common/__init__.py +1 -1
  158. mlrun/common/constants.py +15 -0
  159. mlrun/common/model_monitoring.py +209 -0
  160. mlrun/common/schemas/__init__.py +167 -0
  161. mlrun/{api → common}/schemas/artifact.py +13 -14
  162. mlrun/{api → common}/schemas/auth.py +10 -8
  163. mlrun/{api → common}/schemas/background_task.py +3 -3
  164. mlrun/{api → common}/schemas/client_spec.py +1 -1
  165. mlrun/{api → common}/schemas/clusterization_spec.py +3 -3
  166. mlrun/{api → common}/schemas/constants.py +21 -8
  167. mlrun/common/schemas/events.py +36 -0
  168. mlrun/{api → common}/schemas/feature_store.py +2 -1
  169. mlrun/{api → common}/schemas/frontend_spec.py +7 -6
  170. mlrun/{api → common}/schemas/function.py +5 -5
  171. mlrun/{api → common}/schemas/http.py +3 -3
  172. mlrun/common/schemas/hub.py +134 -0
  173. mlrun/{api → common}/schemas/k8s.py +3 -3
  174. mlrun/{api → common}/schemas/memory_reports.py +1 -1
  175. mlrun/common/schemas/model_endpoints.py +342 -0
  176. mlrun/common/schemas/notification.py +57 -0
  177. mlrun/{api → common}/schemas/object.py +6 -6
  178. mlrun/{api → common}/schemas/pipeline.py +3 -3
  179. mlrun/{api → common}/schemas/project.py +6 -5
  180. mlrun/common/schemas/regex.py +24 -0
  181. mlrun/common/schemas/runs.py +30 -0
  182. mlrun/{api → common}/schemas/runtime_resource.py +3 -3
  183. mlrun/{api → common}/schemas/schedule.py +19 -7
  184. mlrun/{api → common}/schemas/secret.py +3 -3
  185. mlrun/{api → common}/schemas/tag.py +2 -2
  186. mlrun/common/types.py +25 -0
  187. mlrun/config.py +152 -20
  188. mlrun/data_types/__init__.py +7 -2
  189. mlrun/data_types/data_types.py +4 -2
  190. mlrun/data_types/infer.py +1 -1
  191. mlrun/data_types/spark.py +10 -3
  192. mlrun/datastore/__init__.py +10 -3
  193. mlrun/datastore/azure_blob.py +1 -1
  194. mlrun/datastore/base.py +185 -53
  195. mlrun/datastore/datastore.py +1 -1
  196. mlrun/datastore/filestore.py +1 -1
  197. mlrun/datastore/google_cloud_storage.py +1 -1
  198. mlrun/datastore/inmem.py +4 -1
  199. mlrun/datastore/redis.py +1 -1
  200. mlrun/datastore/s3.py +1 -1
  201. mlrun/datastore/sources.py +192 -70
  202. mlrun/datastore/spark_udf.py +44 -0
  203. mlrun/datastore/store_resources.py +4 -4
  204. mlrun/datastore/targets.py +115 -45
  205. mlrun/datastore/utils.py +127 -5
  206. mlrun/datastore/v3io.py +1 -1
  207. mlrun/datastore/wasbfs/__init__.py +1 -1
  208. mlrun/datastore/wasbfs/fs.py +1 -1
  209. mlrun/db/__init__.py +7 -5
  210. mlrun/db/base.py +112 -68
  211. mlrun/db/httpdb.py +445 -277
  212. mlrun/db/nopdb.py +491 -0
  213. mlrun/db/sqldb.py +112 -65
  214. mlrun/errors.py +6 -1
  215. mlrun/execution.py +44 -22
  216. mlrun/feature_store/__init__.py +1 -1
  217. mlrun/feature_store/api.py +143 -95
  218. mlrun/feature_store/common.py +16 -20
  219. mlrun/feature_store/feature_set.py +42 -12
  220. mlrun/feature_store/feature_vector.py +32 -21
  221. mlrun/feature_store/ingestion.py +9 -12
  222. mlrun/feature_store/retrieval/__init__.py +3 -2
  223. mlrun/feature_store/retrieval/base.py +388 -66
  224. mlrun/feature_store/retrieval/dask_merger.py +63 -151
  225. mlrun/feature_store/retrieval/job.py +30 -12
  226. mlrun/feature_store/retrieval/local_merger.py +40 -133
  227. mlrun/feature_store/retrieval/spark_merger.py +129 -127
  228. mlrun/feature_store/retrieval/storey_merger.py +173 -0
  229. mlrun/feature_store/steps.py +132 -15
  230. mlrun/features.py +8 -3
  231. mlrun/frameworks/__init__.py +1 -1
  232. mlrun/frameworks/_common/__init__.py +1 -1
  233. mlrun/frameworks/_common/artifacts_library.py +1 -1
  234. mlrun/frameworks/_common/mlrun_interface.py +1 -1
  235. mlrun/frameworks/_common/model_handler.py +1 -1
  236. mlrun/frameworks/_common/plan.py +1 -1
  237. mlrun/frameworks/_common/producer.py +1 -1
  238. mlrun/frameworks/_common/utils.py +1 -1
  239. mlrun/frameworks/_dl_common/__init__.py +1 -1
  240. mlrun/frameworks/_dl_common/loggers/__init__.py +1 -1
  241. mlrun/frameworks/_dl_common/loggers/logger.py +1 -1
  242. mlrun/frameworks/_dl_common/loggers/mlrun_logger.py +1 -1
  243. mlrun/frameworks/_dl_common/loggers/tensorboard_logger.py +1 -1
  244. mlrun/frameworks/_dl_common/model_handler.py +1 -1
  245. mlrun/frameworks/_dl_common/utils.py +1 -1
  246. mlrun/frameworks/_ml_common/__init__.py +1 -1
  247. mlrun/frameworks/_ml_common/artifacts_library.py +1 -1
  248. mlrun/frameworks/_ml_common/loggers/__init__.py +1 -1
  249. mlrun/frameworks/_ml_common/loggers/logger.py +1 -1
  250. mlrun/frameworks/_ml_common/loggers/mlrun_logger.py +1 -1
  251. mlrun/frameworks/_ml_common/model_handler.py +1 -1
  252. mlrun/frameworks/_ml_common/pkl_model_server.py +13 -1
  253. mlrun/frameworks/_ml_common/plan.py +1 -1
  254. mlrun/frameworks/_ml_common/plans/__init__.py +1 -1
  255. mlrun/frameworks/_ml_common/plans/calibration_curve_plan.py +1 -6
  256. mlrun/frameworks/_ml_common/plans/confusion_matrix_plan.py +1 -1
  257. mlrun/frameworks/_ml_common/plans/dataset_plan.py +1 -1
  258. mlrun/frameworks/_ml_common/plans/feature_importance_plan.py +1 -1
  259. mlrun/frameworks/_ml_common/plans/roc_curve_plan.py +1 -1
  260. mlrun/frameworks/_ml_common/producer.py +1 -1
  261. mlrun/frameworks/_ml_common/utils.py +1 -1
  262. mlrun/frameworks/auto_mlrun/__init__.py +1 -1
  263. mlrun/frameworks/auto_mlrun/auto_mlrun.py +1 -1
  264. mlrun/frameworks/huggingface/__init__.py +1 -1
  265. mlrun/frameworks/huggingface/model_server.py +1 -1
  266. mlrun/frameworks/lgbm/__init__.py +1 -1
  267. mlrun/frameworks/lgbm/callbacks/__init__.py +1 -1
  268. mlrun/frameworks/lgbm/callbacks/callback.py +1 -1
  269. mlrun/frameworks/lgbm/callbacks/logging_callback.py +1 -1
  270. mlrun/frameworks/lgbm/callbacks/mlrun_logging_callback.py +1 -1
  271. mlrun/frameworks/lgbm/mlrun_interfaces/__init__.py +1 -1
  272. mlrun/frameworks/lgbm/mlrun_interfaces/booster_mlrun_interface.py +1 -1
  273. mlrun/frameworks/lgbm/mlrun_interfaces/mlrun_interface.py +1 -1
  274. mlrun/frameworks/lgbm/mlrun_interfaces/model_mlrun_interface.py +1 -1
  275. mlrun/frameworks/lgbm/model_handler.py +1 -1
  276. mlrun/frameworks/lgbm/model_server.py +1 -1
  277. mlrun/frameworks/lgbm/utils.py +1 -1
  278. mlrun/frameworks/onnx/__init__.py +1 -1
  279. mlrun/frameworks/onnx/dataset.py +1 -1
  280. mlrun/frameworks/onnx/mlrun_interface.py +1 -1
  281. mlrun/frameworks/onnx/model_handler.py +1 -1
  282. mlrun/frameworks/onnx/model_server.py +1 -1
  283. mlrun/frameworks/parallel_coordinates.py +1 -1
  284. mlrun/frameworks/pytorch/__init__.py +1 -1
  285. mlrun/frameworks/pytorch/callbacks/__init__.py +1 -1
  286. mlrun/frameworks/pytorch/callbacks/callback.py +1 -1
  287. mlrun/frameworks/pytorch/callbacks/logging_callback.py +1 -1
  288. mlrun/frameworks/pytorch/callbacks/mlrun_logging_callback.py +1 -1
  289. mlrun/frameworks/pytorch/callbacks/tensorboard_logging_callback.py +1 -1
  290. mlrun/frameworks/pytorch/callbacks_handler.py +1 -1
  291. mlrun/frameworks/pytorch/mlrun_interface.py +1 -1
  292. mlrun/frameworks/pytorch/model_handler.py +1 -1
  293. mlrun/frameworks/pytorch/model_server.py +1 -1
  294. mlrun/frameworks/pytorch/utils.py +1 -1
  295. mlrun/frameworks/sklearn/__init__.py +1 -1
  296. mlrun/frameworks/sklearn/estimator.py +1 -1
  297. mlrun/frameworks/sklearn/metric.py +1 -1
  298. mlrun/frameworks/sklearn/metrics_library.py +1 -1
  299. mlrun/frameworks/sklearn/mlrun_interface.py +1 -1
  300. mlrun/frameworks/sklearn/model_handler.py +1 -1
  301. mlrun/frameworks/sklearn/utils.py +1 -1
  302. mlrun/frameworks/tf_keras/__init__.py +1 -1
  303. mlrun/frameworks/tf_keras/callbacks/__init__.py +1 -1
  304. mlrun/frameworks/tf_keras/callbacks/logging_callback.py +1 -1
  305. mlrun/frameworks/tf_keras/callbacks/mlrun_logging_callback.py +1 -1
  306. mlrun/frameworks/tf_keras/callbacks/tensorboard_logging_callback.py +1 -1
  307. mlrun/frameworks/tf_keras/mlrun_interface.py +1 -1
  308. mlrun/frameworks/tf_keras/model_handler.py +1 -1
  309. mlrun/frameworks/tf_keras/model_server.py +1 -1
  310. mlrun/frameworks/tf_keras/utils.py +1 -1
  311. mlrun/frameworks/xgboost/__init__.py +1 -1
  312. mlrun/frameworks/xgboost/mlrun_interface.py +1 -1
  313. mlrun/frameworks/xgboost/model_handler.py +1 -1
  314. mlrun/frameworks/xgboost/utils.py +1 -1
  315. mlrun/k8s_utils.py +14 -765
  316. mlrun/kfpops.py +14 -17
  317. mlrun/launcher/__init__.py +13 -0
  318. mlrun/launcher/base.py +406 -0
  319. mlrun/launcher/client.py +159 -0
  320. mlrun/launcher/factory.py +50 -0
  321. mlrun/launcher/local.py +276 -0
  322. mlrun/launcher/remote.py +178 -0
  323. mlrun/lists.py +10 -2
  324. mlrun/mlutils/__init__.py +1 -1
  325. mlrun/mlutils/data.py +1 -1
  326. mlrun/mlutils/models.py +1 -1
  327. mlrun/mlutils/plots.py +1 -1
  328. mlrun/model.py +252 -14
  329. mlrun/model_monitoring/__init__.py +41 -0
  330. mlrun/model_monitoring/features_drift_table.py +1 -1
  331. mlrun/model_monitoring/helpers.py +123 -38
  332. mlrun/model_monitoring/model_endpoint.py +144 -0
  333. mlrun/model_monitoring/model_monitoring_batch.py +310 -259
  334. mlrun/model_monitoring/stores/__init__.py +106 -0
  335. mlrun/model_monitoring/stores/kv_model_endpoint_store.py +448 -0
  336. mlrun/model_monitoring/stores/model_endpoint_store.py +147 -0
  337. mlrun/model_monitoring/stores/models/__init__.py +23 -0
  338. mlrun/model_monitoring/stores/models/base.py +18 -0
  339. mlrun/model_monitoring/stores/models/mysql.py +100 -0
  340. mlrun/model_monitoring/stores/models/sqlite.py +98 -0
  341. mlrun/model_monitoring/stores/sql_model_endpoint_store.py +370 -0
  342. mlrun/model_monitoring/stream_processing_fs.py +239 -271
  343. mlrun/package/__init__.py +163 -0
  344. mlrun/package/context_handler.py +325 -0
  345. mlrun/package/errors.py +47 -0
  346. mlrun/package/packager.py +298 -0
  347. mlrun/{runtimes/package → package/packagers}/__init__.py +3 -1
  348. mlrun/package/packagers/default_packager.py +422 -0
  349. mlrun/package/packagers/numpy_packagers.py +612 -0
  350. mlrun/package/packagers/pandas_packagers.py +968 -0
  351. mlrun/package/packagers/python_standard_library_packagers.py +616 -0
  352. mlrun/package/packagers_manager.py +786 -0
  353. mlrun/package/utils/__init__.py +53 -0
  354. mlrun/package/utils/_archiver.py +226 -0
  355. mlrun/package/utils/_formatter.py +211 -0
  356. mlrun/package/utils/_pickler.py +234 -0
  357. mlrun/package/utils/_supported_format.py +71 -0
  358. mlrun/package/utils/log_hint_utils.py +93 -0
  359. mlrun/package/utils/type_hint_utils.py +298 -0
  360. mlrun/platforms/__init__.py +1 -1
  361. mlrun/platforms/iguazio.py +34 -2
  362. mlrun/platforms/other.py +1 -1
  363. mlrun/projects/__init__.py +1 -1
  364. mlrun/projects/operations.py +14 -9
  365. mlrun/projects/pipelines.py +31 -13
  366. mlrun/projects/project.py +762 -238
  367. mlrun/render.py +49 -19
  368. mlrun/run.py +57 -326
  369. mlrun/runtimes/__init__.py +3 -9
  370. mlrun/runtimes/base.py +247 -784
  371. mlrun/runtimes/constants.py +1 -1
  372. mlrun/runtimes/daskjob.py +45 -41
  373. mlrun/runtimes/funcdoc.py +43 -7
  374. mlrun/runtimes/function.py +66 -656
  375. mlrun/runtimes/function_reference.py +1 -1
  376. mlrun/runtimes/generators.py +1 -1
  377. mlrun/runtimes/kubejob.py +99 -116
  378. mlrun/runtimes/local.py +59 -66
  379. mlrun/runtimes/mpijob/__init__.py +1 -1
  380. mlrun/runtimes/mpijob/abstract.py +13 -15
  381. mlrun/runtimes/mpijob/v1.py +3 -1
  382. mlrun/runtimes/mpijob/v1alpha1.py +1 -1
  383. mlrun/runtimes/nuclio.py +1 -1
  384. mlrun/runtimes/pod.py +51 -26
  385. mlrun/runtimes/remotesparkjob.py +3 -1
  386. mlrun/runtimes/serving.py +12 -4
  387. mlrun/runtimes/sparkjob/__init__.py +1 -2
  388. mlrun/runtimes/sparkjob/abstract.py +44 -31
  389. mlrun/runtimes/sparkjob/spark3job.py +11 -9
  390. mlrun/runtimes/utils.py +61 -42
  391. mlrun/secrets.py +16 -18
  392. mlrun/serving/__init__.py +3 -2
  393. mlrun/serving/merger.py +1 -1
  394. mlrun/serving/remote.py +1 -1
  395. mlrun/serving/routers.py +39 -42
  396. mlrun/serving/server.py +23 -13
  397. mlrun/serving/serving_wrapper.py +1 -1
  398. mlrun/serving/states.py +172 -39
  399. mlrun/serving/utils.py +1 -1
  400. mlrun/serving/v1_serving.py +1 -1
  401. mlrun/serving/v2_serving.py +29 -21
  402. mlrun/utils/__init__.py +1 -2
  403. mlrun/utils/async_http.py +8 -1
  404. mlrun/utils/azure_vault.py +1 -1
  405. mlrun/utils/clones.py +2 -2
  406. mlrun/utils/condition_evaluator.py +65 -0
  407. mlrun/utils/db.py +52 -0
  408. mlrun/utils/helpers.py +188 -13
  409. mlrun/utils/http.py +89 -54
  410. mlrun/utils/logger.py +48 -8
  411. mlrun/utils/model_monitoring.py +132 -100
  412. mlrun/utils/notifications/__init__.py +1 -1
  413. mlrun/utils/notifications/notification/__init__.py +8 -6
  414. mlrun/utils/notifications/notification/base.py +20 -14
  415. mlrun/utils/notifications/notification/console.py +7 -4
  416. mlrun/utils/notifications/notification/git.py +36 -19
  417. mlrun/utils/notifications/notification/ipython.py +10 -8
  418. mlrun/utils/notifications/notification/slack.py +18 -13
  419. mlrun/utils/notifications/notification_pusher.py +377 -56
  420. mlrun/utils/regex.py +6 -1
  421. mlrun/utils/singleton.py +1 -1
  422. mlrun/utils/v3io_clients.py +1 -1
  423. mlrun/utils/vault.py +270 -269
  424. mlrun/utils/version/__init__.py +1 -1
  425. mlrun/utils/version/version.json +2 -2
  426. mlrun/utils/version/version.py +1 -1
  427. {mlrun-1.3.3rc1.dist-info → mlrun-1.4.0.dist-info}/METADATA +16 -10
  428. mlrun-1.4.0.dist-info/RECORD +434 -0
  429. mlrun/api/api/endpoints/marketplace.py +0 -257
  430. mlrun/api/crud/marketplace.py +0 -221
  431. mlrun/api/crud/model_monitoring/model_endpoint_store.py +0 -847
  432. mlrun/api/db/filedb/db.py +0 -518
  433. mlrun/api/schemas/marketplace.py +0 -128
  434. mlrun/api/schemas/model_endpoints.py +0 -185
  435. mlrun/db/filedb.py +0 -891
  436. mlrun/feature_store/retrieval/online.py +0 -92
  437. mlrun/model_monitoring/constants.py +0 -67
  438. mlrun/runtimes/package/context_handler.py +0 -711
  439. mlrun/runtimes/sparkjob/spark2job.py +0 -59
  440. mlrun-1.3.3rc1.dist-info/RECORD +0 -381
  441. {mlrun-1.3.3rc1.dist-info → mlrun-1.4.0.dist-info}/LICENSE +0 -0
  442. {mlrun-1.3.3rc1.dist-info → mlrun-1.4.0.dist-info}/WHEEL +0 -0
  443. {mlrun-1.3.3rc1.dist-info → mlrun-1.4.0.dist-info}/entry_points.txt +0 -0
  444. {mlrun-1.3.3rc1.dist-info → mlrun-1.4.0.dist-info}/top_level.txt +0 -0
@@ -1,4 +1,4 @@
1
- # Copyright 2018 Iguazio
1
+ # Copyright 2023 Iguazio
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -13,83 +13,54 @@
13
13
  # limitations under the License.
14
14
  #
15
15
  import asyncio
16
- import json
16
+ import warnings
17
17
  from http import HTTPStatus
18
- from typing import Any, Dict, List, Optional, Set, Union
18
+ from typing import List, Union
19
19
 
20
- import numpy as np
21
- import pandas as pd
22
20
  from fastapi import APIRouter, Depends, Request, Response
23
21
  from fastapi.concurrency import run_in_threadpool
24
22
  from sqlalchemy.orm import Session
25
23
 
26
24
  import mlrun.api.crud
27
- import mlrun.api.schemas
25
+ import mlrun.api.crud.model_monitoring.grafana
28
26
  import mlrun.api.utils.auth.verifier
27
+ import mlrun.common.model_monitoring
28
+ import mlrun.common.schemas
29
29
  from mlrun.api.api import deps
30
- from mlrun.api.schemas import (
31
- GrafanaColumn,
32
- GrafanaDataPoint,
33
- GrafanaNumberColumn,
34
- GrafanaTable,
35
- GrafanaTimeSeriesTarget,
36
- ProjectsFormat,
37
- )
38
- from mlrun.api.utils.singletons.project_member import get_project_member
39
- from mlrun.errors import MLRunBadRequestError
40
- from mlrun.utils import config, logger
41
- from mlrun.utils.model_monitoring import parse_model_endpoint_store_prefix
42
- from mlrun.utils.v3io_clients import get_frames_client
43
30
 
44
- router = APIRouter()
31
+ router = APIRouter(prefix="/grafana-proxy/model-endpoints")
32
+
33
+ NAME_TO_SEARCH_FUNCTION_DICTIONARY = {
34
+ "list_projects": mlrun.api.crud.model_monitoring.grafana.grafana_list_projects,
35
+ }
36
+ NAME_TO_QUERY_FUNCTION_DICTIONARY = {
37
+ "list_endpoints": mlrun.api.crud.model_monitoring.grafana.grafana_list_endpoints,
38
+ "individual_feature_analysis": mlrun.api.crud.model_monitoring.grafana.grafana_individual_feature_analysis,
39
+ "overall_feature_analysis": mlrun.api.crud.model_monitoring.grafana.grafana_overall_feature_analysis,
40
+ "incoming_features": mlrun.api.crud.model_monitoring.grafana.grafana_incoming_features,
41
+ }
42
+
43
+ SUPPORTED_QUERY_FUNCTIONS = set(NAME_TO_QUERY_FUNCTION_DICTIONARY.keys())
44
+ SUPPORTED_SEARCH_FUNCTIONS = set(NAME_TO_SEARCH_FUNCTION_DICTIONARY)
45
45
 
46
46
 
47
- @router.get("/grafana-proxy/model-endpoints", status_code=HTTPStatus.OK.value)
47
+ @router.get("", status_code=HTTPStatus.OK.value)
48
48
  def grafana_proxy_model_endpoints_check_connection(
49
- auth_info: mlrun.api.schemas.AuthInfo = Depends(deps.authenticate_request),
49
+ auth_info: mlrun.common.schemas.AuthInfo = Depends(deps.authenticate_request),
50
50
  ):
51
51
  """
52
52
  Root of grafana proxy for the model-endpoints API, used for validating the model-endpoints data source
53
53
  connectivity.
54
54
  """
55
- mlrun.api.crud.ModelEndpoints().get_access_key(auth_info)
55
+ if not mlrun.mlconf.is_ce_mode():
56
+ mlrun.api.crud.ModelEndpoints().get_access_key(auth_info)
56
57
  return Response(status_code=HTTPStatus.OK.value)
57
58
 
58
59
 
59
- @router.post(
60
- "/grafana-proxy/model-endpoints/query",
61
- response_model=List[Union[GrafanaTable, GrafanaTimeSeriesTarget]],
62
- )
63
- async def grafana_proxy_model_endpoints_query(
64
- request: Request,
65
- auth_info: mlrun.api.schemas.AuthInfo = Depends(deps.authenticate_request),
66
- ) -> List[Union[GrafanaTable, GrafanaTimeSeriesTarget]]:
67
- """
68
- Query route for model-endpoints grafana proxy API, used for creating an interface between grafana queries and
69
- model-endpoints logic.
70
-
71
- This implementation requires passing target_endpoint query parameter in order to dispatch different
72
- model-endpoint monitoring functions.
73
- """
74
- body = await request.json()
75
- query_parameters = _parse_query_parameters(body)
76
- _validate_query_parameters(query_parameters, SUPPORTED_QUERY_FUNCTIONS)
77
- query_parameters = _drop_grafana_escape_chars(query_parameters)
78
-
79
- # At this point everything is validated and we can access everything that is needed without performing all previous
80
- # checks again.
81
- target_endpoint = query_parameters["target_endpoint"]
82
- function = NAME_TO_QUERY_FUNCTION_DICTIONARY[target_endpoint]
83
- if asyncio.iscoroutinefunction(function):
84
- return await function(body, query_parameters, auth_info)
85
- result = await run_in_threadpool(function, body, query_parameters, auth_info)
86
- return result
87
-
88
-
89
- @router.post("/grafana-proxy/model-endpoints/search", response_model=List[str])
60
+ @router.post("/search", response_model=List[str])
90
61
  async def grafana_proxy_model_endpoints_search(
91
62
  request: Request,
92
- auth_info: mlrun.api.schemas.AuthInfo = Depends(deps.authenticate_request),
63
+ auth_info: mlrun.common.schemas.AuthInfo = Depends(deps.authenticate_request),
93
64
  db_session: Session = Depends(deps.get_db_session),
94
65
  ) -> List[str]:
95
66
  """
@@ -98,411 +69,87 @@ async def grafana_proxy_model_endpoints_search(
98
69
 
99
70
  This implementation requires passing target_endpoint query parameter in order to dispatch different
100
71
  model-endpoint monitoring functions.
72
+
73
+ :param request: An api request with the required target and parameters.
74
+ :param auth_info: The auth info of the request.
75
+ :param db_session: A session that manages the current dialog with the database.
76
+
77
+ :return: List of results. e.g. list of available project names.
101
78
  """
102
- mlrun.api.crud.ModelEndpoints().get_access_key(auth_info)
79
+ if not mlrun.mlconf.is_ce_mode():
80
+ mlrun.api.crud.ModelEndpoints().get_access_key(auth_info)
103
81
  body = await request.json()
104
- query_parameters = _parse_search_parameters(body)
105
-
106
- _validate_query_parameters(query_parameters, SUPPORTED_SEARCH_FUNCTIONS)
82
+ query_parameters = mlrun.api.crud.model_monitoring.grafana.parse_search_parameters(
83
+ body
84
+ )
85
+ mlrun.api.crud.model_monitoring.grafana.validate_query_parameters(
86
+ query_parameters, SUPPORTED_SEARCH_FUNCTIONS
87
+ )
107
88
 
108
89
  # At this point everything is validated and we can access everything that is needed without performing all previous
109
90
  # checks again.
110
91
  target_endpoint = query_parameters["target_endpoint"]
111
92
  function = NAME_TO_SEARCH_FUNCTION_DICTIONARY[target_endpoint]
112
- if asyncio.iscoroutinefunction(function):
113
- return await function(db_session, auth_info)
114
- result = await run_in_threadpool(function, db_session, auth_info)
115
- return result
116
93
 
117
-
118
- def grafana_list_projects(
119
- db_session: Session, auth_info: mlrun.api.schemas.AuthInfo
120
- ) -> List[str]:
121
- projects_output = get_project_member().list_projects(
122
- db_session, format_=ProjectsFormat.name_only, leader_session=auth_info.session
123
- )
124
- return projects_output.projects
125
-
126
-
127
- async def grafana_list_endpoints(
128
- body: Dict[str, Any],
129
- query_parameters: Dict[str, str],
130
- auth_info: mlrun.api.schemas.AuthInfo,
131
- ) -> List[GrafanaTable]:
132
- project = query_parameters.get("project")
133
-
134
- # Filters
135
- model = query_parameters.get("model", None)
136
- function = query_parameters.get("function", None)
137
- labels = query_parameters.get("labels", "")
138
- labels = labels.split(",") if labels else []
139
-
140
- # Metrics to include
141
- metrics = query_parameters.get("metrics", "")
142
- metrics = metrics.split(",") if metrics else []
143
-
144
- # Time range for metrics
145
- start = body.get("rangeRaw", {}).get("start", "now-1h")
146
- end = body.get("rangeRaw", {}).get("end", "now")
147
-
148
- if project:
149
- await mlrun.api.utils.auth.verifier.AuthVerifier().query_project_permissions(
150
- project,
151
- mlrun.api.schemas.AuthorizationAction.read,
152
- auth_info,
94
+ if asyncio.iscoroutinefunction(function):
95
+ result = await function(db_session, auth_info, query_parameters)
96
+ else:
97
+ result = await run_in_threadpool(
98
+ function, db_session, auth_info, query_parameters
153
99
  )
154
- endpoint_list = await run_in_threadpool(
155
- mlrun.api.crud.ModelEndpoints().list_model_endpoints,
156
- auth_info=auth_info,
157
- project=project,
158
- model=model,
159
- function=function,
160
- labels=labels,
161
- metrics=metrics,
162
- start=start,
163
- end=end,
164
- )
165
- allowed_endpoints = await mlrun.api.utils.auth.verifier.AuthVerifier().filter_project_resources_by_permissions(
166
- mlrun.api.schemas.AuthorizationResourceTypes.model_endpoint,
167
- endpoint_list.endpoints,
168
- lambda _endpoint: (
169
- _endpoint.metadata.project,
170
- _endpoint.metadata.uid,
171
- ),
172
- auth_info,
173
- )
174
- endpoint_list.endpoints = allowed_endpoints
175
-
176
- columns = [
177
- GrafanaColumn(text="endpoint_id", type="string"),
178
- GrafanaColumn(text="endpoint_function", type="string"),
179
- GrafanaColumn(text="endpoint_model", type="string"),
180
- GrafanaColumn(text="endpoint_model_class", type="string"),
181
- GrafanaColumn(text="first_request", type="time"),
182
- GrafanaColumn(text="last_request", type="time"),
183
- GrafanaColumn(text="accuracy", type="number"),
184
- GrafanaColumn(text="error_count", type="number"),
185
- GrafanaColumn(text="drift_status", type="number"),
186
- ]
187
-
188
- metric_columns = []
189
-
190
- found_metrics = set()
191
- for endpoint in endpoint_list.endpoints:
192
- if endpoint.status.metrics is not None:
193
- for key in endpoint.status.metrics.keys():
194
- if key not in found_metrics:
195
- found_metrics.add(key)
196
- metric_columns.append(GrafanaColumn(text=key, type="number"))
197
-
198
- columns = columns + metric_columns
199
- table = GrafanaTable(columns=columns)
200
-
201
- for endpoint in endpoint_list.endpoints:
202
- row = [
203
- endpoint.metadata.uid,
204
- endpoint.spec.function_uri,
205
- endpoint.spec.model,
206
- endpoint.spec.model_class,
207
- endpoint.status.first_request,
208
- endpoint.status.last_request,
209
- endpoint.status.accuracy,
210
- endpoint.status.error_count,
211
- endpoint.status.drift_status,
212
- ]
213
-
214
- if endpoint.status.metrics is not None and metric_columns:
215
- for metric_column in metric_columns:
216
- row.append(endpoint.status.metrics[metric_column.text])
217
-
218
- table.add_row(*row)
219
-
220
- return [table]
221
-
222
-
223
- async def grafana_individual_feature_analysis(
224
- body: Dict[str, Any],
225
- query_parameters: Dict[str, str],
226
- auth_info: mlrun.api.schemas.AuthInfo,
227
- ):
228
- endpoint_id = query_parameters.get("endpoint_id")
229
- project = query_parameters.get("project")
230
- await mlrun.api.utils.auth.verifier.AuthVerifier().query_project_resource_permissions(
231
- mlrun.api.schemas.AuthorizationResourceTypes.model_endpoint,
232
- project,
233
- endpoint_id,
234
- mlrun.api.schemas.AuthorizationAction.read,
235
- auth_info,
236
- )
237
-
238
- endpoint = await run_in_threadpool(
239
- mlrun.api.crud.ModelEndpoints().get_model_endpoint,
240
- auth_info=auth_info,
241
- project=project,
242
- endpoint_id=endpoint_id,
243
- feature_analysis=True,
244
- )
100
+ return result
245
101
 
246
- # Load JSON data from KV, make sure not to fail if a field is missing
247
- feature_stats = endpoint.status.feature_stats or {}
248
- current_stats = endpoint.status.current_stats or {}
249
- drift_measures = endpoint.status.drift_measures or {}
250
102
 
251
- table = GrafanaTable(
252
- columns=[
253
- GrafanaColumn(text="feature_name", type="string"),
254
- GrafanaColumn(text="actual_min", type="number"),
255
- GrafanaColumn(text="actual_mean", type="number"),
256
- GrafanaColumn(text="actual_max", type="number"),
257
- GrafanaColumn(text="expected_min", type="number"),
258
- GrafanaColumn(text="expected_mean", type="number"),
259
- GrafanaColumn(text="expected_max", type="number"),
260
- GrafanaColumn(text="tvd", type="number"),
261
- GrafanaColumn(text="hellinger", type="number"),
262
- GrafanaColumn(text="kld", type="number"),
103
+ @router.post(
104
+ "/query",
105
+ response_model=List[
106
+ Union[
107
+ mlrun.common.schemas.GrafanaTable,
108
+ mlrun.common.schemas.GrafanaTimeSeriesTarget,
263
109
  ]
264
- )
265
-
266
- for feature, base_stat in feature_stats.items():
267
- current_stat = current_stats.get(feature, {})
268
- drift_measure = drift_measures.get(feature, {})
269
-
270
- table.add_row(
271
- feature,
272
- current_stat.get("min"),
273
- current_stat.get("mean"),
274
- current_stat.get("max"),
275
- base_stat.get("min"),
276
- base_stat.get("mean"),
277
- base_stat.get("max"),
278
- drift_measure.get("tvd"),
279
- drift_measure.get("hellinger"),
280
- drift_measure.get("kld"),
281
- )
282
-
283
- return [table]
284
-
110
+ ],
111
+ )
112
+ async def grafana_proxy_model_endpoints_query(
113
+ request: Request,
114
+ auth_info: mlrun.common.schemas.AuthInfo = Depends(deps.authenticate_request),
115
+ ) -> List[
116
+ Union[
117
+ mlrun.common.schemas.GrafanaTable, mlrun.common.schemas.GrafanaTimeSeriesTarget
118
+ ]
119
+ ]:
120
+ """
121
+ Query route for model-endpoints grafana proxy API, used for creating an interface between grafana queries and
122
+ model-endpoints logic.
285
123
 
286
- async def grafana_overall_feature_analysis(
287
- body: Dict[str, Any],
288
- query_parameters: Dict[str, str],
289
- auth_info: mlrun.api.schemas.AuthInfo,
290
- ):
291
- endpoint_id = query_parameters.get("endpoint_id")
292
- project = query_parameters.get("project")
293
- await mlrun.api.utils.auth.verifier.AuthVerifier().query_project_resource_permissions(
294
- mlrun.api.schemas.AuthorizationResourceTypes.model_endpoint,
295
- project,
296
- endpoint_id,
297
- mlrun.api.schemas.AuthorizationAction.read,
298
- auth_info,
299
- )
300
- endpoint = await run_in_threadpool(
301
- mlrun.api.crud.ModelEndpoints().get_model_endpoint,
302
- auth_info=auth_info,
303
- project=project,
304
- endpoint_id=endpoint_id,
305
- feature_analysis=True,
306
- )
124
+ This implementation requires passing target_endpoint query parameter in order to dispatch different
125
+ model-endpoint monitoring functions.
126
+ """
307
127
 
308
- table = GrafanaTable(
309
- columns=[
310
- GrafanaNumberColumn(text="tvd_sum"),
311
- GrafanaNumberColumn(text="tvd_mean"),
312
- GrafanaNumberColumn(text="hellinger_sum"),
313
- GrafanaNumberColumn(text="hellinger_mean"),
314
- GrafanaNumberColumn(text="kld_sum"),
315
- GrafanaNumberColumn(text="kld_mean"),
316
- ]
128
+ warnings.warn(
129
+ "This api is deprecated in 1.3.1 and will be removed in 1.5.0. "
130
+ "Please update grafana model monitoring dashboards that use a different data source",
131
+ # TODO: remove in 1.5.0
132
+ FutureWarning,
317
133
  )
318
134
 
319
- if endpoint.status.drift_measures:
320
- table.add_row(
321
- endpoint.status.drift_measures.get("tvd_sum"),
322
- endpoint.status.drift_measures.get("tvd_mean"),
323
- endpoint.status.drift_measures.get("hellinger_sum"),
324
- endpoint.status.drift_measures.get("hellinger_mean"),
325
- endpoint.status.drift_measures.get("kld_sum"),
326
- endpoint.status.drift_measures.get("kld_mean"),
327
- )
328
-
329
- return [table]
330
-
331
-
332
- async def grafana_incoming_features(
333
- body: Dict[str, Any],
334
- query_parameters: Dict[str, str],
335
- auth_info: mlrun.api.schemas.AuthInfo,
336
- ):
337
- endpoint_id = query_parameters.get("endpoint_id")
338
- project = query_parameters.get("project")
339
- start = body.get("rangeRaw", {}).get("from", "now-1h")
340
- end = body.get("rangeRaw", {}).get("to", "now")
341
-
342
- await mlrun.api.utils.auth.verifier.AuthVerifier().query_project_resource_permissions(
343
- mlrun.api.schemas.AuthorizationResourceTypes.model_endpoint,
344
- project,
345
- endpoint_id,
346
- mlrun.api.schemas.AuthorizationAction.read,
347
- auth_info,
135
+ body = await request.json()
136
+ query_parameters = mlrun.api.crud.model_monitoring.grafana.parse_query_parameters(
137
+ body
348
138
  )
349
-
350
- endpoint = await run_in_threadpool(
351
- mlrun.api.crud.ModelEndpoints().get_model_endpoint,
352
- auth_info=auth_info,
353
- project=project,
354
- endpoint_id=endpoint_id,
139
+ mlrun.api.crud.model_monitoring.grafana.validate_query_parameters(
140
+ query_parameters, SUPPORTED_QUERY_FUNCTIONS
355
141
  )
356
-
357
- time_series = []
358
-
359
- feature_names = endpoint.spec.feature_names
360
-
361
- if not feature_names:
362
- logger.warn(
363
- "'feature_names' is either missing or not initialized in endpoint record",
364
- endpoint_id=endpoint.metadata.uid,
142
+ query_parameters = (
143
+ mlrun.api.crud.model_monitoring.grafana.drop_grafana_escape_chars(
144
+ query_parameters
365
145
  )
366
- return time_series
367
-
368
- path = config.model_endpoint_monitoring.store_prefixes.default.format(
369
- project=project, kind=mlrun.api.schemas.ModelMonitoringStoreKinds.EVENTS
370
- )
371
- _, container, path = parse_model_endpoint_store_prefix(path)
372
-
373
- client = get_frames_client(
374
- token=auth_info.data_session,
375
- address=config.v3io_framesd,
376
- container=container,
377
146
  )
378
147
 
379
- data: pd.DataFrame = await run_in_threadpool(
380
- client.read,
381
- backend="tsdb",
382
- table=path,
383
- columns=feature_names,
384
- filter=f"endpoint_id=='{endpoint_id}'",
385
- start=start,
386
- end=end,
387
- )
388
-
389
- data.drop(["endpoint_id"], axis=1, inplace=True, errors="ignore")
390
- data.index = data.index.astype(np.int64) // 10**6
391
-
392
- for feature, indexed_values in data.to_dict().items():
393
- target = GrafanaTimeSeriesTarget(target=feature)
394
- for index, value in indexed_values.items():
395
- data_point = GrafanaDataPoint(value=float(value), timestamp=index)
396
- target.add_data_point(data_point)
397
- time_series.append(target)
398
-
399
- return time_series
400
-
401
-
402
- def _parse_query_parameters(request_body: Dict[str, Any]) -> Dict[str, str]:
403
- """
404
- This function searches for the target field in Grafana's SimpleJson json. Once located, the target string is
405
- parsed by splitting on semi-colons (;). Each part in the resulting list is then split by an equal sign (=) to be
406
- read as key-value pairs.
407
- """
408
-
409
- # Try to get the target
410
- targets = request_body.get("targets", [])
411
-
412
- if len(targets) > 1:
413
- logger.warn(
414
- f"The 'targets' list contains more then one element ({len(targets)}), all targets except the first one are "
415
- f"ignored."
416
- )
417
-
418
- target_obj = targets[0] if targets else {}
419
- target_query = target_obj.get("target") if target_obj else ""
420
-
421
- if not target_query:
422
- raise MLRunBadRequestError(f"Target missing in request body:\n {request_body}")
423
-
424
- parameters = _parse_parameters(target_query)
425
-
426
- return parameters
427
-
428
-
429
- def _parse_search_parameters(request_body: Dict[str, Any]) -> Dict[str, str]:
430
- """
431
- This function searches for the target field in Grafana's SimpleJson json. Once located, the target string is
432
- parsed by splitting on semi-colons (;). Each part in the resulting list is then split by an equal sign (=) to be
433
- read as key-value pairs.
434
- """
435
-
436
- # Try to get the target
437
- target = request_body.get("target")
438
-
439
- if not target:
440
- raise MLRunBadRequestError(f"Target missing in request body:\n {request_body}")
441
-
442
- parameters = _parse_parameters(target)
443
-
444
- return parameters
445
-
446
-
447
- def _parse_parameters(target_query):
448
- parameters = {}
449
- for query in filter(lambda q: q, target_query.split(";")):
450
- query_parts = query.split("=")
451
- if len(query_parts) < 2:
452
- raise MLRunBadRequestError(
453
- f"Query must contain both query key and query value. Expected query_key=query_value, found {query} "
454
- f"instead."
455
- )
456
- parameters[query_parts[0]] = query_parts[1]
457
- return parameters
458
-
459
-
460
- def _drop_grafana_escape_chars(query_parameters: Dict[str, str]):
461
- query_parameters = dict(query_parameters)
462
- endpoint_id = query_parameters.get("endpoint_id")
463
- if endpoint_id is not None:
464
- query_parameters["endpoint_id"] = endpoint_id.replace("\\", "")
465
- return query_parameters
466
-
467
-
468
- def _validate_query_parameters(
469
- query_parameters: Dict[str, str], supported_endpoints: Optional[Set[str]] = None
470
- ):
471
- """Validates the parameters sent via Grafana's SimpleJson query"""
472
- if "target_endpoint" not in query_parameters:
473
- raise MLRunBadRequestError(
474
- f"Expected 'target_endpoint' field in query, found {query_parameters} instead"
475
- )
476
-
477
- if (
478
- supported_endpoints is not None
479
- and query_parameters["target_endpoint"] not in supported_endpoints
480
- ):
481
- raise MLRunBadRequestError(
482
- f"{query_parameters['target_endpoint']} unsupported in query parameters: {query_parameters}. "
483
- f"Currently supports: {','.join(supported_endpoints)}"
484
- )
485
-
486
-
487
- def _json_loads_or_default(string: Optional[str], default: Any):
488
- if string is None:
489
- return default
490
- obj = json.loads(string)
491
- if not obj:
492
- return default
493
- return obj
494
-
495
-
496
- NAME_TO_QUERY_FUNCTION_DICTIONARY = {
497
- "list_endpoints": grafana_list_endpoints,
498
- "individual_feature_analysis": grafana_individual_feature_analysis,
499
- "overall_feature_analysis": grafana_overall_feature_analysis,
500
- "incoming_features": grafana_incoming_features,
501
- }
502
-
503
- NAME_TO_SEARCH_FUNCTION_DICTIONARY = {
504
- "list_projects": grafana_list_projects,
505
- }
506
-
507
- SUPPORTED_QUERY_FUNCTIONS = set(NAME_TO_QUERY_FUNCTION_DICTIONARY.keys())
508
- SUPPORTED_SEARCH_FUNCTIONS = set(NAME_TO_SEARCH_FUNCTION_DICTIONARY)
148
+ # At this point everything is validated and we can access everything that is needed without performing all previous
149
+ # checks again.
150
+ target_endpoint = query_parameters["target_endpoint"]
151
+ function = NAME_TO_QUERY_FUNCTION_DICTIONARY[target_endpoint]
152
+ if asyncio.iscoroutinefunction(function):
153
+ return await function(body, query_parameters, auth_info)
154
+ result = await run_in_threadpool(function, body, query_parameters, auth_info)
155
+ return result
@@ -1,4 +1,4 @@
1
- # Copyright 2018 Iguazio
1
+ # Copyright 2023 Iguazio
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -12,20 +12,33 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
  #
15
+ import http
16
+
15
17
  from fastapi import APIRouter
16
18
 
17
- import mlrun.api.crud
18
- import mlrun.api.schemas
19
+ import mlrun.common.schemas
20
+ from mlrun.config import config as mlconfig
19
21
 
20
22
  router = APIRouter()
21
23
 
22
24
 
23
25
  @router.get(
24
26
  "/healthz",
25
- response_model=mlrun.api.schemas.ClientSpec,
27
+ status_code=http.HTTPStatus.OK.value,
26
28
  )
27
29
  def health():
28
30
 
29
- # TODO: From 0.7.0 client uses the /client-spec endpoint,
30
- # when this is the oldest relevant client, remove this logic from the healthz endpoint
31
- return mlrun.api.crud.ClientSpec().get_client_spec()
31
+ # offline is the initial state
32
+ # waiting for chief is set for workers waiting for chief to be ready and then clusterize against it
33
+ if mlconfig.httpdb.state in [
34
+ mlrun.common.schemas.APIStates.offline,
35
+ mlrun.common.schemas.APIStates.waiting_for_chief,
36
+ ]:
37
+ raise mlrun.errors.MLRunServiceUnavailableError()
38
+
39
+ return {
40
+ # for old `align_mlrun.sh` scripts expecting `version` in the response
41
+ # TODO: remove on mlrun >= 1.6.0
42
+ "version": mlconfig.version,
43
+ "status": "ok",
44
+ }