mlrun 1.8.0rc1__py3-none-any.whl → 1.8.0rc2__py3-none-any.whl

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

Potentially problematic release.


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

Files changed (76) hide show
  1. mlrun/__init__.py +5 -7
  2. mlrun/__main__.py +1 -1
  3. mlrun/common/formatters/project.py +9 -0
  4. mlrun/common/schemas/__init__.py +3 -0
  5. mlrun/common/schemas/alert.py +31 -18
  6. mlrun/common/schemas/api_gateway.py +3 -3
  7. mlrun/common/schemas/artifact.py +7 -7
  8. mlrun/common/schemas/auth.py +6 -4
  9. mlrun/common/schemas/background_task.py +7 -7
  10. mlrun/common/schemas/client_spec.py +2 -2
  11. mlrun/common/schemas/clusterization_spec.py +2 -2
  12. mlrun/common/schemas/common.py +5 -5
  13. mlrun/common/schemas/datastore_profile.py +1 -1
  14. mlrun/common/schemas/feature_store.py +9 -9
  15. mlrun/common/schemas/frontend_spec.py +4 -4
  16. mlrun/common/schemas/function.py +10 -10
  17. mlrun/common/schemas/hub.py +1 -1
  18. mlrun/common/schemas/k8s.py +3 -3
  19. mlrun/common/schemas/memory_reports.py +3 -3
  20. mlrun/common/schemas/model_monitoring/grafana.py +1 -1
  21. mlrun/common/schemas/model_monitoring/model_endpoint_v2.py +1 -1
  22. mlrun/common/schemas/model_monitoring/model_endpoints.py +1 -1
  23. mlrun/common/schemas/notification.py +18 -3
  24. mlrun/common/schemas/object.py +1 -1
  25. mlrun/common/schemas/pagination.py +4 -4
  26. mlrun/common/schemas/partition.py +16 -1
  27. mlrun/common/schemas/pipeline.py +2 -2
  28. mlrun/common/schemas/project.py +22 -17
  29. mlrun/common/schemas/runs.py +2 -2
  30. mlrun/common/schemas/runtime_resource.py +5 -5
  31. mlrun/common/schemas/schedule.py +1 -1
  32. mlrun/common/schemas/secret.py +1 -1
  33. mlrun/common/schemas/tag.py +3 -3
  34. mlrun/common/schemas/workflow.py +5 -5
  35. mlrun/config.py +22 -0
  36. mlrun/datastore/datastore_profile.py +19 -19
  37. mlrun/db/base.py +48 -6
  38. mlrun/db/httpdb.py +221 -9
  39. mlrun/db/nopdb.py +34 -5
  40. mlrun/model.py +2 -2
  41. mlrun/model_monitoring/applications/results.py +2 -2
  42. mlrun/model_monitoring/db/tsdb/base.py +2 -2
  43. mlrun/model_monitoring/db/tsdb/tdengine/schemas.py +37 -13
  44. mlrun/model_monitoring/db/tsdb/tdengine/tdengine_connector.py +32 -40
  45. mlrun/model_monitoring/helpers.py +4 -10
  46. mlrun/model_monitoring/stream_processing.py +14 -11
  47. mlrun/platforms/__init__.py +0 -13
  48. mlrun/projects/__init__.py +6 -1
  49. mlrun/projects/pipelines.py +184 -55
  50. mlrun/projects/project.py +95 -28
  51. mlrun/run.py +4 -1
  52. mlrun/runtimes/base.py +2 -1
  53. mlrun/runtimes/mounts.py +572 -0
  54. mlrun/runtimes/nuclio/function.py +1 -2
  55. mlrun/runtimes/pod.py +82 -18
  56. mlrun/runtimes/remotesparkjob.py +1 -1
  57. mlrun/runtimes/sparkjob/spark3job.py +1 -1
  58. mlrun/utils/helpers.py +12 -2
  59. mlrun/utils/logger.py +2 -2
  60. mlrun/utils/notifications/notification/__init__.py +22 -19
  61. mlrun/utils/notifications/notification/base.py +12 -12
  62. mlrun/utils/notifications/notification/console.py +6 -6
  63. mlrun/utils/notifications/notification/git.py +6 -6
  64. mlrun/utils/notifications/notification/ipython.py +6 -6
  65. mlrun/utils/notifications/notification/mail.py +149 -0
  66. mlrun/utils/notifications/notification/slack.py +6 -6
  67. mlrun/utils/notifications/notification/webhook.py +6 -6
  68. mlrun/utils/notifications/notification_pusher.py +20 -12
  69. mlrun/utils/regex.py +2 -0
  70. mlrun/utils/version/version.json +2 -2
  71. {mlrun-1.8.0rc1.dist-info → mlrun-1.8.0rc2.dist-info}/METADATA +190 -186
  72. {mlrun-1.8.0rc1.dist-info → mlrun-1.8.0rc2.dist-info}/RECORD +76 -74
  73. {mlrun-1.8.0rc1.dist-info → mlrun-1.8.0rc2.dist-info}/WHEEL +1 -1
  74. {mlrun-1.8.0rc1.dist-info → mlrun-1.8.0rc2.dist-info}/LICENSE +0 -0
  75. {mlrun-1.8.0rc1.dist-info → mlrun-1.8.0rc2.dist-info}/entry_points.txt +0 -0
  76. {mlrun-1.8.0rc1.dist-info → mlrun-1.8.0rc2.dist-info}/top_level.txt +0 -0
