mlrun 1.7.0rc28__py3-none-any.whl → 1.7.0rc55__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 (135) hide show
  1. mlrun/__main__.py +4 -2
  2. mlrun/alerts/alert.py +75 -8
  3. mlrun/artifacts/base.py +1 -0
  4. mlrun/artifacts/manager.py +9 -2
  5. mlrun/common/constants.py +4 -1
  6. mlrun/common/db/sql_session.py +3 -2
  7. mlrun/common/formatters/__init__.py +1 -0
  8. mlrun/common/formatters/artifact.py +1 -0
  9. mlrun/{model_monitoring/application.py → common/formatters/feature_set.py} +20 -6
  10. mlrun/common/formatters/run.py +3 -0
  11. mlrun/common/helpers.py +0 -1
  12. mlrun/common/schemas/__init__.py +3 -1
  13. mlrun/common/schemas/alert.py +15 -12
  14. mlrun/common/schemas/api_gateway.py +6 -6
  15. mlrun/common/schemas/auth.py +5 -0
  16. mlrun/common/schemas/client_spec.py +0 -1
  17. mlrun/common/schemas/common.py +7 -4
  18. mlrun/common/schemas/frontend_spec.py +7 -0
  19. mlrun/common/schemas/function.py +7 -0
  20. mlrun/common/schemas/model_monitoring/__init__.py +4 -3
  21. mlrun/common/schemas/model_monitoring/constants.py +41 -26
  22. mlrun/common/schemas/model_monitoring/model_endpoints.py +23 -47
  23. mlrun/common/schemas/notification.py +69 -12
  24. mlrun/common/schemas/project.py +45 -12
  25. mlrun/common/schemas/workflow.py +10 -2
  26. mlrun/common/types.py +1 -0
  27. mlrun/config.py +91 -35
  28. mlrun/data_types/data_types.py +6 -1
  29. mlrun/data_types/spark.py +2 -2
  30. mlrun/data_types/to_pandas.py +57 -25
  31. mlrun/datastore/__init__.py +1 -0
  32. mlrun/datastore/alibaba_oss.py +3 -2
  33. mlrun/datastore/azure_blob.py +125 -37
  34. mlrun/datastore/base.py +42 -21
  35. mlrun/datastore/datastore.py +4 -2
  36. mlrun/datastore/datastore_profile.py +1 -1
  37. mlrun/datastore/dbfs_store.py +3 -7
  38. mlrun/datastore/filestore.py +1 -3
  39. mlrun/datastore/google_cloud_storage.py +85 -29
  40. mlrun/datastore/inmem.py +4 -1
  41. mlrun/datastore/redis.py +1 -0
  42. mlrun/datastore/s3.py +25 -12
  43. mlrun/datastore/sources.py +76 -4
  44. mlrun/datastore/spark_utils.py +30 -0
  45. mlrun/datastore/storeytargets.py +151 -0
  46. mlrun/datastore/targets.py +102 -131
  47. mlrun/datastore/v3io.py +1 -0
  48. mlrun/db/base.py +15 -6
  49. mlrun/db/httpdb.py +57 -28
  50. mlrun/db/nopdb.py +29 -5
  51. mlrun/errors.py +20 -3
  52. mlrun/execution.py +46 -5
  53. mlrun/feature_store/api.py +25 -1
  54. mlrun/feature_store/common.py +6 -11
  55. mlrun/feature_store/feature_vector.py +3 -1
  56. mlrun/feature_store/retrieval/job.py +4 -1
  57. mlrun/feature_store/retrieval/spark_merger.py +10 -39
  58. mlrun/feature_store/steps.py +8 -0
  59. mlrun/frameworks/_common/plan.py +3 -3
  60. mlrun/frameworks/_ml_common/plan.py +1 -1
  61. mlrun/frameworks/parallel_coordinates.py +2 -3
  62. mlrun/frameworks/sklearn/mlrun_interface.py +13 -3
  63. mlrun/k8s_utils.py +48 -2
  64. mlrun/launcher/client.py +6 -6
  65. mlrun/launcher/local.py +2 -2
  66. mlrun/model.py +215 -34
  67. mlrun/model_monitoring/api.py +38 -24
  68. mlrun/model_monitoring/applications/__init__.py +1 -2
  69. mlrun/model_monitoring/applications/_application_steps.py +60 -29
  70. mlrun/model_monitoring/applications/base.py +2 -174
  71. mlrun/model_monitoring/applications/context.py +197 -70
  72. mlrun/model_monitoring/applications/evidently_base.py +11 -85
  73. mlrun/model_monitoring/applications/histogram_data_drift.py +21 -16
  74. mlrun/model_monitoring/applications/results.py +4 -4
  75. mlrun/model_monitoring/controller.py +110 -282
  76. mlrun/model_monitoring/db/stores/__init__.py +8 -3
  77. mlrun/model_monitoring/db/stores/base/store.py +3 -0
  78. mlrun/model_monitoring/db/stores/sqldb/models/base.py +9 -7
  79. mlrun/model_monitoring/db/stores/sqldb/models/mysql.py +18 -3
  80. mlrun/model_monitoring/db/stores/sqldb/sql_store.py +43 -23
  81. mlrun/model_monitoring/db/stores/v3io_kv/kv_store.py +48 -35
  82. mlrun/model_monitoring/db/tsdb/__init__.py +7 -2
  83. mlrun/model_monitoring/db/tsdb/base.py +147 -15
  84. mlrun/model_monitoring/db/tsdb/tdengine/schemas.py +94 -55
  85. mlrun/model_monitoring/db/tsdb/tdengine/stream_graph_steps.py +0 -3
  86. mlrun/model_monitoring/db/tsdb/tdengine/tdengine_connector.py +144 -38
  87. mlrun/model_monitoring/db/tsdb/v3io/stream_graph_steps.py +44 -3
  88. mlrun/model_monitoring/db/tsdb/v3io/v3io_connector.py +246 -57
  89. mlrun/model_monitoring/helpers.py +70 -50
  90. mlrun/model_monitoring/stream_processing.py +96 -195
  91. mlrun/model_monitoring/writer.py +13 -5
  92. mlrun/package/packagers/default_packager.py +2 -2
  93. mlrun/projects/operations.py +16 -8
  94. mlrun/projects/pipelines.py +126 -115
  95. mlrun/projects/project.py +286 -129
  96. mlrun/render.py +3 -3
  97. mlrun/run.py +38 -19
  98. mlrun/runtimes/__init__.py +19 -8
  99. mlrun/runtimes/base.py +4 -1
  100. mlrun/runtimes/daskjob.py +1 -1
  101. mlrun/runtimes/funcdoc.py +1 -1
  102. mlrun/runtimes/kubejob.py +6 -6
  103. mlrun/runtimes/local.py +12 -5
  104. mlrun/runtimes/nuclio/api_gateway.py +68 -8
  105. mlrun/runtimes/nuclio/application/application.py +307 -70
  106. mlrun/runtimes/nuclio/function.py +63 -14
  107. mlrun/runtimes/nuclio/serving.py +10 -10
  108. mlrun/runtimes/pod.py +25 -19
  109. mlrun/runtimes/remotesparkjob.py +2 -5
  110. mlrun/runtimes/sparkjob/spark3job.py +16 -17
  111. mlrun/runtimes/utils.py +34 -0
  112. mlrun/serving/routers.py +2 -5
  113. mlrun/serving/server.py +37 -19
  114. mlrun/serving/states.py +30 -3
  115. mlrun/serving/v2_serving.py +44 -35
  116. mlrun/track/trackers/mlflow_tracker.py +5 -0
  117. mlrun/utils/async_http.py +1 -1
  118. mlrun/utils/db.py +18 -0
  119. mlrun/utils/helpers.py +150 -36
  120. mlrun/utils/http.py +1 -1
  121. mlrun/utils/notifications/notification/__init__.py +0 -1
  122. mlrun/utils/notifications/notification/webhook.py +8 -1
  123. mlrun/utils/notifications/notification_pusher.py +1 -1
  124. mlrun/utils/v3io_clients.py +2 -2
  125. mlrun/utils/version/version.json +2 -2
  126. {mlrun-1.7.0rc28.dist-info → mlrun-1.7.0rc55.dist-info}/METADATA +153 -66
  127. {mlrun-1.7.0rc28.dist-info → mlrun-1.7.0rc55.dist-info}/RECORD +131 -134
  128. {mlrun-1.7.0rc28.dist-info → mlrun-1.7.0rc55.dist-info}/WHEEL +1 -1
  129. mlrun/feature_store/retrieval/conversion.py +0 -271
  130. mlrun/model_monitoring/controller_handler.py +0 -37
  131. mlrun/model_monitoring/evidently_application.py +0 -20
  132. mlrun/model_monitoring/prometheus.py +0 -216
  133. {mlrun-1.7.0rc28.dist-info → mlrun-1.7.0rc55.dist-info}/LICENSE +0 -0
  134. {mlrun-1.7.0rc28.dist-info → mlrun-1.7.0rc55.dist-info}/entry_points.txt +0 -0
  135. {mlrun-1.7.0rc28.dist-info → mlrun-1.7.0rc55.dist-info}/top_level.txt +0 -0
