mlrun 1.7.0rc5__py3-none-any.whl → 1.7.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of mlrun might be problematic. Click here for more details.

Files changed (234) hide show
  1. mlrun/__init__.py +11 -1
  2. mlrun/__main__.py +39 -121
  3. mlrun/{datastore/helpers.py → alerts/__init__.py} +2 -5
  4. mlrun/alerts/alert.py +248 -0
  5. mlrun/api/schemas/__init__.py +4 -3
  6. mlrun/artifacts/__init__.py +8 -3
  7. mlrun/artifacts/base.py +39 -254
  8. mlrun/artifacts/dataset.py +9 -190
  9. mlrun/artifacts/manager.py +73 -46
  10. mlrun/artifacts/model.py +30 -158
  11. mlrun/artifacts/plots.py +23 -380
  12. mlrun/common/constants.py +73 -2
  13. mlrun/common/db/sql_session.py +3 -2
  14. mlrun/common/formatters/__init__.py +21 -0
  15. mlrun/common/formatters/artifact.py +46 -0
  16. mlrun/common/formatters/base.py +113 -0
  17. mlrun/common/formatters/feature_set.py +44 -0
  18. mlrun/common/formatters/function.py +46 -0
  19. mlrun/common/formatters/pipeline.py +53 -0
  20. mlrun/common/formatters/project.py +51 -0
  21. mlrun/common/formatters/run.py +29 -0
  22. mlrun/common/helpers.py +11 -1
  23. mlrun/{runtimes → common/runtimes}/constants.py +32 -4
  24. mlrun/common/schemas/__init__.py +21 -4
  25. mlrun/common/schemas/alert.py +202 -0
  26. mlrun/common/schemas/api_gateway.py +113 -2
  27. mlrun/common/schemas/artifact.py +28 -1
  28. mlrun/common/schemas/auth.py +11 -0
  29. mlrun/common/schemas/client_spec.py +2 -1
  30. mlrun/common/schemas/common.py +7 -4
  31. mlrun/common/schemas/constants.py +3 -0
  32. mlrun/common/schemas/feature_store.py +58 -28
  33. mlrun/common/schemas/frontend_spec.py +8 -0
  34. mlrun/common/schemas/function.py +11 -0
  35. mlrun/common/schemas/hub.py +7 -9
  36. mlrun/common/schemas/model_monitoring/__init__.py +21 -4
  37. mlrun/common/schemas/model_monitoring/constants.py +136 -42
  38. mlrun/common/schemas/model_monitoring/grafana.py +9 -5
  39. mlrun/common/schemas/model_monitoring/model_endpoints.py +89 -41
  40. mlrun/common/schemas/notification.py +69 -12
  41. mlrun/{runtimes/mpijob/v1alpha1.py → common/schemas/pagination.py} +10 -13
  42. mlrun/common/schemas/pipeline.py +7 -0
  43. mlrun/common/schemas/project.py +67 -16
  44. mlrun/common/schemas/runs.py +17 -0
  45. mlrun/common/schemas/schedule.py +1 -1
  46. mlrun/common/schemas/workflow.py +10 -2
  47. mlrun/common/types.py +14 -1
  48. mlrun/config.py +224 -58
  49. mlrun/data_types/data_types.py +11 -1
  50. mlrun/data_types/spark.py +5 -4
  51. mlrun/data_types/to_pandas.py +75 -34
  52. mlrun/datastore/__init__.py +8 -10
  53. mlrun/datastore/alibaba_oss.py +131 -0
  54. mlrun/datastore/azure_blob.py +131 -43
  55. mlrun/datastore/base.py +107 -47
  56. mlrun/datastore/datastore.py +17 -7
  57. mlrun/datastore/datastore_profile.py +91 -7
  58. mlrun/datastore/dbfs_store.py +3 -7
  59. mlrun/datastore/filestore.py +1 -3
  60. mlrun/datastore/google_cloud_storage.py +92 -32
  61. mlrun/datastore/hdfs.py +5 -0
  62. mlrun/datastore/inmem.py +6 -3
  63. mlrun/datastore/redis.py +3 -2
  64. mlrun/datastore/s3.py +30 -12
  65. mlrun/datastore/snowflake_utils.py +45 -0
  66. mlrun/datastore/sources.py +274 -59
  67. mlrun/datastore/spark_utils.py +30 -0
  68. mlrun/datastore/store_resources.py +9 -7
  69. mlrun/datastore/storeytargets.py +151 -0
  70. mlrun/datastore/targets.py +374 -102
  71. mlrun/datastore/utils.py +68 -5
  72. mlrun/datastore/v3io.py +28 -50
  73. mlrun/db/auth_utils.py +152 -0
  74. mlrun/db/base.py +231 -22
  75. mlrun/db/factory.py +1 -4
  76. mlrun/db/httpdb.py +864 -228
  77. mlrun/db/nopdb.py +268 -16
  78. mlrun/errors.py +35 -5
  79. mlrun/execution.py +111 -38
  80. mlrun/feature_store/__init__.py +0 -2
  81. mlrun/feature_store/api.py +46 -53
  82. mlrun/feature_store/common.py +6 -11
  83. mlrun/feature_store/feature_set.py +48 -23
  84. mlrun/feature_store/feature_vector.py +13 -2
  85. mlrun/feature_store/ingestion.py +7 -6
  86. mlrun/feature_store/retrieval/base.py +9 -4
  87. mlrun/feature_store/retrieval/dask_merger.py +2 -0
  88. mlrun/feature_store/retrieval/job.py +13 -4
  89. mlrun/feature_store/retrieval/local_merger.py +2 -0
  90. mlrun/feature_store/retrieval/spark_merger.py +24 -32
  91. mlrun/feature_store/steps.py +38 -19
  92. mlrun/features.py +6 -14
  93. mlrun/frameworks/_common/plan.py +3 -3
  94. mlrun/frameworks/_dl_common/loggers/tensorboard_logger.py +7 -12
  95. mlrun/frameworks/_ml_common/plan.py +1 -1
  96. mlrun/frameworks/auto_mlrun/auto_mlrun.py +2 -2
  97. mlrun/frameworks/lgbm/__init__.py +1 -1
  98. mlrun/frameworks/lgbm/callbacks/callback.py +2 -4
  99. mlrun/frameworks/lgbm/model_handler.py +1 -1
  100. mlrun/frameworks/parallel_coordinates.py +4 -4
  101. mlrun/frameworks/pytorch/__init__.py +2 -2
  102. mlrun/frameworks/sklearn/__init__.py +1 -1
  103. mlrun/frameworks/sklearn/mlrun_interface.py +13 -3
  104. mlrun/frameworks/tf_keras/__init__.py +5 -2
  105. mlrun/frameworks/tf_keras/callbacks/logging_callback.py +1 -1
  106. mlrun/frameworks/tf_keras/mlrun_interface.py +2 -2
  107. mlrun/frameworks/xgboost/__init__.py +1 -1
  108. mlrun/k8s_utils.py +57 -12
  109. mlrun/launcher/__init__.py +1 -1
  110. mlrun/launcher/base.py +6 -5
  111. mlrun/launcher/client.py +13 -11
  112. mlrun/launcher/factory.py +1 -1
  113. mlrun/launcher/local.py +15 -5
  114. mlrun/launcher/remote.py +10 -3
  115. mlrun/lists.py +6 -2
  116. mlrun/model.py +297 -48
  117. mlrun/model_monitoring/__init__.py +1 -1
  118. mlrun/model_monitoring/api.py +152 -357
  119. mlrun/model_monitoring/applications/__init__.py +10 -0
  120. mlrun/model_monitoring/applications/_application_steps.py +190 -0
  121. mlrun/model_monitoring/applications/base.py +108 -0
  122. mlrun/model_monitoring/applications/context.py +341 -0
  123. mlrun/model_monitoring/{evidently_application.py → applications/evidently_base.py} +27 -22
  124. mlrun/model_monitoring/applications/histogram_data_drift.py +227 -91
  125. mlrun/model_monitoring/applications/results.py +99 -0
  126. mlrun/model_monitoring/controller.py +130 -303
  127. mlrun/model_monitoring/{stores/models/sqlite.py → db/__init__.py} +5 -10
  128. mlrun/model_monitoring/db/stores/__init__.py +136 -0
  129. mlrun/model_monitoring/db/stores/base/__init__.py +15 -0
  130. mlrun/model_monitoring/db/stores/base/store.py +213 -0
  131. mlrun/model_monitoring/db/stores/sqldb/__init__.py +13 -0
  132. mlrun/model_monitoring/db/stores/sqldb/models/__init__.py +71 -0
  133. mlrun/model_monitoring/db/stores/sqldb/models/base.py +190 -0
  134. mlrun/model_monitoring/db/stores/sqldb/models/mysql.py +103 -0
  135. mlrun/model_monitoring/{stores/models/mysql.py → db/stores/sqldb/models/sqlite.py} +19 -13
  136. mlrun/model_monitoring/db/stores/sqldb/sql_store.py +659 -0
  137. mlrun/model_monitoring/db/stores/v3io_kv/__init__.py +13 -0
  138. mlrun/model_monitoring/db/stores/v3io_kv/kv_store.py +726 -0
  139. mlrun/model_monitoring/db/tsdb/__init__.py +105 -0
  140. mlrun/model_monitoring/db/tsdb/base.py +448 -0
  141. mlrun/model_monitoring/db/tsdb/helpers.py +30 -0
  142. mlrun/model_monitoring/db/tsdb/tdengine/__init__.py +15 -0
  143. mlrun/model_monitoring/db/tsdb/tdengine/schemas.py +298 -0
  144. mlrun/model_monitoring/db/tsdb/tdengine/stream_graph_steps.py +42 -0
  145. mlrun/model_monitoring/db/tsdb/tdengine/tdengine_connector.py +522 -0
  146. mlrun/model_monitoring/db/tsdb/v3io/__init__.py +15 -0
  147. mlrun/model_monitoring/db/tsdb/v3io/stream_graph_steps.py +158 -0
  148. mlrun/model_monitoring/db/tsdb/v3io/v3io_connector.py +849 -0
  149. mlrun/model_monitoring/features_drift_table.py +34 -22
  150. mlrun/model_monitoring/helpers.py +177 -39
  151. mlrun/model_monitoring/model_endpoint.py +3 -2
  152. mlrun/model_monitoring/stream_processing.py +165 -398
  153. mlrun/model_monitoring/tracking_policy.py +7 -1
  154. mlrun/model_monitoring/writer.py +161 -125
  155. mlrun/package/packagers/default_packager.py +2 -2
  156. mlrun/package/packagers_manager.py +1 -0
  157. mlrun/package/utils/_formatter.py +2 -2
  158. mlrun/platforms/__init__.py +11 -10
  159. mlrun/platforms/iguazio.py +67 -228
  160. mlrun/projects/__init__.py +6 -1
  161. mlrun/projects/operations.py +47 -20
  162. mlrun/projects/pipelines.py +396 -249
  163. mlrun/projects/project.py +1125 -414
  164. mlrun/render.py +28 -22
  165. mlrun/run.py +207 -180
  166. mlrun/runtimes/__init__.py +76 -11
  167. mlrun/runtimes/base.py +40 -14
  168. mlrun/runtimes/daskjob.py +9 -2
  169. mlrun/runtimes/databricks_job/databricks_runtime.py +1 -0
  170. mlrun/runtimes/databricks_job/databricks_wrapper.py +1 -1
  171. mlrun/runtimes/funcdoc.py +1 -29
  172. mlrun/runtimes/kubejob.py +34 -128
  173. mlrun/runtimes/local.py +39 -10
  174. mlrun/runtimes/mpijob/__init__.py +0 -20
  175. mlrun/runtimes/mpijob/abstract.py +8 -8
  176. mlrun/runtimes/mpijob/v1.py +1 -1
  177. mlrun/runtimes/nuclio/api_gateway.py +646 -177
  178. mlrun/runtimes/nuclio/application/__init__.py +15 -0
  179. mlrun/runtimes/nuclio/application/application.py +758 -0
  180. mlrun/runtimes/nuclio/application/reverse_proxy.go +95 -0
  181. mlrun/runtimes/nuclio/function.py +188 -68
  182. mlrun/runtimes/nuclio/serving.py +57 -60
  183. mlrun/runtimes/pod.py +191 -58
  184. mlrun/runtimes/remotesparkjob.py +11 -8
  185. mlrun/runtimes/sparkjob/spark3job.py +17 -18
  186. mlrun/runtimes/utils.py +40 -73
  187. mlrun/secrets.py +6 -2
  188. mlrun/serving/__init__.py +8 -1
  189. mlrun/serving/remote.py +2 -3
  190. mlrun/serving/routers.py +89 -64
  191. mlrun/serving/server.py +54 -26
  192. mlrun/serving/states.py +187 -56
  193. mlrun/serving/utils.py +19 -11
  194. mlrun/serving/v2_serving.py +136 -63
  195. mlrun/track/tracker.py +2 -1
  196. mlrun/track/trackers/mlflow_tracker.py +5 -0
  197. mlrun/utils/async_http.py +26 -6
  198. mlrun/utils/db.py +18 -0
  199. mlrun/utils/helpers.py +375 -105
  200. mlrun/utils/http.py +2 -2
  201. mlrun/utils/logger.py +75 -9
  202. mlrun/utils/notifications/notification/__init__.py +14 -10
  203. mlrun/utils/notifications/notification/base.py +48 -0
  204. mlrun/utils/notifications/notification/console.py +2 -0
  205. mlrun/utils/notifications/notification/git.py +24 -1
  206. mlrun/utils/notifications/notification/ipython.py +2 -0
  207. mlrun/utils/notifications/notification/slack.py +96 -21
  208. mlrun/utils/notifications/notification/webhook.py +63 -2
  209. mlrun/utils/notifications/notification_pusher.py +146 -16
  210. mlrun/utils/regex.py +9 -0
  211. mlrun/utils/retryer.py +3 -2
  212. mlrun/utils/v3io_clients.py +2 -3
  213. mlrun/utils/version/version.json +2 -2
  214. mlrun-1.7.2.dist-info/METADATA +390 -0
  215. mlrun-1.7.2.dist-info/RECORD +351 -0
  216. {mlrun-1.7.0rc5.dist-info → mlrun-1.7.2.dist-info}/WHEEL +1 -1
  217. mlrun/feature_store/retrieval/conversion.py +0 -271
  218. mlrun/kfpops.py +0 -868
  219. mlrun/model_monitoring/application.py +0 -310
  220. mlrun/model_monitoring/batch.py +0 -974
  221. mlrun/model_monitoring/controller_handler.py +0 -37
  222. mlrun/model_monitoring/prometheus.py +0 -216
  223. mlrun/model_monitoring/stores/__init__.py +0 -111
  224. mlrun/model_monitoring/stores/kv_model_endpoint_store.py +0 -574
  225. mlrun/model_monitoring/stores/model_endpoint_store.py +0 -145
  226. mlrun/model_monitoring/stores/models/__init__.py +0 -27
  227. mlrun/model_monitoring/stores/models/base.py +0 -84
  228. mlrun/model_monitoring/stores/sql_model_endpoint_store.py +0 -382
  229. mlrun/platforms/other.py +0 -305
  230. mlrun-1.7.0rc5.dist-info/METADATA +0 -269
  231. mlrun-1.7.0rc5.dist-info/RECORD +0 -323
  232. {mlrun-1.7.0rc5.dist-info → mlrun-1.7.2.dist-info}/LICENSE +0 -0
  233. {mlrun-1.7.0rc5.dist-info → mlrun-1.7.2.dist-info}/entry_points.txt +0 -0
  234. {mlrun-1.7.0rc5.dist-info → mlrun-1.7.2.dist-info}/top_level.txt +0 -0