mlrun/db/base.py CHANGED
@@ -14,7 +14,7 @@
14
14
 
15
15
  import datetime
16
16
  from abc import ABC, abstractmethod
17
- from typing import Optional, Union
17
+ from typing import Literal, Optional, Union
18
18
 
19
19
  from deprecated import deprecated
20
20
 
@@ -23,6 +23,7 @@ import mlrun.common
23
23
  import mlrun.common.formatters
24
24
  import mlrun.common.runtimes.constants
25
25
  import mlrun.common.schemas
26
+ import mlrun.common.schemas.model_monitoring.model_endpoints as mm_endpoints
26
27
  import mlrun.model_monitoring
27
28
 
28
29
 
@@ -213,11 +214,13 @@ class RunDBInterface(ABC):
213
214
  def list_functions(
214
215
  self,
215
216
  name: Optional[str] = None,
216
- project: Optional[str] = "",
217
- tag: Optional[str] = "",
217
+ project: Optional[str] = None,
218
+ tag: Optional[str] = None,
219
+ kind: Optional[str] = None,
218
220
  labels: Optional[Union[str, dict[str, Optional[str]], list[str]]] = None,
219
- since=None,
220
- until=None,
221
+ format_: mlrun.common.formatters.FunctionFormat = mlrun.common.formatters.FunctionFormat.full,
222
+ since: Optional[datetime.datetime] = None,
223
+ until: Optional[datetime.datetime] = None,
221
224
  ):
222
225
  pass
223
226
 
@@ -306,6 +309,14 @@ class RunDBInterface(ABC):
306
309
  kind="artifact", identifiers=artifact_identifiers
307
310
  )
308
311
 
312
+ def get_model_endpoint_monitoring_metrics(
313
+ self,
314
+ project: str,
315
+ endpoint_id: str,
316
+ type: Literal["results", "metrics", "all"] = "all",
317
+ ) -> list[mm_endpoints.ModelEndpointMonitoringMetric]:
318
+ pass
319
+
309
320
  @abstractmethod
310
321
  def delete_project(
311
322
  self,
@@ -666,7 +677,9 @@ class RunDBInterface(ABC):
666
677
  start: str = "now-1h",
667
678
  end: str = "now",
668
679
  metrics: Optional[list[str]] = None,
669
- ):
680
+ top_level: bool = False,
681
+ uids: Optional[list[str]] = None,
682
+ ) -> list[mlrun.model_monitoring.model_endpoint.ModelEndpoint]:
670
683
  pass
671
684
 
672
685
  @abstractmethod
@@ -832,6 +845,35 @@ class RunDBInterface(ABC):
832
845
  def list_alert_templates(self):
833
846
  pass
834
847
 
848
+ @abstractmethod
849
+ def list_alert_activations(
850
+ self,
851
+ project: Optional[str] = None,
852
+ name: Optional[str] = None,
853
+ since: Optional[datetime.datetime] = None,
854
+ until: Optional[datetime.datetime] = None,
855
+ entity: Optional[str] = None,
856
+ severity: Optional[
857
+ list[Union[mlrun.common.schemas.alert.AlertSeverity, str]]
858
+ ] = None,
859
+ entity_kind: Optional[
860
+ Union[mlrun.common.schemas.alert.EventEntityKind, str]
861
+ ] = None,
862
+ event_kind: Optional[Union[mlrun.common.schemas.alert.EventKind, str]] = None,
863
+ ):
864
+ pass
865
+
866
+ @abstractmethod
867
+ def paginated_list_alert_activations(
868
+ self,
869
+ *args,
870
+ page: Optional[int] = None,
871
+ page_size: Optional[int] = None,
872
+ page_token: Optional[str] = None,
873
+ **kwargs,
874
+ ):
875
+ pass
876
+
835
877
  @abstractmethod