mlrun/__main__.py CHANGED
@@ -734,9 +734,11 @@ def get(kind, name, selector, namespace, uid, project, tag, db, extra_args):
734
734
  if db:
735
735
  mlconf.dbpath = db
736
736
  if not project:
737
- print("Warning, project parameter was not specified using default !")
737
+ logger.warning(
738
+ "Project parameter was not specified. Defaulting to 'default' project"
739
+ )
738
740
  if kind.startswith("po"):
739
- print("Unsupported, use 'get runtimes' instead")
741
+ logger.warning("Unsupported, use 'get runtimes' instead")
740
742
  return
741
743
 
742
744
  elif kind.startswith("runtime"):
mlrun/alerts/alert.py CHANGED
@@ -28,6 +28,8 @@ class AlertConfig(ModelObj):
28
28
  "severity",
29
29
  "reset_policy",
30
30
  "state",
31
+ "count",
32
+ "created",
31
33
  ]
32
34
  _fields_to_serialize = ModelObj._fields_to_serialize + [
33
35
  "entities",
@@ -54,6 +56,69 @@ class AlertConfig(ModelObj):
54
56
  created: str = None,
55
57
  count: int = None,
56
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
+ """
57
122
  self.project = project
58
123
  self.name = name
59
124
  self.description = description
@@ -73,8 +138,8 @@ class AlertConfig(ModelObj):
73
138
  self._apply_template(template)
74
139
 
75
140
  def validate_required_fields(self):
76
- if not self.project or not self.name:
77
- raise mlrun.errors.MLRunBadRequestError("Project and name must be provided")
141
+ if not self.name:
142
+ raise mlrun.errors.MLRunInvalidArgumentError("Alert name must be provided")
78
143
 
79
144
  def _serialize_field(
80
145
  self, struct: dict, field_name: str = None, strip: bool = False
@@ -173,9 +238,11 @@ class AlertConfig(ModelObj):
173
238
  db = mlrun.get_run_db()
174
239
  template = db.get_alert_template(template)
175
240
 
176
- # Extract parameters from the template and apply them to the AlertConfig object
177
- self.summary = template.summary
178
- self.severity = template.severity
179
- self.criteria = template.criteria
180
- self.trigger = template.trigger
181
- self.reset_policy = template.reset_policy
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
mlrun/artifacts/base.py CHANGED
@@ -632,6 +632,7 @@ class DirArtifactSpec(ArtifactSpec):
632
632
  "src_path",
633
633
  "target_path",
634
634
  "db_key",
635
+ "producer",
635
636
  ]
636
637
 
637
638
 
@@ -72,7 +72,12 @@ class ArtifactProducer:
72
72
  self.inputs = {}
73
73
 
74
74
  def get_meta(self) -> dict:
75
- return {"kind": self.kind, "name": self.name, "tag": self.tag}
75
+ return {
76
+ "kind": self.kind,
77
+ "name": self.name,
78
+ "tag": self.tag,
79
+ "owner": self.owner,
80
+ }
76
81
 
77
82
  @property
78
83
  def uid(self):
@@ -195,7 +200,9 @@ class ArtifactManager:
195
200
  :param artifact_path: The path to store the artifact.
196
201
  If not provided, the artifact will be stored in the default artifact path.
197
202
  :param format: The format of the artifact. (e.g. csv, json, html, etc.)
198
- :param upload: Whether to upload the artifact or not.
203
+ :param upload: Whether to upload the artifact to the datastore. If not provided, and the
204
+ `local_path` is not a directory, upload occurs by default. Directories are uploaded only when this
205
+ flag is explicitly set to `True`.
199
206
  :param labels: Labels to add to the artifact.
200
207
  :param db_key: The key to use when logging the artifact to the DB.
201
208
  If not provided, will generate a key based on the producer name and the artifact key.
mlrun/common/constants.py CHANGED
@@ -11,7 +11,6 @@
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
14
 
16
15
  IMAGE_NAME_ENRICH_REGISTRY_PREFIX = "." # prefix for image name to enrich with registry
17
16
  MLRUN_SERVING_CONF = "serving-conf"
@@ -66,10 +65,14 @@ class MLRunInternalLabels:
66
65
  task_name = f"{MLRUN_LABEL_PREFIX}task-name"
67
66
  resource_name = f"{MLRUN_LABEL_PREFIX}resource_name"
68
67
  created = f"{MLRUN_LABEL_PREFIX}created"
68
+ producer_type = f"{MLRUN_LABEL_PREFIX}producer-type"
69
+ app_name = f"{MLRUN_LABEL_PREFIX}app-name"
70
+ endpoint_id = f"{MLRUN_LABEL_PREFIX}endpoint-id"
69
71
  host = "host"
70
72
  job_type = "job-type"
71
73
  kind = "kind"
72
74
  component = "component"
75
+ mlrun_type = "mlrun__type"
73
76
 
74
77
  owner = "owner"
75
78
  v3io_user = "v3io_user"
@@ -11,13 +11,14 @@
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
14
 
16
15
 
17
16
  from sqlalchemy import create_engine
18
17
  from sqlalchemy.engine import Engine
19
18
  from sqlalchemy.orm import Session
20
- from sqlalchemy.orm import sessionmaker as SessionMaker
19
+ from sqlalchemy.orm import (
20
+ sessionmaker as SessionMaker, # noqa: N812 - `sessionmaker` is a class
21
+ )
21
22
 
22
23
  from mlrun.config import config
23
24
 
@@ -18,3 +18,4 @@ from .function import FunctionFormat # noqa
18
18
  from .pipeline import PipelineFormat # noqa
19
19
  from .project import ProjectFormat # noqa
20
20
  from .run import RunFormat # noqa
21
+ from .feature_set import FeatureSetFormat # noqa
@@ -37,6 +37,7 @@ class ArtifactFormat(ObjectFormat, mlrun.common.types.StrEnum):
37
37
  "spec.db_key",
38
38
  "spec.size",
39
39
  "spec.framework",
40
+ "spec.algorithm",
40
41
  "spec.metrics",
41
42
  "spec.target_path",
42
43
  ]
@@ -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,9 +11,23 @@
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
+ import typing
17
+
18
+ import mlrun.common.types
19
+
20
+ from .base import ObjectFormat
21
+
22
+
23
+ class FeatureSetFormat(ObjectFormat, mlrun.common.types.StrEnum):
24
+ minimal = "minimal"
14
25
 
15
- # TODO : delete this file in 1.9.0
16
- from mlrun.model_monitoring.applications import ( # noqa: F401
17
- ModelMonitoringApplicationBase,
18
- ModelMonitoringApplicationResult,
19
- )
26
+ @staticmethod
27
+ def format_method(_format: str) -> typing.Optional[typing.Callable]:
28
+ return {
29
+ FeatureSetFormat.full: None,
30
+ FeatureSetFormat.minimal: FeatureSetFormat.filter_obj_method(
31
+ ["kind", "metadata", "spec", "status.state"]
32
+ ),
33
+ }[_format]
@@ -22,5 +22,8 @@ class RunFormat(ObjectFormat, mlrun.common.types.StrEnum):
22
22
  # No enrichment, data is pulled as-is from the database.
23
23
  standard = "standard"
24
24
 
25
+ # Enrich run with full notifications since the notification params are subtracted from the run body.
26
+ notifications = "notifications"
27
+
25
28
  # Performs run enrichment, including the run's artifacts. Only available for the `get` run API.
26
29
  full = "full"
mlrun/common/helpers.py CHANGED
@@ -11,7 +11,6 @@
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
14
 
16
15
 
17
16
  def parse_versioned_object_uri(
@@ -108,6 +108,7 @@ from .feature_store import (
108
108
  FeatureVectorsTagsOutput,
109
109
  )
110
110
  from .frontend_spec import (
111
+ ArtifactLimits,
111
112
  AuthenticationFeatureFlag,
112
113
  FeatureFlags,
113
114
  FrontendSpec,
@@ -151,7 +152,6 @@ from .model_monitoring import (
151
152
  ModelMonitoringMode,
152
153
  ModelMonitoringStoreKinds,
153
154
  MonitoringFunctionNames,
154
- PrometheusEndpoints,
155
155
  TSDBTarget,
156
156
  V3IOTSDBTables,
157
157
  )
@@ -170,10 +170,12 @@ from .project import (
170
170
  Project,
171
171
  ProjectDesiredState,
172
172
  ProjectMetadata,
173
+ ProjectOut,
173
174
  ProjectOutput,
174
175
  ProjectOwner,
175
176
  ProjectsOutput,
176
177
  ProjectSpec,
178
+ ProjectSpecOut,
177
179
  ProjectState,
178
180
  ProjectStatus,
179
181
  ProjectSummariesOutput,
@@ -23,6 +23,7 @@ from mlrun.common.types import StrEnum
23
23
 
24
24
  class EventEntityKind(StrEnum):
25
25
  MODEL_ENDPOINT_RESULT = "model-endpoint-result"
26
+ MODEL_MONITORING_APPLICATION = "model-monitoring-application"
26
27
  JOB = "job"
27
28
 
28
29
 
@@ -33,16 +34,17 @@ class EventEntities(pydantic.BaseModel):
33
34
 
34
35
 
35
36
  class EventKind(StrEnum):
36
- DATA_DRIFT_DETECTED = "data_drift_detected"
37
- DATA_DRIFT_SUSPECTED = "data_drift_suspected"
38
- CONCEPT_DRIFT_DETECTED = "concept_drift_detected"
39
- CONCEPT_DRIFT_SUSPECTED = "concept_drift_suspected"
40
- MODEL_PERFORMANCE_DETECTED = "model_performance_detected"
41
- MODEL_PERFORMANCE_SUSPECTED = "model_performance_suspected"
42
- SYSTEM_PERFORMANCE_DETECTED = "system_performance_detected"
43
- SYSTEM_PERFORMANCE_SUSPECTED = "system_performance_suspected"
44
- MM_APP_ANOMALY_DETECTED = "mm_app_anomaly_detected"
45
- MM_APP_ANOMALY_SUSPECTED = "mm_app_anomaly_suspected"
37
+ DATA_DRIFT_DETECTED = "data-drift-detected"
38
+ DATA_DRIFT_SUSPECTED = "data-drift-suspected"
39
+ CONCEPT_DRIFT_DETECTED = "concept-drift-detected"
40
+ CONCEPT_DRIFT_SUSPECTED = "concept-drift-suspected"
41
+ MODEL_PERFORMANCE_DETECTED = "model-performance-detected"
42
+ MODEL_PERFORMANCE_SUSPECTED = "model-performance-suspected"
43
+ SYSTEM_PERFORMANCE_DETECTED = "system-performance-detected"
44
+ SYSTEM_PERFORMANCE_SUSPECTED = "system-performance-suspected"
45
+ MM_APP_ANOMALY_DETECTED = "mm-app-anomaly-detected"
46
+ MM_APP_ANOMALY_SUSPECTED = "mm-app-anomaly-suspected"
47
+ MM_APP_FAILED = "mm-app-failed"
46
48
  FAILED = "failed"
47
49
 
48
50
 
@@ -57,6 +59,7 @@ _event_kind_entity_map = {
57
59
  EventKind.SYSTEM_PERFORMANCE_SUSPECTED: [EventEntityKind.MODEL_ENDPOINT_RESULT],
58
60
  EventKind.MM_APP_ANOMALY_DETECTED: [EventEntityKind.MODEL_ENDPOINT_RESULT],
59
61
  EventKind.MM_APP_ANOMALY_SUSPECTED: [EventEntityKind.MODEL_ENDPOINT_RESULT],
62
+ EventKind.MM_APP_FAILED: [EventEntityKind.MODEL_MONITORING_APPLICATION],
60
63
  EventKind.FAILED: [EventEntityKind.JOB],
61
64
  }
62
65
 
@@ -149,7 +152,7 @@ class AlertConfig(pydantic.BaseModel):
149
152
  entities: EventEntities
150
153
  trigger: AlertTrigger
151
154
  criteria: Optional[AlertCriteria]
152
- reset_policy: ResetPolicy = ResetPolicy.MANUAL
155
+ reset_policy: ResetPolicy = ResetPolicy.AUTO
153
156
  notifications: pydantic.conlist(AlertNotification, min_items=1)
154
157
  state: AlertActiveState = AlertActiveState.INACTIVE
155
158
  count: Optional[int] = 0
@@ -185,7 +188,7 @@ class AlertTemplate(
185
188
  severity: AlertSeverity
186
189
  trigger: AlertTrigger
187
190
  criteria: Optional[AlertCriteria]
188
- reset_policy: ResetPolicy = ResetPolicy.MANUAL
191
+ reset_policy: ResetPolicy = ResetPolicy.AUTO
189
192
 
190
193
  # This is slightly different than __eq__ as it doesn't compare everything
191
194
  def templates_differ(self, other):
@@ -77,7 +77,7 @@ class APIGatewaySpec(_APIGatewayBaseModel):
77
77
  name: str
78
78
  description: Optional[str]
79
79
  path: Optional[str] = "/"
80
- authenticationMode: Optional[APIGatewayAuthenticationMode] = (
80
+ authenticationMode: Optional[APIGatewayAuthenticationMode] = ( # noqa: N815 - for compatibility with Nuclio https://github.com/nuclio/nuclio/blob/672b8e36f9edd6e42b4685ec1d27cabae3c5f045/pkg/platform/types.go#L476
81
81
  APIGatewayAuthenticationMode.none
82
82
  )
83
83
  upstreams: list[APIGatewayUpstream]
@@ -103,11 +103,11 @@ class APIGateway(_APIGatewayBaseModel):
103
103
  ]
104
104
 
105
105
  def get_invoke_url(self):
106
- return (
107
- self.spec.host + self.spec.path
108
- if self.spec.path and self.spec.host
109
- else self.spec.host
110
- )
106
+ if self.spec.host and self.spec.path:
107
+ return f"{self.spec.host.rstrip('/')}/{self.spec.path.lstrip('/')}".rstrip(
108
+ "/"
109
+ )
110
+ return self.spec.host.rstrip("/")
111
111
 
112
112
  def enrich_mlrun_names(self):
113
113
  self._enrich_api_gateway_mlrun_name()
@@ -63,6 +63,7 @@ class AuthorizationResourceTypes(mlrun.common.types.StrEnum):
63
63
  event = "event"
64
64
  datastore_profile = "datastore-profile"
65
65
  api_gateway = "api-gateway"
66
+ project_summaries = "project-summaries"
66
67
 
67
68
  def to_resource_string(
68
69
  self,
@@ -72,6 +73,7 @@ class AuthorizationResourceTypes(mlrun.common.types.StrEnum):
72
73
  return {
73
74
  # project is the resource itself, so no need for both resource_name and project_name
74
75
  AuthorizationResourceTypes.project: "/projects/{project_name}",
76
+ AuthorizationResourceTypes.project_summaries: "/projects/{project_name}/project-summaries/{resource_name}",
75
77
  AuthorizationResourceTypes.function: "/projects/{project_name}/functions/{resource_name}",
76
78
  AuthorizationResourceTypes.artifact: "/projects/{project_name}/artifacts/{resource_name}",
77
79
  AuthorizationResourceTypes.project_background_task: (
@@ -139,6 +141,9 @@ class AuthInfo(pydantic.BaseModel):
139
141
  member_ids.extend(self.user_group_ids)
140
142
  return member_ids
141
143
 
144
+ def get_session(self) -> str:
145
+ return self.data_session or self.session
146
+
142
147
 
143
148
  class Credentials(pydantic.BaseModel):
144
149
  access_key: typing.Optional[str]
@@ -57,7 +57,6 @@ class ClientSpec(pydantic.BaseModel):
57
57
  redis_url: typing.Optional[str]
58
58
  redis_type: typing.Optional[str]
59
59
  sql_url: typing.Optional[str]
60
- model_endpoint_monitoring_store_type: typing.Optional[str]
61
60
  model_endpoint_monitoring_endpoint_store_connection: typing.Optional[str]
62
61
  model_monitoring_tsdb_connection: typing.Optional[str]
63
62
  ce: typing.Optional[dict]
@@ -11,16 +11,16 @@
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
- #
14
+
15
15
  import typing
16
16
 
17
17
  import pydantic
18
18
 
19
19
 
20
20
  class ImageBuilder(pydantic.BaseModel):
21
- functionSourceCode: typing.Optional[str] = None
22
- codeEntryType: typing.Optional[str] = None
23
- codeEntryAttributes: typing.Optional[str] = None
21
+ functionSourceCode: typing.Optional[str] = None # noqa: N815
22
+ codeEntryType: typing.Optional[str] = None # noqa: N815
23
+ codeEntryAttributes: typing.Optional[str] = None # noqa: N815
24
24
  source: typing.Optional[str] = None
25
25
  code_origin: typing.Optional[str] = None
26
26
  origin_filename: typing.Optional[str] = None
@@ -38,3 +38,6 @@ class ImageBuilder(pydantic.BaseModel):
38
38
  build_pod: typing.Optional[str] = None
39
39
  requirements: typing.Optional[list] = None
40
40
  source_code_target_dir: typing.Optional[str] = None
41
+
42
+ class Config:
43
+ extra = pydantic.Extra.allow
@@ -50,6 +50,12 @@ class FeatureFlags(pydantic.BaseModel):
50
50
  preemption_nodes: PreemptionNodesFeatureFlag
51
51
 
52
52
 
53
+ class ArtifactLimits(pydantic.BaseModel):
54
+ max_chunk_size: int
55
+ max_preview_size: int
56
+ max_download_size: int
57
+
58
+
53
59
  class FrontendSpec(pydantic.BaseModel):
54
60
  jobs_dashboard_url: typing.Optional[str]
55
61
  model_monitoring_dashboard_url: typing.Optional[str]
@@ -71,3 +77,4 @@ class FrontendSpec(pydantic.BaseModel):
71
77
  allowed_artifact_path_prefixes_list: list[str]
72
78
  ce: typing.Optional[dict]
73
79
  internal_labels: list[str] = []
80
+ artifact_limits: ArtifactLimits
@@ -119,6 +119,13 @@ class FunctionSpec(pydantic.BaseModel):
119
119
  service_account: typing.Optional[ServiceAccount]
120
120
  state_thresholds: typing.Optional[StateThresholds]
121
121
 
122
+ class Config:
123
+ extra = pydantic.Extra.allow
124
+
122
125
 
123
126
  class Function(pydantic.BaseModel):
124
127
  spec: typing.Optional[FunctionSpec]
128
+ application: typing.Optional[dict[str, typing.Any]]
129
+
130
+ class Config:
131
+ extra = pydantic.Extra.allow
@@ -13,6 +13,7 @@
13
13
  # limitations under the License.
14
14
 
15
15
  from .constants import (
16
+ V3IO_MODEL_MONITORING_DB,
16
17
  ControllerPolicy,
17
18
  DriftStatus,
18
19
  EndpointType,
@@ -24,16 +25,17 @@ from .constants import (
24
25
  FileTargetKind,
25
26
  FunctionURI,
26
27
  MetricData,
28
+ ModelEndpointMonitoringMetricType,
27
29
  ModelEndpointTarget,
30
+ ModelEndpointTargetSchemas,
28
31
  ModelMonitoringMode,
29
32
  ModelMonitoringStoreKinds,
30
33
  MonitoringFunctionNames,
31
34
  PredictionsQueryConstants,
32
35
  ProjectSecretKeys,
33
- PrometheusEndpoints,
34
- PrometheusMetric,
35
36
  ResultData,
36
37
  ResultKindApp,
38
+ ResultStatusApp,
37
39
  SchedulingKeys,
38
40
  SpecialApps,
39
41
  TDEngineSuperTables,
@@ -60,7 +62,6 @@ from .model_endpoints import (
60
62
  ModelEndpointMetadata,
61
63
  ModelEndpointMonitoringMetric,
62
64
  ModelEndpointMonitoringMetricNoData,
63
- ModelEndpointMonitoringMetricType,
64
65
  ModelEndpointMonitoringMetricValues,
65
66
  ModelEndpointMonitoringResultValues,
66
67
  ModelEndpointSpec,
@@ -13,10 +13,12 @@
13
13
  # limitations under the License.
14
14
 
15
15
  import hashlib
16
- from dataclasses import dataclass
16
+ import re
17
+ from dataclasses import dataclass, field
17
18
  from enum import Enum, IntEnum
18
19
  from typing import Optional
19
20
 
21
+ import mlrun.common.constants
20
22
  import mlrun.common.helpers
21
23
  from mlrun.common.types import StrEnum
22
24
 
@@ -52,9 +54,11 @@ class EventFieldType:
52
54
  PREDICTIONS = "predictions"
53
55
  NAMED_PREDICTIONS = "named_predictions"
54
56
  ERROR_COUNT = "error_count"
57
+ MODEL_ERROR = "model_error"
55
58
  ENTITIES = "entities"
56
59
  FIRST_REQUEST = "first_request"
57
60
  LAST_REQUEST = "last_request"
61
+ LAST_REQUEST_TIMESTAMP = "last_request_timestamp"
58
62
  METRIC = "metric"
59
63
  METRICS = "metrics"
60
64
  BATCH_INTERVALS_DICT = "batch_intervals_dict"
@@ -101,15 +105,8 @@ class ApplicationEvent:
101
105
  APPLICATION_NAME = "application_name"
102
106
  START_INFER_TIME = "start_infer_time"
103
107
  END_INFER_TIME = "end_infer_time"
104
- LAST_REQUEST = "last_request"
105
108
  ENDPOINT_ID = "endpoint_id"
106
109
  OUTPUT_STREAM_URI = "output_stream_uri"
107
- MLRUN_CONTEXT = "mlrun_context"
108
-
109
- # Deprecated fields - TODO : delete in 1.9.0 (V1 app deprecation)
110
- SAMPLE_PARQUET_PATH = "sample_parquet_path"
111
- CURRENT_STATS = "current_stats"
112
- FEATURE_STATS = "feature_stats"
113
110
 
114
111
 
115
112
  class WriterEvent(MonitoringStrEnum):
@@ -169,7 +166,6 @@ class StreamKind(MonitoringStrEnum):
169
166
  class TSDBTarget(MonitoringStrEnum):
170
167
  V3IO_TSDB = "v3io-tsdb"
171
168
  TDEngine = "tdengine"
172
- PROMETHEUS = "prometheus"
173
169
 
174
170
 
175
171
  class ProjectSecretKeys:
@@ -187,6 +183,12 @@ class ProjectSecretKeys:
187
183
  ]
188
184
 
189
185
 
186
+ class ModelEndpointTargetSchemas(MonitoringStrEnum):
187
+ V3IO = "v3io"
188
+ MYSQL = "mysql"
189
+ SQLITE = "sqlite"
190
+
191
+
190
192
  class ModelMonitoringStoreKinds:
191
193
  ENDPOINTS = "endpoints"
192
194
  EVENTS = "events"
@@ -211,6 +213,7 @@ class FileTargetKind:
211
213
  APP_METRICS = "app_metrics"
212
214
  MONITORING_SCHEDULES = "monitoring_schedules"
213
215
  MONITORING_APPLICATION = "monitoring_application"
216
+ ERRORS = "errors"
214
217
 
215
218
 
216
219
  class ModelMonitoringMode(str, Enum):
@@ -224,21 +227,6 @@ class EndpointType(IntEnum):
224
227
  LEAF_EP = 3 # end point that is a child of a router
225
228
 
226
229
 
227
- class PrometheusMetric:
228
- PREDICTIONS_TOTAL = "predictions_total"
229
- MODEL_LATENCY_SECONDS = "model_latency_seconds"
230
- INCOME_FEATURES = "income_features"
231
- ERRORS_TOTAL = "errors_total"
232
- DRIFT_METRICS = "drift_metrics"
233
- DRIFT_STATUS = "drift_status"
234
-
235
-
236
- class PrometheusEndpoints(MonitoringStrEnum):
237
- MODEL_MONITORING_METRICS = "/model-monitoring-metrics"
238
- MONITORING_BATCH_METRICS = "/monitoring-batch-metrics"
239
- MONITORING_DRIFT_STATUS = "/monitoring-drift-status"
240
-
241
-
242
230
  class MonitoringFunctionNames(MonitoringStrEnum):
243
231
  STREAM = "model-monitoring-stream"
244
232
  APPLICATION_CONTROLLER = "model-monitoring-controller"
@@ -249,6 +237,7 @@ class V3IOTSDBTables(MonitoringStrEnum):
249
237
  APP_RESULTS = "app-results"
250
238
  METRICS = "metrics"
251
239
  EVENTS = "events"
240
+ ERRORS = "errors"
252
241
 
253
242
 
254
243
  class TDEngineSuperTables(MonitoringStrEnum):
@@ -300,7 +289,7 @@ class EndpointUID:
300
289
  function_hash_key: str
301
290
  model: str
302
291
  model_version: str
303
- uid: Optional[str] = None
292
+ uid: str = field(init=False)
304
293
 
305
294
  def __post_init__(self):
306
295
  function_ref = (
@@ -348,7 +337,7 @@ class ResultStatusApp(IntEnum):
348
337
 
349
338
 
350
339
  class ModelMonitoringAppLabel:
351
- KEY = "mlrun__type"
340
+ KEY = mlrun.common.constants.MLRunInternalLabels.mlrun_type
352
341
  VAL = "mlrun__model-monitoring-application"
353
342
 
354
343
  def __str__(self) -> str:
@@ -371,3 +360,29 @@ class PredictionsQueryConstants:
371
360
 
372
361
  class SpecialApps:
373
362
  MLRUN_INFRA = "mlrun-infra"
363
+
364
+
365
+ _RESERVED_FUNCTION_NAMES = MonitoringFunctionNames.list() + [SpecialApps.MLRUN_INFRA]
366
+
367
+
368
+ V3IO_MODEL_MONITORING_DB = "v3io"
369
+
370
+
371
+ class ModelEndpointMonitoringMetricType(StrEnum):
372
+ RESULT = "result"
373
+ METRIC = "metric"
374
+
375
+
376
+ _FQN_PART_PATTERN = r"[a-zA-Z0-9_-]+"
377
+ FQN_PATTERN = (
378
+ rf"^(?P<project>{_FQN_PART_PATTERN})\."
379
+ rf"(?P<app>{_FQN_PART_PATTERN})\."
380
+ rf"(?P<type>{ModelEndpointMonitoringMetricType.RESULT}|{ModelEndpointMonitoringMetricType.METRIC})\."
381
+ rf"(?P<name>{_FQN_PART_PATTERN})$"
382
+ )
383
+ FQN_REGEX = re.compile(FQN_PATTERN)
384
+
385
+ # refer to `mlrun.utils.regex.project_name`
386
+ PROJECT_PATTERN = r"^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?$"
387
+
388
+ MODEL_ENDPOINT_ID_PATTERN = r"^[a-zA-Z0-9_-]+$"