mlrun/__init__.py CHANGED
@@ -22,11 +22,16 @@ __all__ = [
22
22
  "handler",
23
23
  "ArtifactType",
24
24
  "get_secret_or_env",
25
+ "mount_v3io",
26
+ "v3io_cred",
27
+ "auto_mount",
28
+ "VolumeMount",
25
29
  ]
26
30
 
27
31
  from os import environ, path
28
32
 
29
33
  import dotenv
34
+ import mlrun_pipelines
30
35
 
31
36
  from .config import config as mlconf
32
37
  from .datastore import DataItem, store_manager
@@ -35,7 +40,6 @@ from .errors import MLRunInvalidArgumentError, MLRunNotFoundError
35
40
  from .execution import MLClientCtx
36
41
  from .model import RunObject, RunTemplate, new_task
37
42
  from .package import ArtifactType, DefaultPackager, Packager, handler
38
- from .platforms import VolumeMount, auto_mount, mount_v3io, v3io_cred
39
43
  from .projects import (
40
44
  ProjectMetadata,
41
45
  build_function,
@@ -65,6 +69,11 @@ from .utils.version import Version
65
69
 
66
70
  __version__ = Version().get()["version"]
67
71
 
72
+ VolumeMount = mlrun_pipelines.common.mounts.VolumeMount
73
+ mount_v3io = mlrun_pipelines.mounts.mount_v3io
74
+ v3io_cred = mlrun_pipelines.mounts.v3io_cred
75
+ auto_mount = mlrun_pipelines.mounts.auto_mount
76
+
68
77
 
69
78
  def get_version():
70
79
  """get current mlrun version"""
@@ -97,6 +106,7 @@ def set_environment(
97
106
  example::
98
107
 
99
108
  from os import path
109
+
100
110
  project_name, artifact_path = set_environment()
101
111
  set_environment("http://localhost:8080", artifact_path="./")
102
112
  set_environment(env_file="mlrun.env")
mlrun/__main__.py CHANGED
@@ -22,17 +22,16 @@ from ast import literal_eval
22
22
  from base64 import b64decode, b64encode
23
23
  from os import environ, path, remove
24
24
  from pprint import pprint
25
- from subprocess import Popen
26
- from sys import executable
27
- from urllib.parse import urlparse
28
25
 
29
26
  import click
30
27
  import dotenv
31
28
  import pandas as pd
32
29
  import yaml
30
+ from mlrun_pipelines.mounts import auto_mount as auto_mount_modifier
33
31
  from tabulate import tabulate
34
32
 
35
33
  import mlrun
34
+ import mlrun.common.constants as mlrun_constants
36
35
  import mlrun.common.schemas
37
36
  from mlrun.common.helpers import parse_versioned_object_uri
38
37
 
@@ -40,7 +39,6 @@ from .config import config as mlconf
40
39
  from .db import get_run_db
41
40
  from .errors import err_to_str
42
41
  from .model import RunTemplate
43
- from .platforms import auto_mount as auto_mount_modifier
44
42
  from .projects import load_project
45
43
  from .run import (
46
44
  get_object,
@@ -52,12 +50,12 @@ from .run import (
52
50
  from .runtimes import RemoteRuntime, RunError, RuntimeKinds, ServingRuntime
53
51
  from .secrets import SecretsStore
54
52
  from .utils import (
53
+ RunKeys,
55
54
  dict_to_yaml,
56
55
  get_in,
57
56
  is_relative_path,
58
57
  list2dict,
59
58
  logger,
60
- run_keys,
61
59
  update_in,
62
60
  )
63
61
  from .utils.version import Version
@@ -104,7 +102,9 @@ def main():
104
102
  )
105
103
  @click.option("--uid", help="unique run ID")
106
104
  @click.option("--name", help="run name")
107
- @click.option("--workflow", help="workflow name/id")
105
+ @click.option(
106
+ "--workflow", help="sets the run labels to match the given workflow name/id"
107
+ )
108
108
  @click.option("--project", help="project name/id")
109
109
  @click.option("--db", default="", help="save run results to path or DB url")
110
110
  @click.option(
@@ -259,8 +259,10 @@ def run(
259
259
  runobj.metadata.labels[k] = v
260
260
 
261
261
  if workflow:
262
- runobj.metadata.labels["workflow"] = workflow
263
- runobj.metadata.labels["mlrun/runner-pod"] = socket.gethostname()
262
+ runobj.metadata.labels[mlrun_constants.MLRunInternalLabels.workflow] = workflow
263
+ runobj.metadata.labels[mlrun_constants.MLRunInternalLabels.runner_pod] = (
264
+ socket.gethostname()
265
+ )
264
266
 
265
267
  if db:
266
268
  mlconf.dbpath = db
@@ -378,15 +380,15 @@ def run(
378
380
  set_item(runobj.spec.hyper_param_options, hyper_param_strategy, "strategy")
379
381
  set_item(runobj.spec.hyper_param_options, selector, "selector")
380
382
 
381
- set_item(runobj.spec, inputs, run_keys.inputs, list2dict(inputs))
383
+ set_item(runobj.spec, inputs, RunKeys.inputs, list2dict(inputs))
382
384
  set_item(
383
- runobj.spec, returns, run_keys.returns, [py_eval(value) for value in returns]
385
+ runobj.spec, returns, RunKeys.returns, [py_eval(value) for value in returns]
384
386
  )
385
- set_item(runobj.spec, in_path, run_keys.input_path)
386
- set_item(runobj.spec, out_path, run_keys.output_path)
387
- set_item(runobj.spec, outputs, run_keys.outputs, list(outputs))
387
+ set_item(runobj.spec, in_path, RunKeys.input_path)
388
+ set_item(runobj.spec, out_path, RunKeys.output_path)
389
+ set_item(runobj.spec, outputs, RunKeys.outputs, list(outputs))
388
390
  set_item(
389
- runobj.spec, secrets, run_keys.secrets, line2keylist(secrets, "kind", "source")
391
+ runobj.spec, secrets, RunKeys.secrets, line2keylist(secrets, "kind", "source")
390
392
  )
391
393
  set_item(runobj.spec, verbose, "verbose")
392
394
  set_item(runobj.spec, scrape_metrics, "scrape_metrics")
@@ -469,6 +471,17 @@ def run(
469
471
  is_flag=True,
470
472
  help="ensure the project exists, if not, create project",
471
473
  )
474
+ @click.option(
475
+ "--state-file-path", default="/tmp/state", help="path to file with state data"
476
+ )
477
+ @click.option(
478
+ "--image-file-path", default="/tmp/image", help="path to file with image data"
479
+ )
480
+ @click.option(
481
+ "--full-image-file-path",
482
+ default="/tmp/fullimage",
483
+ help="path to file with full image data",
484
+ )
472
485
  def build(
473
486
  func_url,
474
487
  name,
@@ -488,6 +501,9 @@ def build(
488
501
  skip,
489
502
  env_file,
490
503
  ensure_project,
504
+ state_file_path,
505
+ image_file_path,
506
+ full_image_file_path,
491
507
  ):
492
508
  """Build a container image from code and requirements."""
493
509
 
@@ -505,6 +521,8 @@ def build(
505
521
  if kfp:
506
522
  print("Runtime:")
507
523
  pprint(runtime)
524
+ # use kind = "job" by default if not specified
525
+ runtime.setdefault("kind", "job")
508
526
  func = new_function(runtime=runtime)
509
527
 
510
528
  elif func_url:
@@ -575,12 +593,12 @@ def build(
575
593
  state = func.status.state
576
594
  image = func.spec.image
577
595
  if kfp:
578
- with open("/tmp/state", "w") as fp:
596
+ with open(state_file_path, "w") as fp:
579
597
  fp.write(state or "none")
580
598
  full_image = func.full_image_path(image) or ""
581
- with open("/tmp/image", "w") as fp:
599
+ with open(image_file_path, "w") as fp:
582
600
  fp.write(image)
583
- with open("/tmp/fullimage", "w") as fp:
601
+ with open(full_image_file_path, "w") as fp:
584
602
  fp.write(full_image)
585
603
  print("Full image path = ", full_image)
586
604
 
@@ -716,9 +734,11 @@ def get(kind, name, selector, namespace, uid, project, tag, db, extra_args):
716
734
  if db:
717
735
  mlconf.dbpath = db
718
736
  if not project:
719
- print("Warning, project parameter was not specified using default !")
737
+ logger.warning(
738
+ "Project parameter was not specified. Defaulting to 'default' project"
739
+ )
720
740
  if kind.startswith("po"):
721
- print("Unsupported, use 'get runtimes' instead")
741
+ logger.warning("Unsupported, use 'get runtimes' instead")
722
742
  return
723
743
 
724
744
  elif kind.startswith("runtime"):
@@ -825,108 +845,6 @@ def get(kind, name, selector, namespace, uid, project, tag, db, extra_args):
825
845
  )
826
846
 
827
847
 
828
- @main.command(deprecated=True)
829
- @click.option("--port", "-p", help="port to listen on", type=int)
830
- @click.option("--dirpath", "-d", help="database directory (dirpath)")
831
- @click.option("--dsn", "-s", help="database dsn, e.g. sqlite:///db/mlrun.db")
832
- @click.option("--logs-path", "-l", help="logs directory path")
833
- @click.option("--data-volume", "-v", help="path prefix to the location of artifacts")
834
- @click.option("--verbose", is_flag=True, help="verbose log")
835
- @click.option("--background", "-b", is_flag=True, help="run in background process")
836
- @click.option("--artifact-path", "-a", help="default artifact path")
837
- @click.option(
838
- "--update-env",
839
- default="",
840
- is_flag=False,
841
- flag_value=mlrun.config.default_env_file,
842
- help=f"update the specified mlrun .env file (if TEXT not provided defaults to {mlrun.config.default_env_file})",
843
- )
844
- def db(
845
- port,
846
- dirpath,
847
- dsn,
848
- logs_path,
849
- data_volume,
850
- verbose,
851
- background,
852
- artifact_path,
853
- update_env,
854
- ):
855
- """Run HTTP api/database server"""
856
- warnings.warn(
857
- "The `mlrun db` command is deprecated in 1.5.0 and will be removed in 1.7.0, it is for internal use only.",
858
- FutureWarning,
859
- )
860
- env = environ.copy()
861
- # ignore client side .env file (so import mlrun in server will not try to connect to local/remote DB)
862
- env["MLRUN_IGNORE_ENV_FILE"] = "true"
863
- env["MLRUN_DBPATH"] = ""
864
-
865
- if port is not None:
866
- env["MLRUN_HTTPDB__PORT"] = str(port)
867
- if dirpath is not None:
868
- env["MLRUN_HTTPDB__DIRPATH"] = dirpath
869
- if dsn is not None:
870
- if dsn.startswith("sqlite://") and "check_same_thread=" not in dsn:
871
- dsn += "?check_same_thread=false"
872
- env["MLRUN_HTTPDB__DSN"] = dsn
873
- if logs_path is not None:
874
- env["MLRUN_HTTPDB__LOGS_PATH"] = logs_path
875
- if data_volume is not None:
876
- env["MLRUN_HTTPDB__DATA_VOLUME"] = data_volume
877
- if verbose:
878
- env["MLRUN_LOG_LEVEL"] = "DEBUG"
879
- if artifact_path or "MLRUN_ARTIFACT_PATH" not in env:
880
- if not artifact_path:
881
- artifact_path = (
882
- env.get("MLRUN_HTTPDB__DATA_VOLUME", "./artifacts").rstrip("/")
883
- + "/{{project}}"
884
- )
885
- env["MLRUN_ARTIFACT_PATH"] = path.realpath(path.expanduser(artifact_path))
886
-
887
- env["MLRUN_IS_API_SERVER"] = "true"
888
-
889
- # create the DB dir if needed
890
- dsn = dsn or mlconf.httpdb.dsn
891
- if dsn and dsn.startswith("sqlite:///"):
892
- parsed = urlparse(dsn)
893
- p = pathlib.Path(parsed.path[1:]).parent
894
- p.mkdir(parents=True, exist_ok=True)
895
-
896
- cmd = [executable, "-m", "server.api.main"]
897
- pid = None
898
- if background:
899
- print("Starting MLRun API service in the background...")
900
- child = Popen(
901
- cmd,
902
- env=env,
903
- stdout=open("mlrun-stdout.log", "w"),
904
- stderr=open("mlrun-stderr.log", "w"),
905
- start_new_session=True,
906
- )
907
- pid = child.pid
908
- print(
909
- f"Background pid: {pid}, logs written to mlrun-stdout.log and mlrun-stderr.log, use:\n"
910
- f"`kill {pid}` (linux/mac) or `taskkill /pid {pid} /t /f` (windows), to kill the mlrun service process"
911
- )
912
- else:
913
- child = Popen(cmd, env=env)
914
- returncode = child.wait()
915
- if returncode != 0:
916
- raise SystemExit(returncode)
917
- if update_env:
918
- # update mlrun client env file with the API path, so client will use the new DB
919
- # update and PID, allow killing the correct process in a config script
920
- filename = path.expanduser(update_env)
921
- dotenv.set_key(
922
- filename, "MLRUN_DBPATH", f"http://localhost:{port or 8080}", quote_mode=""
923
- )
924
- dotenv.set_key(filename, "MLRUN_MOCK_NUCLIO_DEPLOYMENT", "auto", quote_mode="")
925
- if pid:
926
- dotenv.set_key(filename, "MLRUN_SERVICE_PID", str(pid), quote_mode="")
927
- print(f"Updated configuration in {update_env} .env file")
928
-
929
-
930
848
  @main.command()
931
849
  def version():
932
850
  """get mlrun version"""
@@ -1,4 +1,4 @@
1
- # Copyright 2023 Iguazio
1
+ # Copyright 2024 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.
@@ -11,8 +11,5 @@
11
11
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
- #
15
-
16
14
 
17
- ONE_GB = 1024 * 1024 * 1024
18
- ONE_MB = 1024 * 1024
15
+ from .alert import AlertConfig
mlrun/alerts/alert.py ADDED
@@ -0,0 +1,248 @@
1
+ # Copyright 2024 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
+ from typing import Union
16
+
17
+ import mlrun
18
+ import mlrun.common.schemas.alert as alert_objects
19
+ from mlrun.model import ModelObj
20
+
21
+
22
+ class AlertConfig(ModelObj):
23
+ _dict_fields = [
24
+ "project",
25
+ "name",
26
+ "description",
27
+ "summary",
28
+ "severity",
29
+ "reset_policy",
30
+ "state",
31
+ "count",
32
+ "created",
33
+ ]
34
+ _fields_to_serialize = ModelObj._fields_to_serialize + [
35
+ "entities",
36
+ "notifications",
37
+ "trigger",
38
+ "criteria",
39
+ ]
40
+
41
+ def __init__(
42
+ self,
43
+ project: str = None,
44
+ name: str = None,
45
+ template: Union[alert_objects.AlertTemplate, str] = None,
46
+ description: str = None,
47
+ summary: str = None,
48
+ severity: alert_objects.AlertSeverity = None,
49
+ trigger: alert_objects.AlertTrigger = None,
50
+ criteria: alert_objects.AlertCriteria = None,
51
+ reset_policy: alert_objects.ResetPolicy = None,
52
+ notifications: list[alert_objects.AlertNotification] = None,
53
+ entities: alert_objects.EventEntities = None,
54
+ id: int = None,
55
+ state: alert_objects.AlertActiveState = None,
56
+ created: str = None,
57
+ count: int = None,
58
+ ):
59
+ """Alert config object
60
+
61
+ Example::
62
+
63
+ # create an alert on endpoint_id, which will be triggered to slack if there is a "data_drift_detected" event
64
+ # 3 times in the next hour.
65
+
66
+ from mlrun.alerts import AlertConfig
67
+ import mlrun.common.schemas.alert as alert_objects
68
+
69
+ entity_kind = alert_objects.EventEntityKind.MODEL_ENDPOINT_RESULT
70
+ entity_id = get_default_result_instance_fqn(endpoint_id)
71
+ event_name = alert_objects.EventKind.DATA_DRIFT_DETECTED
72
+ notification = mlrun.model.Notification(
73
+ kind="slack",
74
+ name="slack_notification",
75
+ message="drift was detected",
76
+ severity="warning",
77
+ when=["now"],
78
+ condition="failed",
79
+ secret_params={
80
+ "webhook": "https://hooks.slack.com/",
81
+ },
82
+ ).to_dict()
83
+
84
+ alert_data = AlertConfig(
85
+ project="my-project",
86
+ name="drift-alert",
87
+ summary="a drift was detected",
88
+ severity=alert_objects.AlertSeverity.LOW,
89
+ entities=alert_objects.EventEntities(
90
+ kind=entity_kind, project="my-project", ids=[entity_id]
91
+ ),
92
+ trigger=alert_objects.AlertTrigger(events=[event_name]),
93
+ criteria=alert_objects.AlertCriteria(count=3, period="1h"),
94
+ notifications=[alert_objects.AlertNotification(notification=notification)],
95
+ )
96
+ project.store_alert_config(alert_data)
97
+
98
+ :param project: Name of the project to associate the alert with
99
+ :param name: Name of the alert
100
+ :param template: Optional parameter that allows creating an alert based on a predefined template.
101
+ You can pass either an AlertTemplate object or a string (the template name).
102
+ If a template is used, many fields of the alert will be auto-generated based on the
103
+ template.However, you still need to provide the following fields:
104
+ `name`, `project`, `entity`, `notifications`
105
+ :param description: Description of the alert
106
+ :param summary: Summary of the alert, will be sent in the generated notifications
107
+ :param severity: Severity of the alert
108
+ :param trigger: The events that will trigger this alert, may be a simple trigger based on events or
109
+ complex trigger which is based on a prometheus alert
110
+ :param criteria: When the alert will be triggered based on the specified number of events within the
111
+ defined time period.
112
+ :param reset_policy: When to clear the alert. May be "manual" for manual reset of the alert, or
113
+ "auto" if the criteria contains a time period
114
+ :param notifications: List of notifications to invoke once the alert is triggered
115
+ :param entities: Entities that the event relates to. The entity object will contain fields that
116
+ uniquely identify a given entity in the system
117
+ :param id: Internal id of the alert (user should not supply it)
118
+ :param state: State of the alert, may be active/inactive (user should not supply it)
119
+ :param created: When the alert is created (user should not supply it)
120
+ :param count: Internal counter of the alert (user should not supply it)
121
+ """
122
+ self.project = project
123
+ self.name = name
124
+ self.description = description
125
+ self.summary = summary
126
+ self.severity = severity
127
+ self.trigger = trigger
128
+ self.criteria = criteria
129
+ self.reset_policy = reset_policy
130
+ self.notifications = notifications or []
131
+ self.entities = entities
132
+ self.id = id
133
+ self.state = state
134
+ self.created = created
135
+ self.count = count
136
+
137
+ if template:
138
+ self._apply_template(template)
139
+
140
+ def validate_required_fields(self):
141
+ if not self.name:
142
+ raise mlrun.errors.MLRunInvalidArgumentError("Alert name must be provided")
143
+
144
+ def _serialize_field(
145
+ self, struct: dict, field_name: str = None, strip: bool = False
146
+ ):
147
+ if field_name == "entities":
148
+ if self.entities:
149
+ return (
150
+ self.entities.dict()
151
+ if not isinstance(self.entities, dict)
152
+ else self.entities
153
+ )
154
+ return None
155
+ if field_name == "notifications":
156
+ if self.notifications:
157
+ return [
158
+ notification_data.dict()
159
+ if not isinstance(notification_data, dict)
160
+ else notification_data
161
+ for notification_data in self.notifications
162
+ ]
163
+ return None
164
+ if field_name == "trigger":
165
+ if self.trigger:
166
+ return (
167
+ self.trigger.dict()
168
+ if not isinstance(self.trigger, dict)
169
+ else self.trigger
170
+ )
171
+ return None
172
+ if field_name == "criteria":
173
+ if self.criteria:
174
+ return (
175
+ self.criteria.dict()
176
+ if not isinstance(self.criteria, dict)
177
+ else self.criteria
178
+ )
179
+ return None
180
+ return super()._serialize_field(struct, field_name, strip)
181
+
182
+ def to_dict(self, fields: list = None, exclude: list = None, strip: bool = False):
183
+ if self.entities is None:
184
+ raise mlrun.errors.MLRunBadRequestError("Alert entity field is missing")
185
+ if not self.notifications:
186
+ raise mlrun.errors.MLRunBadRequestError(
187
+ "Alert must have at least one notification"
188
+ )
189
+ return super().to_dict(self._dict_fields)
190
+
191
+ @classmethod
192
+ def from_dict(cls, struct=None, fields=None, deprecated_fields: dict = None):
193
+ new_obj = super().from_dict(struct, fields=fields)
194
+
195
+ entity_data = struct.get("entities")
196
+ if entity_data:
197
+ entity_obj = alert_objects.EventEntities.parse_obj(entity_data)
198
+ new_obj.entities = entity_obj
199
+
200
+ notifications_data = struct.get("notifications")
201
+ if notifications_data:
202
+ notifications_objs = [
203
+ alert_objects.AlertNotification.parse_obj(notification)
204
+ for notification in notifications_data
205
+ ]
206
+ new_obj.notifications = notifications_objs
207
+
208
+ trigger_data = struct.get("trigger")
209
+ if trigger_data:
210
+ trigger_obj = alert_objects.AlertTrigger.parse_obj(trigger_data)
211
+ new_obj.trigger = trigger_obj
212
+
213
+ criteria_data = struct.get("criteria")
214
+ if criteria_data:
215
+ criteria_obj = alert_objects.AlertCriteria.parse_obj(criteria_data)
216
+ new_obj.criteria = criteria_obj
217
+ return new_obj
218
+
219
+ def with_notifications(self, notifications: list[alert_objects.AlertNotification]):
220
+ if not isinstance(notifications, list) or not all(
221
+ isinstance(item, alert_objects.AlertNotification) for item in notifications
222
+ ):
223
+ raise ValueError(
224
+ "Notifications parameter must be a list of AlertNotification"
225
+ )
226
+ for notification_data in notifications:
227
+ self.notifications.append(notification_data)
228
+ return self
229
+
230
+ def with_entities(self, entities: alert_objects.EventEntities):
231
+ if not isinstance(entities, alert_objects.EventEntities):
232
+ raise ValueError("Entities parameter must be of type: EventEntities")
233
+ self.entities = entities
234
+ return self
235
+
236
+ def _apply_template(self, template):
237
+ if isinstance(template, str):
238
+ db = mlrun.get_run_db()
239
+ template = db.get_alert_template(template)
240
+
241
+ # Apply parameters from the template to the AlertConfig object only if they are not already specified by the
242
+ # user in the current configuration.
243
+ # User-provided parameters will take precedence over corresponding template values
244
+ self.summary = self.summary or template.summary
245
+ self.severity = self.severity or template.severity
246
+ self.criteria = self.criteria or template.criteria
247
+ self.trigger = self.trigger or template.trigger
248
+ self.reset_policy = self.reset_policy or template.reset_policy
@@ -25,6 +25,7 @@ schema.
25
25
  import sys
26
26
  import warnings
27
27
 
28
+ import mlrun.common.formatters
28
29
  import mlrun.common.schemas
29
30
  import mlrun.common.schemas.artifact as old_artifact
30
31
  import mlrun.common.schemas.auth as old_auth
@@ -96,7 +97,7 @@ sys.modules["mlrun.api.schemas.tag"] = old_tag
96
97
  # and return the new schema. This is done for backwards compatibility with mlrun.api.schemas.
97
98
  ArtifactCategories = DeprecationHelper(mlrun.common.schemas.ArtifactCategories)
98
99
  ArtifactIdentifier = DeprecationHelper(mlrun.common.schemas.ArtifactIdentifier)
99
- ArtifactsFormat = DeprecationHelper(mlrun.common.schemas.ArtifactsFormat)
100
+ ArtifactsFormat = DeprecationHelper(mlrun.common.formatters.ArtifactFormat)
100
101
  AuthInfo = DeprecationHelper(mlrun.common.schemas.AuthInfo)
101
102
  AuthorizationAction = DeprecationHelper(mlrun.common.schemas.AuthorizationAction)
102
103
  AuthorizationResourceTypes = DeprecationHelper(
@@ -221,7 +222,7 @@ ObjectKind = DeprecationHelper(mlrun.common.schemas.ObjectKind)
221
222
  ObjectMetadata = DeprecationHelper(mlrun.common.schemas.ObjectMetadata)
222
223
  ObjectSpec = DeprecationHelper(mlrun.common.schemas.ObjectSpec)
223
224
  ObjectStatus = DeprecationHelper(mlrun.common.schemas.ObjectStatus)
224
- PipelinesFormat = DeprecationHelper(mlrun.common.schemas.PipelinesFormat)
225
+ PipelinesFormat = DeprecationHelper(mlrun.common.formatters.PipelineFormat)
225
226
  PipelinesOutput = DeprecationHelper(mlrun.common.schemas.PipelinesOutput)
226
227
  PipelinesPagination = DeprecationHelper(mlrun.common.schemas.PipelinesPagination)
227
228
  IguazioProject = DeprecationHelper(mlrun.common.schemas.IguazioProject)
@@ -229,7 +230,7 @@ Project = DeprecationHelper(mlrun.common.schemas.Project)
229
230
  ProjectDesiredState = DeprecationHelper(mlrun.common.schemas.ProjectDesiredState)
230
231
  ProjectMetadata = DeprecationHelper(mlrun.common.schemas.ProjectMetadata)
231
232
  ProjectOwner = DeprecationHelper(mlrun.common.schemas.ProjectOwner)
232
- ProjectsFormat = DeprecationHelper(mlrun.common.schemas.ProjectsFormat)
233
+ ProjectsFormat = DeprecationHelper(mlrun.common.formatters.ProjectFormat)
233
234
  ProjectsOutput = DeprecationHelper(mlrun.common.schemas.ProjectsOutput)
234
235
  ProjectSpec = DeprecationHelper(mlrun.common.schemas.ProjectSpec)
235
236
  ProjectState = DeprecationHelper(mlrun.common.schemas.ProjectState)
@@ -17,14 +17,19 @@
17
17
  # Don't remove this, used by sphinx documentation
18
18
  __all__ = ["get_model", "update_model"]
19
19
 
20
- from .base import Artifact, ArtifactMetadata, ArtifactSpec, get_artifact_meta
20
+ from .base import (
21
+ Artifact,
22
+ ArtifactMetadata,
23
+ ArtifactSpec,
24
+ DirArtifact,
25
+ get_artifact_meta,
26
+ )
21
27
  from .dataset import DatasetArtifact, TableArtifact, update_dataset_meta
22
28
  from .manager import (
23
29
  ArtifactManager,
24
30
  ArtifactProducer,
25
31
  artifact_types,
26
32
  dict_to_artifact,
27
- legacy_artifact_types,
28
33
  )
29
34
  from .model import ModelArtifact, get_model, update_model
30
- from .plots import BokehArtifact, ChartArtifact, PlotArtifact, PlotlyArtifact
35
+ from .plots import PlotArtifact, PlotlyArtifact