836
878
  def get_builder_status(
837
879
  self,
mlrun/db/httpdb.py CHANGED
@@ -22,18 +22,20 @@ import warnings
22
22
  from copy import deepcopy
23
23
  from datetime import datetime, timedelta
24
24
  from os import path, remove
25
- from typing import Optional, Union
25
+ from typing import Literal, Optional, Union
26
26
  from urllib.parse import urlparse
27
27
 
28
- import pydantic
28
+ import pydantic.v1
29
29
  import requests
30
30
  import semver
31
+ from pydantic import parse_obj_as
31
32
 
32
33
  import mlrun
33
34
  import mlrun.common.constants
34
35
  import mlrun.common.formatters
35
36
  import mlrun.common.runtimes
36
37
  import mlrun.common.schemas
38
+ import mlrun.common.schemas.model_monitoring.model_endpoints as mm_endpoints
37
39
  import mlrun.common.types
38
40
  import mlrun.model_monitoring.model_endpoint
39
41
  import mlrun.platforms
@@ -1392,6 +1394,8 @@ class HTTPRunDB(RunDBInterface):
1392
1394
  labels: Optional[Union[str, dict[str, Optional[str]], list[str]]] = None,
1393
1395
  since: Optional[datetime] = None,
1394
1396
  until: Optional[datetime] = None,
1397
+ kind: Optional[str] = None,
1398
+ format_: mlrun.common.formatters.FunctionFormat = mlrun.common.formatters.FunctionFormat.full,
1395
1399
  ):
1396
1400
  """Retrieve a list of functions, filtered by specific criteria.
1397
1401
 
@@ -1407,13 +1411,17 @@ class HTTPRunDB(RunDBInterface):
1407
1411
  the specified key-value pairs or key existence.
1408
1412
  :param since: Return functions updated after this date (as datetime object).
1409
1413
  :param until: Return functions updated before this date (as datetime object).
1414
+ :param kind: Return only functions of a specific kind.
1415
+ :param format_: The format in which to return the functions. Default is 'full'.
1410
1416
  :returns: List of function objects (as dictionary).
1411
1417
  """
1412
1418
  functions, _ = self._list_functions(
1413
1419
  name=name,
1414
1420
  project=project,
1415
1421
  tag=tag,
1422
+ kind=kind,
1416
1423
  labels=labels,
1424
+ format_=format_,
1417
1425
  since=since,
1418
1426
  until=until,
1419
1427
  return_all=True,
@@ -3359,6 +3367,37 @@ class HTTPRunDB(RunDBInterface):
3359
3367
  params=params,
3360
3368
  )
3361
3369
 
3370
+ def get_model_endpoint_monitoring_metrics(
3371
+ self,
3372
+ project: str,
3373
+ endpoint_id: str,
3374
+ type: Literal["results", "metrics", "all"] = "all",
3375
+ ) -> list[mm_endpoints.ModelEndpointMonitoringMetric]:
3376
+ """Get application metrics/results by endpoint id and project.
3377
+
3378
+ :param project: The name of the project.
3379
+ :param endpoint_id: The unique id of the model endpoint.
3380
+ :param type: The type of the metrics to return. "all" means "results" and "metrics".
3381
+
3382
+ :return: A list of the application metrics or/and results for this model endpoint.
3383
+ """
3384
+ path = f"projects/{project}/model-endpoints/{endpoint_id}/metrics"
3385
+ params = {"type": type}
3386
+ error_message = (
3387
+ f"Failed to get model endpoint monitoring metrics,"
3388
+ f" endpoint_id: {endpoint_id}, project: {project}"
3389
+ )
3390
+ response = self.api_call(
3391
+ mlrun.common.types.HTTPMethod.GET,
3392
+ path,
3393
+ error_message,
3394
+ params=params,
3395
+ )
3396
+ monitoring_metrics = response.json()
3397
+ return parse_obj_as(
3398
+ list[mm_endpoints.ModelEndpointMonitoringMetric], monitoring_metrics
3399
+ )
3400
+
3362
3401
  def create_user_secrets(
3363
3402
  self,
3364
3403
  user: str,
@@ -3536,6 +3575,8 @@ class HTTPRunDB(RunDBInterface):
3536
3575
  `m` = minutes, `h` = hours, `'d'` = days, and `'s'` = seconds), or 0 for the earliest time.
