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.
- mlrun/__main__.py +4 -2
- mlrun/alerts/alert.py +75 -8
- mlrun/artifacts/base.py +1 -0
- mlrun/artifacts/manager.py +9 -2
- mlrun/common/constants.py +4 -1
- mlrun/common/db/sql_session.py +3 -2
- mlrun/common/formatters/__init__.py +1 -0
- mlrun/common/formatters/artifact.py +1 -0
- mlrun/{model_monitoring/application.py → common/formatters/feature_set.py} +20 -6
- mlrun/common/formatters/run.py +3 -0
- mlrun/common/helpers.py +0 -1
- mlrun/common/schemas/__init__.py +3 -1
- mlrun/common/schemas/alert.py +15 -12
- mlrun/common/schemas/api_gateway.py +6 -6
- mlrun/common/schemas/auth.py +5 -0
- mlrun/common/schemas/client_spec.py +0 -1
- mlrun/common/schemas/common.py +7 -4
- mlrun/common/schemas/frontend_spec.py +7 -0
- mlrun/common/schemas/function.py +7 -0
- mlrun/common/schemas/model_monitoring/__init__.py +4 -3
- mlrun/common/schemas/model_monitoring/constants.py +41 -26
- mlrun/common/schemas/model_monitoring/model_endpoints.py +23 -47
- mlrun/common/schemas/notification.py +69 -12
- mlrun/common/schemas/project.py +45 -12
- mlrun/common/schemas/workflow.py +10 -2
- mlrun/common/types.py +1 -0
- mlrun/config.py +91 -35
- mlrun/data_types/data_types.py +6 -1
- mlrun/data_types/spark.py +2 -2
- mlrun/data_types/to_pandas.py +57 -25
- mlrun/datastore/__init__.py +1 -0
- mlrun/datastore/alibaba_oss.py +3 -2
- mlrun/datastore/azure_blob.py +125 -37
- mlrun/datastore/base.py +42 -21
- mlrun/datastore/datastore.py +4 -2
- mlrun/datastore/datastore_profile.py +1 -1
- mlrun/datastore/dbfs_store.py +3 -7
- mlrun/datastore/filestore.py +1 -3
- mlrun/datastore/google_cloud_storage.py +85 -29
- mlrun/datastore/inmem.py +4 -1
- mlrun/datastore/redis.py +1 -0
- mlrun/datastore/s3.py +25 -12
- mlrun/datastore/sources.py +76 -4
- mlrun/datastore/spark_utils.py +30 -0
- mlrun/datastore/storeytargets.py +151 -0
- mlrun/datastore/targets.py +102 -131
- mlrun/datastore/v3io.py +1 -0
- mlrun/db/base.py +15 -6
- mlrun/db/httpdb.py +57 -28
- mlrun/db/nopdb.py +29 -5
- mlrun/errors.py +20 -3
- mlrun/execution.py +46 -5
- mlrun/feature_store/api.py +25 -1
- mlrun/feature_store/common.py +6 -11
- mlrun/feature_store/feature_vector.py +3 -1
- mlrun/feature_store/retrieval/job.py +4 -1
- mlrun/feature_store/retrieval/spark_merger.py +10 -39
- mlrun/feature_store/steps.py +8 -0
- mlrun/frameworks/_common/plan.py +3 -3
- mlrun/frameworks/_ml_common/plan.py +1 -1
- mlrun/frameworks/parallel_coordinates.py +2 -3
- mlrun/frameworks/sklearn/mlrun_interface.py +13 -3
- mlrun/k8s_utils.py +48 -2
- mlrun/launcher/client.py +6 -6
- mlrun/launcher/local.py +2 -2
- mlrun/model.py +215 -34
- mlrun/model_monitoring/api.py +38 -24
- mlrun/model_monitoring/applications/__init__.py +1 -2
- mlrun/model_monitoring/applications/_application_steps.py +60 -29
- mlrun/model_monitoring/applications/base.py +2 -174
- mlrun/model_monitoring/applications/context.py +197 -70
- mlrun/model_monitoring/applications/evidently_base.py +11 -85
- mlrun/model_monitoring/applications/histogram_data_drift.py +21 -16
- mlrun/model_monitoring/applications/results.py +4 -4
- mlrun/model_monitoring/controller.py +110 -282
- mlrun/model_monitoring/db/stores/__init__.py +8 -3
- mlrun/model_monitoring/db/stores/base/store.py +3 -0
- mlrun/model_monitoring/db/stores/sqldb/models/base.py +9 -7
- mlrun/model_monitoring/db/stores/sqldb/models/mysql.py +18 -3
- mlrun/model_monitoring/db/stores/sqldb/sql_store.py +43 -23
- mlrun/model_monitoring/db/stores/v3io_kv/kv_store.py +48 -35
- mlrun/model_monitoring/db/tsdb/__init__.py +7 -2
- mlrun/model_monitoring/db/tsdb/base.py +147 -15
- mlrun/model_monitoring/db/tsdb/tdengine/schemas.py +94 -55
- mlrun/model_monitoring/db/tsdb/tdengine/stream_graph_steps.py +0 -3
- mlrun/model_monitoring/db/tsdb/tdengine/tdengine_connector.py +144 -38
- mlrun/model_monitoring/db/tsdb/v3io/stream_graph_steps.py +44 -3
- mlrun/model_monitoring/db/tsdb/v3io/v3io_connector.py +246 -57
- mlrun/model_monitoring/helpers.py +70 -50
- mlrun/model_monitoring/stream_processing.py +96 -195
- mlrun/model_monitoring/writer.py +13 -5
- mlrun/package/packagers/default_packager.py +2 -2
- mlrun/projects/operations.py +16 -8
- mlrun/projects/pipelines.py +126 -115
- mlrun/projects/project.py +286 -129
- mlrun/render.py +3 -3
- mlrun/run.py +38 -19
- mlrun/runtimes/__init__.py +19 -8
- mlrun/runtimes/base.py +4 -1
- mlrun/runtimes/daskjob.py +1 -1
- mlrun/runtimes/funcdoc.py +1 -1
- mlrun/runtimes/kubejob.py +6 -6
- mlrun/runtimes/local.py +12 -5
- mlrun/runtimes/nuclio/api_gateway.py +68 -8
- mlrun/runtimes/nuclio/application/application.py +307 -70
- mlrun/runtimes/nuclio/function.py +63 -14
- mlrun/runtimes/nuclio/serving.py +10 -10
- mlrun/runtimes/pod.py +25 -19
- mlrun/runtimes/remotesparkjob.py +2 -5
- mlrun/runtimes/sparkjob/spark3job.py +16 -17
- mlrun/runtimes/utils.py +34 -0
- mlrun/serving/routers.py +2 -5
- mlrun/serving/server.py +37 -19
- mlrun/serving/states.py +30 -3
- mlrun/serving/v2_serving.py +44 -35
- mlrun/track/trackers/mlflow_tracker.py +5 -0
- mlrun/utils/async_http.py +1 -1
- mlrun/utils/db.py +18 -0
- mlrun/utils/helpers.py +150 -36
- mlrun/utils/http.py +1 -1
- mlrun/utils/notifications/notification/__init__.py +0 -1
- mlrun/utils/notifications/notification/webhook.py +8 -1
- mlrun/utils/notifications/notification_pusher.py +1 -1
- mlrun/utils/v3io_clients.py +2 -2
- mlrun/utils/version/version.json +2 -2
- {mlrun-1.7.0rc28.dist-info → mlrun-1.7.0rc55.dist-info}/METADATA +153 -66
- {mlrun-1.7.0rc28.dist-info → mlrun-1.7.0rc55.dist-info}/RECORD +131 -134
- {mlrun-1.7.0rc28.dist-info → mlrun-1.7.0rc55.dist-info}/WHEEL +1 -1
- mlrun/feature_store/retrieval/conversion.py +0 -271
- mlrun/model_monitoring/controller_handler.py +0 -37
- mlrun/model_monitoring/evidently_application.py +0 -20
- mlrun/model_monitoring/prometheus.py +0 -216
- {mlrun-1.7.0rc28.dist-info → mlrun-1.7.0rc55.dist-info}/LICENSE +0 -0
- {mlrun-1.7.0rc28.dist-info → mlrun-1.7.0rc55.dist-info}/entry_points.txt +0 -0
- {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
|
-
|
|
737
|
+
logger.warning(
|
|
738
|
+
"Project parameter was not specified. Defaulting to 'default' project"
|
|
739
|
+
)
|
|
738
740
|
if kind.startswith("po"):
|
|
739
|
-
|
|
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.
|
|
77
|
-
raise mlrun.errors.
|
|
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
|
-
#
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
self.
|
|
180
|
-
self.
|
|
181
|
-
self.
|
|
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
mlrun/artifacts/manager.py
CHANGED
|
@@ -72,7 +72,12 @@ class ArtifactProducer:
|
|
|
72
72
|
self.inputs = {}
|
|
73
73
|
|
|
74
74
|
def get_meta(self) -> dict:
|
|
75
|
-
return {
|
|
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
|
|
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"
|
mlrun/common/db/sql_session.py
CHANGED
|
@@ -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
|
|
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
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright
|
|
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
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
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]
|
mlrun/common/formatters/run.py
CHANGED
|
@@ -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
mlrun/common/schemas/__init__.py
CHANGED
|
@@ -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,
|
mlrun/common/schemas/alert.py
CHANGED
|
@@ -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 = "
|
|
37
|
-
DATA_DRIFT_SUSPECTED = "
|
|
38
|
-
CONCEPT_DRIFT_DETECTED = "
|
|
39
|
-
CONCEPT_DRIFT_SUSPECTED = "
|
|
40
|
-
MODEL_PERFORMANCE_DETECTED = "
|
|
41
|
-
MODEL_PERFORMANCE_SUSPECTED = "
|
|
42
|
-
SYSTEM_PERFORMANCE_DETECTED = "
|
|
43
|
-
SYSTEM_PERFORMANCE_SUSPECTED = "
|
|
44
|
-
MM_APP_ANOMALY_DETECTED = "
|
|
45
|
-
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.
|
|
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.
|
|
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
|
-
|
|
107
|
-
self.spec.host
|
|
108
|
-
|
|
109
|
-
|
|
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()
|
mlrun/common/schemas/auth.py
CHANGED
|
@@ -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]
|
mlrun/common/schemas/common.py
CHANGED
|
@@ -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
|
mlrun/common/schemas/function.py
CHANGED
|
@@ -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
|
-
|
|
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:
|
|
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 =
|
|
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_-]+$"
|