3537
3576
  :param top_level: if true will return only routers and endpoint that are NOT children of any router
3538
3577
  :param uids: if passed will return a list `ModelEndpoint` object with uid in uids
3578
+
3579
+ :returns: Returns a list of `ModelEndpoint` objects.
3539
3580
  """
3540
3581
 
3541
3582
  path = f"projects/{project}/model-endpoints"
@@ -4183,12 +4224,21 @@ class HTTPRunDB(RunDBInterface):
4183
4224
  "operations/migrations",
4184
4225
  "Failed triggering migrations",
4185
4226
  )
4186
- if response.status_code == http.HTTPStatus.ACCEPTED:
4187
- background_task = mlrun.common.schemas.BackgroundTask(**response.json())
4188
- return self._wait_for_background_task_to_reach_terminal_state(
4189
- background_task.metadata.name
4190
- )
4191
- return None
4227
+ return self._wait_for_background_task_from_response(response)
4228
+
4229
+ def refresh_smtp_configuration(
4230
+ self,
4231
+ ) -> Optional[mlrun.common.schemas.BackgroundTask]:
4232
+ """Refresh smtp configuration and wait for the task to finish
4233
+
4234
+ :returns: :py:class:`~mlrun.common.schemas.BackgroundTask`.
4235
+ """
4236
+ response = self.api_call(
4237
+ "POST",
4238
+ "operations/refresh-smtp-configuration",
4239
+ "Failed refreshing smtp configuration",
4240
+ )
4241
+ return self._wait_for_background_task_from_response(response)
4192
4242
 
4193
4243
  def set_run_notifications(
4194
4244
  self,
@@ -4625,6 +4675,112 @@ class HTTPRunDB(RunDBInterface):
4625
4675
  results.append(mlrun.common.schemas.AlertTemplate(**item))
4626
4676
  return results
4627
4677
 
4678
+ def list_alert_activations(
4679
+ self,
4680
+ project: Optional[str] = None,
4681
+ name: Optional[str] = None,
4682
+ since: Optional[datetime] = None,
4683
+ until: Optional[datetime] = None,
4684
+ entity: Optional[str] = None,
4685
+ severity: Optional[
4686
+ list[Union[mlrun.common.schemas.alert.AlertSeverity, str]]
4687
+ ] = None,
4688
+ entity_kind: Optional[
4689
+ Union[mlrun.common.schemas.alert.EventEntityKind, str]
4690
+ ] = None,
4691
+ event_kind: Optional[Union[mlrun.common.schemas.alert.EventKind, str]] = None,
4692
+ ) -> list[mlrun.common.schemas.AlertActivation]:
4693
+ """
4694
+ Retrieve a list of all alert activations.
4695
+
4696
+ :param project: The project name to filter by. If None, results are not filtered by project.
4697
+ :param name: The alert name to filter by. Supports exact matching or partial matching if prefixed with `~`.
4698
+ :param since: Filters for alert activations occurring after this timestamp.
4699
+ :param until: Filters for alert activations occurring before this timestamp.
4700
+ :param entity: The entity ID to filter by. Supports wildcard matching if prefixed with `~`.
4701
+ :param severity: A list of severity levels to filter by (e.g., ["high", "low"]).
4702
+ :param entity_kind: The kind of entity (e.g., "job", "endpoint") to filter by.
4703
+ :param event_kind: The kind of event (e.g., ""data-drift-detected"", "failed") to filter by.
4704
+
4705
+ :returns: A list of alert activations matching the provided filters.
4706
+ """
4707
+
4708
+ alert_activations, _ = self._list_alert_activations(
4709
+ project=project,
4710
+ name=name,
4711
+ since=since,
4712
+ until=until,
4713
+ entity=entity,
4714
+ severity=severity,
4715
+ entity_kind=entity_kind,
4716
+ event_kind=event_kind,
4717
+ return_all=True,
4718
+ )
4719
+ return alert_activations
4720
+
4721
+ def paginated_list_alert_activations(
4722
+ self,
4723
+ *args,
4724
+ page: Optional[int] = None,
4725
+ page_size: Optional[int] = None,
4726
+ page_token: Optional[str] = None,
4727
+ **kwargs,
4728
+ ) -> tuple[list, Optional[str]]:
4729
+ """List alerts activations with support for pagination and various filtering options.
4730
+
4731
+ This method retrieves a paginated list of alert activations based on the specified filter parameters.
4732
+ Pagination is controlled using the `page`, `page_size`, and `page_token` parameters. The method
4733
+ will return a list of alert activations that match the filtering criteria provided.
4734
+
4735
+ For detailed information about the parameters, refer to the list_alert_activations method:
4736
+ See :py:func:`~list_alert_activations` for more details.
4737
+
4738
+ Examples::
4739
+
4740
+ # Fetch first page of alert activations with page size of 5
4741
+ alert_activations, token = db.paginated_list_alert_activations(
4742
+ project="my-project", page_size=5
4743
+ )
4744
+ # Fetch next page using the pagination token from the previous response
4745
+ alert_activations, token = db.paginated_list_alert_activations(
4746
+ project="my-project", page_token=token
4747
+ )
4748
+ # Fetch alert activations for a specific page (e.g., page 3)
4749
+ alert_activations, token = db.paginated_list_alert_activations(
4750
+ project="my-project", page=3, page_size=5
4751
+ )
4752
+
4753
+ # Automatically iterate over all pages without explicitly specifying the page number
4754
+ alert_activations = []
4755
+ token = None
4756
+ while True:
4757
+ page_alert_activations, token = db.paginated_list_alert_activations(
4758
+ project="my-project", page_token=token, page_size=5
4759
+ )
4760
+ alert_activations.extend(page_alert_activations)
4761
+
4762
+ # If token is None and page_alert_activations is empty, we've reached the end (no more activations).
4763
+ # If token is None and page_alert_activations is not empty, we've fetched the last page of activations.
4764
+ if not token:
4765
+ break
4766
+ print(f"Total alert activations retrieved: {len(alert_activations)}")
4767
+
4768
+ :param page: The page number to retrieve. If not provided, the next page will be retrieved.
4769
+ :param page_size: The number of items per page to retrieve. Up to `page_size` responses are expected.
4770
+ :param page_token: A pagination token used to retrieve the next page of results. Should not be provided
4771
+ for the first request.
4772
+
4773
+ :returns: A tuple containing the list of alert activations and an optional `page_token` for pagination.
4774
+ """
4775
+ return self._list_alert_activations(
4776
+ *args,
4777
+ page=page,
4778
+ page_size=page_size,
4779
+ page_token=page_token,
4780
+ return_all=False,
4781
+ **kwargs,
4782
+ )
4783
+
4628
4784
  @staticmethod
4629
4785
  def _parse_labels(
4630
4786
  labels: Optional[Union[str, dict[str, Optional[str]], list[str]]],
@@ -4641,7 +4797,7 @@ class HTTPRunDB(RunDBInterface):
4641
4797
  """
4642
4798
  try:
4643
4799
  return mlrun.common.schemas.common.LabelsModel(labels=labels).labels
4644
- except pydantic.error_wrappers.ValidationError as exc:
4800
+ except pydantic.v1.error_wrappers.ValidationError as exc:
4645
4801
  raise mlrun.errors.MLRunValueError(
4646
4802
  "Invalid labels format. Must be a dictionary of strings, a list of strings, "
4647
4803
  "or a comma-separated string."
@@ -4719,7 +4875,9 @@ class HTTPRunDB(RunDBInterface):
4719
4875
  name: Optional[str] = None,
4720
4876
  project: Optional[str] = None,
4721
4877
  tag: Optional[str] = None,
4878
+ kind: Optional[str] = None,
4722
4879
  labels: Optional[Union[str, dict[str, Optional[str]], list[str]]] = None,
4880
+ format_: Optional[str] = None,
4723
4881
  since: Optional[datetime] = None,
4724
4882
  until: Optional[datetime] = None,
4725
4883
  page: Optional[int] = None,
@@ -4734,9 +4892,11 @@ class HTTPRunDB(RunDBInterface):
4734
4892
  params = {
4735
4893
  "name": name,
4736
4894
  "tag": tag,
4895
+ "kind": kind,
4737
4896
  "label": labels,
4738
4897
  "since": datetime_to_iso(since),
4739
4898
  "until": datetime_to_iso(until),
4899
+ "format": format_,
4740
4900
  "page": page,
4741
4901
  "page-size": page_size,
4742
4902
  "page-token": page_token,
@@ -4870,6 +5030,58 @@ class HTTPRunDB(RunDBInterface):
4870
5030
  paginated_responses, token = self.process_paginated_responses(responses, "runs")
4871
5031
  return RunList(paginated_responses), token
4872
5032
 
5033
+ def _list_alert_activations(
5034
+ self,
5035
+ project: Optional[str] = None,
5036
+ name: Optional[str] = None,
5037
+ since: Optional[datetime] = None,
5038
+ until: Optional[datetime] = None,
5039
+ entity: Optional[str] = None,
5040
+ severity: Optional[
5041
+ list[Union[mlrun.common.schemas.alert.AlertSeverity, str]]
5042
+ ] = None,
5043
+ entity_kind: Optional[
5044
+ Union[mlrun.common.schemas.alert.EventEntityKind, str]
5045
+ ] = None,
5046
+ event_kind: Optional[Union[mlrun.common.schemas.alert.EventKind, str]] = None,
5047
+ page: Optional[int] = None,
5048
+ page_size: Optional[int] = None,
5049
+ page_token: Optional[str] = None,
5050
+ return_all: bool = False,
5051
+ ) -> tuple[list[mlrun.common.schemas.AlertActivation], Optional[str]]:
5052
+ project = project or config.default_project
5053
+ params = {
5054
+ "name": name,
5055
+ "since": datetime_to_iso(since),
5056
+ "until": datetime_to_iso(until),
5057
+ "entity": entity,
5058
+ "severity": severity,
5059
+ "entity-kind": entity_kind,
5060
+ "event-kind": event_kind,
5061
+ "page": page,
5062
+ "page-size": page_size,
5063
+ "page-token": page_token,
5064
+ }
5065
+ error = "list alert activations"
5066
+ path = f"projects/{project}/alert-activations"
5067
+
5068
+ # Fetch the responses, either one page or all based on `return_all`
5069
+ responses = self.paginated_api_call(
5070
+ "GET", path, error, params=params, return_all=return_all
5071
+ )
5072
+ paginated_responses, token = self.process_paginated_responses(
5073
+ responses, "activations"
5074
+ )
5075
+ return paginated_responses, token
5076
+
5077
+ def _wait_for_background_task_from_response(self, response):
5078
+ if response.status_code == http.HTTPStatus.ACCEPTED:
5079
+ background_task = mlrun.common.schemas.BackgroundTask(**response.json())
5080
+ return self._wait_for_background_task_to_reach_terminal_state(
5081
+ background_task.metadata.name
5082
+ )
5083
+ return None
5084
+
4873
5085
 
4874
5086
  def _as_json(obj):
4875
5087
  fn = getattr(obj, "to_json", None)
mlrun/db/nopdb.py CHANGED
@@ -230,12 +230,14 @@ class NopDB(RunDBInterface):
230
230
 
231
231
  def list_functions(
232
232
  self,
233
- name=None,
234
- project="",
235
- tag="",
233
+ name: Optional[str] = None,
234
+ project: Optional[str] = None,
235
+ tag: Optional[str] = None,
236
+ kind: Optional[str] = None,
236
237
  labels: Optional[Union[str, dict[str, Optional[str]], list[str]]] = None,
237
- since=None,
238
- until=None,
238
+ format_: mlrun.common.formatters.FunctionFormat = mlrun.common.formatters.FunctionFormat.full,
239
+ since: Optional[datetime.datetime] = None,
240
+ until: Optional[datetime.datetime] = None,
239
241
  ):
240
242
  return []
241
243
 
@@ -863,3 +865,30 @@ class NopDB(RunDBInterface):
863
865
 
864
866
  def list_alert_templates(self):
865
867
  pass
868
+
869
+ def list_alert_activations(
870
+ self,
871
+ project: Optional[str] = None,
872
+ name: Optional[str] = None,
873
+ since: Optional[datetime.datetime] = None,
874
+ until: Optional[datetime.datetime] = None,
875
+ entity: Optional[str] = None,
876
+ severity: Optional[
877
+ list[Union[mlrun.common.schemas.alert.AlertSeverity, str]]
878
+ ] = None,
879
+ entity_kind: Optional[
880
+ Union[mlrun.common.schemas.alert.EventEntityKind, str]
881
+ ] = None,
882
+ event_kind: Optional[Union[mlrun.common.schemas.alert.EventKind, str]] = None,
883
+ ):
884
+ pass
885
+
886
+ def paginated_list_alert_activations(
887
+ self,
888
+ *args,
889
+ page: Optional[int] = None,
890
+ page_size: Optional[int] = None,
891
+ page_token: Optional[str] = None,
892
+ **kwargs,
893
+ ):
894
+ pass
mlrun/model.py CHANGED
@@ -24,7 +24,7 @@ from datetime import datetime
24
24
  from os import environ
25
25
  from typing import Any, Optional, Union
26
26
 
27
- import pydantic.error_wrappers
27
+ import pydantic.v1.error_wrappers
28
28
 
29
29
  import mlrun
30
30
  import mlrun.common.constants as mlrun_constants
@@ -739,7 +739,7 @@ class Notification(ModelObj):
739
739
  def validate_notification(self):
740
740
  try:
741
741
  mlrun.common.schemas.notification.Notification(**self.to_dict())
742
- except pydantic.error_wrappers.ValidationError as exc:
742
+ except pydantic.v1.error_wrappers.ValidationError as exc:
743
743
  raise mlrun.errors.MLRunInvalidArgumentError(
744
744
  "Invalid notification object"
745
745
  ) from exc
@@ -17,8 +17,8 @@ import json
17
17
  import re
18
18
  from abc import ABC, abstractmethod
19
19
 
20
- from pydantic import validator
21
- from pydantic.dataclasses import dataclass
20
+ from pydantic.v1 import validator
21
+ from pydantic.v1.dataclasses import dataclass
22
22
 
23
23
  import mlrun.common.helpers
24
24
  import mlrun.common.model_monitoring.helpers
@@ -17,7 +17,7 @@ from abc import ABC, abstractmethod
17
17
  from datetime import datetime
18
18
 
19
19
  import pandas as pd
20
- import pydantic
20
+ import pydantic.v1
21
21
 
22
22
  import mlrun.common.schemas.model_monitoring as mm_schemas
23
23
  import mlrun.model_monitoring.db.tsdb.helpers
@@ -427,7 +427,7 @@ class TSDBConnector(ABC):
427
427
  ), # pyright: ignore[reportArgumentType]
428
428
  )
429
429
  )
430
- except pydantic.ValidationError:
430
+ except pydantic.v1.ValidationError:
431
431
  logger.exception(
432
432
  "Failed to convert data-frame into `ModelEndpointMonitoringResultValues`",
433
433
  full_name=full_name,
@@ -82,9 +82,10 @@ class TDEngineSchema:
82
82
  super_table: str,
83
83
  columns: dict[str, _TDEngineColumn],
84
84
  tags: dict[str, str],
85
+ project: str,
85
86
  database: Optional[str] = None,
86
87
  ):
87
- self.super_table = super_table
88
+ self.super_table = f"{super_table}_{project.replace('-', '_')}"
88
89
  self.columns = columns
89
90
  self.tags = tags
90
91
  self.database = database or _MODEL_MONITORING_DATABASE
@@ -148,6 +149,9 @@ class TDEngineSchema:
148
149
  ) -> str:
149
150
  return f"DROP TABLE if EXISTS {self.database}.{subtable};"
150
151
 
152
+ def drop_supertable_query(self) -> str:
153
+ return f"DROP STABLE if EXISTS {self.database}.{self.super_table};"
154
+
151
155
  def _get_subtables_query(
152
156
  self,
153
157
  values: dict[str, Union[str, int, float, datetime.datetime]],
@@ -260,7 +264,7 @@ class TDEngineSchema:
260
264
 
261
265
  @dataclass
262
266
  class AppResultTable(TDEngineSchema):
263
- def __init__(self, database: Optional[str] = None):
267
+ def __init__(self, project: str, database: Optional[str] = None):
264
268
  super_table = mm_schemas.TDEngineSuperTables.APP_RESULTS
265
269
  columns = {
266
270
  mm_schemas.WriterEvent.END_INFER_TIME: _TDEngineColumn.TIMESTAMP,
@@ -270,18 +274,23 @@ class AppResultTable(TDEngineSchema):
270
274
  mm_schemas.ResultData.RESULT_EXTRA_DATA: _TDEngineColumn.BINARY_1000,
271
275
  }
272
276
  tags = {
273
- mm_schemas.EventFieldType.PROJECT: _TDEngineColumn.BINARY_64,
274
277
  mm_schemas.WriterEvent.ENDPOINT_ID: _TDEngineColumn.BINARY_64,
275
278
  mm_schemas.WriterEvent.APPLICATION_NAME: _TDEngineColumn.BINARY_64,
276
279
  mm_schemas.ResultData.RESULT_NAME: _TDEngineColumn.BINARY_64,
277
280
  mm_schemas.ResultData.RESULT_KIND: _TDEngineColumn.INT,
278
281
  }
279
- super().__init__(super_table, columns, tags, database)
282
+ super().__init__(
283
+ super_table=super_table,
284
+ columns=columns,
285
+ tags=tags,
286
+ database=database,
287
+ project=project,
288
+ )
280
289
 
281
290
 
282
291
  @dataclass
283
292
  class Metrics(TDEngineSchema):
284
- def __init__(self, database: Optional[str] = None):
293
+ def __init__(self, project: str, database: Optional[str] = None):
285
294
  super_table = mm_schemas.TDEngineSuperTables.METRICS
286
295
  columns = {
287
296
  mm_schemas.WriterEvent.END_INFER_TIME: _TDEngineColumn.TIMESTAMP,
@@ -289,17 +298,22 @@ class Metrics(TDEngineSchema):
289
298
  mm_schemas.MetricData.METRIC_VALUE: _TDEngineColumn.FLOAT,
290
299
  }
291
300
  tags = {
292
- mm_schemas.EventFieldType.PROJECT: _TDEngineColumn.BINARY_64,
293
301
  mm_schemas.WriterEvent.ENDPOINT_ID: _TDEngineColumn.BINARY_64,
294
302
  mm_schemas.WriterEvent.APPLICATION_NAME: _TDEngineColumn.BINARY_64,
295
303
  mm_schemas.MetricData.METRIC_NAME: _TDEngineColumn.BINARY_64,
296
304
  }
297
- super().__init__(super_table, columns, tags, database)
305
+ super().__init__(
306
+ super_table=super_table,
307
+ columns=columns,
308
+ tags=tags,
309
+ database=database,
310
+ project=project,
311
+ )
298
312
 
299
313
 
300
314
  @dataclass
301
315
  class Predictions(TDEngineSchema):
302
- def __init__(self, database: Optional[str] = None):
316
+ def __init__(self, project: str, database: Optional[str] = None):
303
317
  super_table = mm_schemas.TDEngineSuperTables.PREDICTIONS
304
318
  columns = {
305
319
  mm_schemas.EventFieldType.TIME: _TDEngineColumn.TIMESTAMP,
@@ -307,23 +321,33 @@ class Predictions(TDEngineSchema):
307
321
  mm_schemas.EventKeyMetrics.CUSTOM_METRICS: _TDEngineColumn.BINARY_1000,
308
322
  }
309
323
  tags = {
310
- mm_schemas.EventFieldType.PROJECT: _TDEngineColumn.BINARY_64,
311
324
  mm_schemas.WriterEvent.ENDPOINT_ID: _TDEngineColumn.BINARY_64,
312
325
  }
313
- super().__init__(super_table, columns, tags, database)
326
+ super().__init__(
327
+ super_table=super_table,
328
+ columns=columns,
329
+ tags=tags,
330
+ database=database,
331
+ project=project,
332
+ )
314
333
 
315
334
 
316
335
  @dataclass
317
336
  class Errors(TDEngineSchema):
318
- def __init__(self, database: Optional[str] = None):
337
+ def __init__(self, project: str, database: Optional[str] = None):
319
338
  super_table = mm_schemas.TDEngineSuperTables.ERRORS
320
339
  columns = {
321
340
  mm_schemas.EventFieldType.TIME: _TDEngineColumn.TIMESTAMP,
322
341
  mm_schemas.EventFieldType.MODEL_ERROR: _TDEngineColumn.BINARY_1000,
323
342
  }
324
343
  tags = {
325
- mm_schemas.EventFieldType.PROJECT: _TDEngineColumn.BINARY_64,
326
344
  mm_schemas.WriterEvent.ENDPOINT_ID: _TDEngineColumn.BINARY_64,
327
345
  mm_schemas.EventFieldType.ERROR_TYPE: _TDEngineColumn.BINARY_64,
328
346
  }
329
- super().__init__(super_table, columns, tags, database)
347
+ super().__init__(
348
+ super_table=super_table,
349
+ columns=columns,
350
+ tags=tags,
351
+ database=database,
352
+ project=project,
353
+ )