mlrun 1.9.0rc2__py3-none-any.whl → 1.9.0rc4__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.

@@ -88,13 +88,18 @@ class ModelEndpointParser(abc.ABC, BaseModel):
88
88
 
89
89
  @classmethod
90
90
  def from_flat_dict(
91
- cls, endpoint_dict: dict, json_parse_values: Optional[list] = None
91
+ cls,
92
+ endpoint_dict: dict,
93
+ json_parse_values: Optional[list] = None,
94
+ validate: bool = True,
92
95
  ) -> "ModelEndpointParser":
93
96
  """Create a `ModelEndpointParser` object from an endpoint dictionary
94
97
 
95
98
  :param endpoint_dict: Model endpoint dictionary.
96
99
  :param json_parse_values: List of dictionary keys with a JSON string value that will be parsed into a
97
100
  dictionary using json.loads().
101
+ :param validate: Whether to validate the flattened dictionary.
102
+ Skip validation to optimize performance when it is safe to do so.
98
103
  """
99
104
  if json_parse_values is None:
100
105
  json_parse_values = cls.json_parse_values()
@@ -103,6 +108,7 @@ class ModelEndpointParser(abc.ABC, BaseModel):
103
108
  model_class=cls,
104
109
  flattened_dictionary=endpoint_dict,
105
110
  json_parse_values=json_parse_values,
111
+ validate=validate,
106
112
  )
107
113
 
108
114
 
@@ -213,17 +219,27 @@ class ModelEndpoint(BaseModel):
213
219
  return flatten_dict
214
220
 
215
221
  @classmethod
216
- def from_flat_dict(cls, endpoint_dict: dict) -> "ModelEndpoint":
222
+ def from_flat_dict(
223
+ cls, endpoint_dict: dict, validate: bool = True
224
+ ) -> "ModelEndpoint":
217
225
  """Create a `ModelEndpoint` object from an endpoint flattened dictionary. Because the provided dictionary
218
226
  is flattened, we pass it as is to the subclasses without splitting the keys into spec, metadata, and status.
219
227
 
220
228
  :param endpoint_dict: Model endpoint dictionary.
229
+ :param validate: Whether to validate the flattened dictionary.
230
+ Skip validation to optimize performance when it is safe to do so.
221
231
  """
222
232
 
223
233
  return cls(
224
- metadata=ModelEndpointMetadata.from_flat_dict(endpoint_dict=endpoint_dict),
225
- spec=ModelEndpointSpec.from_flat_dict(endpoint_dict=endpoint_dict),
226
- status=ModelEndpointStatus.from_flat_dict(endpoint_dict=endpoint_dict),
234
+ metadata=ModelEndpointMetadata.from_flat_dict(
235
+ endpoint_dict=endpoint_dict, validate=validate
236
+ ),
237
+ spec=ModelEndpointSpec.from_flat_dict(
238
+ endpoint_dict=endpoint_dict, validate=validate
239
+ ),
240
+ status=ModelEndpointStatus.from_flat_dict(
241
+ endpoint_dict=endpoint_dict, validate=validate
242
+ ),
227
243
  )
228
244
 
229
245
  def get(self, field, default=None):
@@ -311,7 +327,10 @@ class ModelEndpointMonitoringMetricNoData(_ModelEndpointMonitoringMetricValuesBa
311
327
 
312
328
 
313
329
  def _mapping_attributes(
314
- model_class: type[Model], flattened_dictionary: dict, json_parse_values: list
330
+ model_class: type[Model],
331
+ flattened_dictionary: dict,
332
+ json_parse_values: list,
333
+ validate: bool = True,
315
334
  ) -> Model:
316
335
  """Generate a `BaseModel` object with the provided dictionary attributes.
317
336
 
@@ -319,8 +338,10 @@ def _mapping_attributes(
319
338
  :param flattened_dictionary: Flattened dictionary that contains the model endpoint attributes.
320
339
  :param json_parse_values: List of dictionary keys with a JSON string value that will be parsed into a
321
340
  dictionary using json.loads().
341
+ :param validate: Whether to validate the flattened dictionary.
342
+ Skip validation to optimize performance when it is safe to do so.
322
343
  """
323
- # Get the fields of the provided base model object. These fields will be used to filter to relevent keys
344
+ # Get the fields of the provided base model object. These fields will be used to filter to relevant keys
324
345
  # from the flattened dictionary.
325
346
  wanted_keys = model_class.__fields__.keys()
326
347
 
@@ -338,7 +359,10 @@ def _mapping_attributes(
338
359
  else:
339
360
  dict_to_parse[field_key] = None
340
361
 
341
- return model_class.parse_obj(dict_to_parse)
362
+ if validate:
363
+ return model_class.parse_obj(dict_to_parse)
364
+
365
+ return model_class.construct(**dict_to_parse)
342
366
 
343
367
 
344
368
  def _json_loads_if_not_none(field: Any) -> Any:
mlrun/config.py CHANGED
@@ -634,12 +634,6 @@ default_config = {
634
634
  "offline_storage_path": "model-endpoints/{kind}",
635
635
  "parquet_batching_max_events": 10_000,
636
636
  "parquet_batching_timeout_secs": timedelta(minutes=1).total_seconds(),
637
- "tdengine": {
638
- "run_directly": True,
639
- # timeout and retry are ignored when run_directly is set to True
640
- "timeout": 10,
641
- "retries": 1,
642
- },
643
637
  },
644
638
  "secret_stores": {
645
639
  # Use only in testing scenarios (such as integration tests) to avoid using k8s for secrets (will use in-memory
mlrun/db/base.py CHANGED
@@ -735,6 +735,7 @@ class RunDBInterface(ABC):
735
735
  start: Optional[datetime.datetime] = None,
736
736
  end: Optional[datetime.datetime] = None,
737
737
  tsdb_metrics: bool = True,
738
+ metric_list: Optional[list[str]] = None,
738
739
  top_level: bool = False,
739
740
  uids: Optional[list[str]] = None,
740
741
  latest_only: bool = False,
@@ -750,6 +751,7 @@ class RunDBInterface(ABC):
750
751
  function_tag: Optional[str] = None,
751
752
  endpoint_id: Optional[str] = None,
752
753
  tsdb_metrics: bool = True,
754
+ metric_list: Optional[list[str]] = None,
753
755
  feature_analysis: bool = False,
754
756
  ) -> mlrun.common.schemas.ModelEndpoint:
755
757
  pass
mlrun/db/httpdb.py CHANGED
@@ -1276,8 +1276,8 @@ class HTTPRunDB(RunDBInterface):
1276
1276
  :param producer_uri: Return artifacts produced by the requested producer URI. Producer URI usually
1277
1277
  points to a run and is used to filter artifacts by the run that produced them when the artifact producer id
1278
1278
  is a workflow id (artifact was created as part of a workflow).
1279
- :param format_: The format in which to return the artifacts. Default is 'full'.
1280
- :param limit: Maximum number of artifacts to return.
1279
+ :param format_: The format in which to return the artifacts. Default is 'full'.
1280
+ :param limit: Deprecated - Maximum number of artifacts to return (will be removed in 1.10.0).
1281
1281
  :param partition_by: Field to group results by. When `partition_by` is specified, the `partition_sort_by`
1282
1282
  parameter must be provided as well.
1283
1283
  :param rows_per_partition: How many top rows (per sorting defined by `partition_sort_by` and `partition_order`)
@@ -3584,7 +3584,7 @@ class HTTPRunDB(RunDBInterface):
3584
3584
  params = {
3585
3585
  "type": type,
3586
3586
  "endpoint-id": endpoint_ids,
3587
- "events_format": events_format,
3587
+ "events-format": events_format,
3588
3588
  }
3589
3589
  error_message = (
3590
3590
  f"Failed to get model monitoring metrics,"
@@ -3720,7 +3720,7 @@ class HTTPRunDB(RunDBInterface):
3720
3720
  path=path,
3721
3721
  body=model_endpoint.json(),
3722
3722
  params={
3723
- "creation_strategy": creation_strategy,
3723
+ "creation-strategy": creation_strategy,
3724
3724
  },
3725
3725
  )
3726
3726
  return mlrun.common.schemas.ModelEndpoint(**response.json())
@@ -3750,9 +3750,9 @@ class HTTPRunDB(RunDBInterface):
3750
3750
  method=mlrun.common.types.HTTPMethod.DELETE,
3751
3751
  path=path,
3752
3752
  params={
3753
- "function_name": function_name,
3754
- "function_tag": function_tag,
3755
- "endpoint_id": endpoint_id,
3753
+ "function-name": function_name,
3754
+ "function-tag": function_tag,
3755
+ "endpoint-id": endpoint_id,
3756
3756
  },
3757
3757
  )
3758
3758
 
@@ -3768,6 +3768,7 @@ class HTTPRunDB(RunDBInterface):
3768
3768
  start: Optional[datetime] = None,
3769
3769
  end: Optional[datetime] = None,
3770
3770
  tsdb_metrics: bool = True,
3771
+ metric_list: Optional[list[str]] = None,
3771
3772
  top_level: bool = False,
3772
3773
  uids: Optional[list[str]] = None,
3773
3774
  latest_only: bool = False,
@@ -3785,6 +3786,9 @@ class HTTPRunDB(RunDBInterface):
3785
3786
  :param start: The start time to filter by.Corresponding to the `created` field.
3786
3787
  :param end: The end time to filter by. Corresponding to the `created` field.
3787
3788
  :param tsdb_metrics: Whether to include metrics from the time series DB.
3789
+ :param metric_list: List of metrics to include from the time series DB. Defaults to all metrics.
3790
+ If tsdb_metrics=False, this parameter will be ignored and no tsdb metrics
3791
+ will be included.
3788
3792
  :param top_level: Whether to return only top level model endpoints.
3789
3793
  :param uids: A list of unique ids to filter by.
3790
3794
  :param latest_only: Whether to return only the latest model endpoint version.
@@ -3799,17 +3803,18 @@ class HTTPRunDB(RunDBInterface):
3799
3803
  path=path,
3800
3804
  params={
3801
3805
  "name": names,
3802
- "model_name": model_name,
3803
- "model_tag": model_tag,
3804
- "function_name": function_name,
3805
- "function_tag": function_tag,
3806
+ "model-name": model_name,
3807
+ "model-tag": model_tag,
3808
+ "function-name": function_name,
3809
+ "function-tag": function_tag,
3806
3810
  "label": labels,
3807
3811
  "start": datetime_to_iso(start),
3808
3812
  "end": datetime_to_iso(end),
3809
- "tsdb_metrics": tsdb_metrics,
3813
+ "tsdb-metrics": tsdb_metrics,
3814
+ "metric": metric_list,
3810
3815
  "top-level": top_level,
3811
3816
  "uid": uids,
3812
- "latest_only": latest_only,
3817
+ "latest-only": latest_only,
3813
3818
  },
3814
3819
  )
3815
3820
 
@@ -3823,6 +3828,7 @@ class HTTPRunDB(RunDBInterface):
3823
3828
  function_tag: Optional[str] = None,
3824
3829
  endpoint_id: Optional[str] = None,
3825
3830
  tsdb_metrics: bool = True,
3831
+ metric_list: Optional[list[str]] = None,
3826
3832
  feature_analysis: bool = False,
3827
3833
  ) -> mlrun.common.schemas.ModelEndpoint:
3828
3834
  """
@@ -3834,6 +3840,9 @@ class HTTPRunDB(RunDBInterface):
3834
3840
  :param function_tag: The tag of the function
3835
3841
  :param endpoint_id: The id of the endpoint
3836
3842
  :param tsdb_metrics: Whether to include metrics from the time series DB.
3843
+ :param metric_list: List of metrics to include from the time series DB. Defaults to all metrics.
3844
+ If tsdb_metrics=False, this parameter will be ignored and no tsdb metrics
3845
+ will be included.
3837
3846
  :param feature_analysis: Whether to include feature analysis data (feature_stats,
3838
3847
  current_stats & drift_measures).
3839
3848
 
@@ -3847,11 +3856,12 @@ class HTTPRunDB(RunDBInterface):
3847
3856
  method=mlrun.common.types.HTTPMethod.GET,
3848
3857
  path=path,
3849
3858
  params={
3850
- "function_name": function_name,
3851
- "function_tag": function_tag,
3852
- "endpoint_id": endpoint_id,
3853
- "tsdb_metrics": tsdb_metrics,
3854
- "feature_analysis": feature_analysis,
3859
+ "function-name": function_name,
3860
+ "function-tag": function_tag,
3861
+ "endpoint-id": endpoint_id,
3862
+ "tsdb-metrics": tsdb_metrics,
3863
+ "metric": metric_list,
3864
+ "feature-analysis": feature_analysis,
3855
3865
  },
3856
3866
  )
3857
3867
 
@@ -3879,8 +3889,8 @@ class HTTPRunDB(RunDBInterface):
3879
3889
  attributes_keys = list(attributes.keys())
3880
3890
  attributes["name"] = name
3881
3891
  attributes["project"] = project
3882
- attributes["function_name"] = function_name or None
3883
- attributes["function_tag"] = function_tag or None
3892
+ attributes["function-name"] = function_name or None
3893
+ attributes["function-tag"] = function_tag or None
3884
3894
  attributes["uid"] = endpoint_id or None
3885
3895
  model_endpoint = mlrun.common.schemas.ModelEndpoint.from_flat_dict(attributes)
3886
3896
  path = f"projects/{project}/model-endpoints"
@@ -5089,6 +5099,13 @@ class HTTPRunDB(RunDBInterface):
5089
5099
  project = project or config.default_project
5090
5100
  labels = self._parse_labels(labels)
5091
5101
 
5102
+ if limit:
5103
+ # TODO: Remove this in 1.10.0
5104
+ warnings.warn(
5105
+ "'limit' is deprecated and will be removed in 1.10.0. Use 'page' and 'page_size' instead.",
5106
+ FutureWarning,
5107
+ )
5108
+
5092
5109
  params = {
5093
5110
  "name": name,
5094
5111
  "tag": tag,
mlrun/db/nopdb.py CHANGED
@@ -632,6 +632,7 @@ class NopDB(RunDBInterface):
632
632
  start: Optional[datetime.datetime] = None,
633
633
  end: Optional[datetime.datetime] = None,
634
634
  tsdb_metrics: bool = True,
635
+ metric_list: Optional[list[str]] = None,
635
636
  top_level: bool = False,
636
637
  uids: Optional[list[str]] = None,
637
638
  latest_only: bool = False,
@@ -646,6 +647,7 @@ class NopDB(RunDBInterface):
646
647
  function_tag: Optional[str] = None,
647
648
  endpoint_id: Optional[str] = None,
648
649
  tsdb_metrics: bool = True,
650
+ metric_list: Optional[list[str]] = None,
649
651
  feature_analysis: bool = False,
650
652
  ) -> mlrun.common.schemas.ModelEndpoint:
651
653
  pass
@@ -673,7 +673,9 @@ class MonitoringApplicationController:
673
673
  """
674
674
  logger.info("Starting monitoring controller chief")
675
675
  applications_names = []
676
- endpoints = self.project_obj.list_model_endpoints(tsdb_metrics=True).endpoints
676
+ endpoints = self.project_obj.list_model_endpoints(
677
+ metric_list=["last_request"]
678
+ ).endpoints
677
679
  if not endpoints:
678
680
  logger.info("No model endpoints found", project=self.project)
679
681
  return
@@ -82,7 +82,8 @@ class TSDBConnector(ABC):
82
82
 
83
83
  @abstractmethod
84
84
  def delete_tsdb_records(
85
- self, endpoint_ids: list[str], delete_timeout: Optional[int] = None
85
+ self,
86
+ endpoint_ids: list[str],
86
87
  ) -> None:
87
88
  """
88
89
  Delete model endpoint records from the TSDB connector.
@@ -332,6 +333,7 @@ class TSDBConnector(ABC):
332
333
  model_endpoint_objects: list[mlrun.common.schemas.ModelEndpoint],
333
334
  project: str,
334
335
  run_in_threadpool: Callable,
336
+ metric_list: Optional[list[str]] = None,
335
337
  ) -> list[mlrun.common.schemas.ModelEndpoint]:
336
338
  raise NotImplementedError()
337
339
 
@@ -0,0 +1,213 @@
1
+ # Copyright 2025 Iguazio
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ import traceback
16
+ from collections.abc import Callable
17
+ from enum import Enum
18
+ from typing import Any, Final, Optional, Union
19
+
20
+ import taosws
21
+ from taosws import TaosStmt
22
+
23
+
24
+ class _StrEnum(str, Enum):
25
+ pass
26
+
27
+
28
+ class TimestampPrecision(_StrEnum):
29
+ ms = "ms" # milliseconds
30
+ us = "us" # microseconds
31
+ ns = "ns" # nanoseconds
32
+
33
+
34
+ _TS_PRECISION_TO_FACTOR_AND_FUNC: Final[
35
+ dict[TimestampPrecision, tuple[int, Callable[[list[int]], taosws.PyColumnView]]]
36
+ ] = {
37
+ TimestampPrecision.ms: (10**3, taosws.millis_timestamps_to_column),
38
+ TimestampPrecision.us: (10**6, taosws.micros_timestamps_to_column),
39
+ TimestampPrecision.ns: (10**9, taosws.nanos_timestamps_to_column),
40
+ }
41
+
42
+
43
+ class QueryResult:
44
+ def __init__(self, data, fields):
45
+ self.data = data
46
+ self.fields = fields
47
+
48
+ def __eq__(self, other):
49
+ return self.data == other.data and self.fields == other.fields
50
+
51
+ def __repr__(self):
52
+ return f"QueryResult({self.data}, {self.fields})"
53
+
54
+
55
+ class Field:
56
+ def __init__(self, name, type, bytes):
57
+ self.name = name
58
+ self.type = type
59
+ self.bytes = bytes
60
+
61
+ def __eq__(self, other):
62
+ return (
63
+ self.name == other.name
64
+ and self.type == other.type
65
+ and self.bytes == other.bytes
66
+ )
67
+
68
+ def __repr__(self):
69
+ return f"Field({self.name}, {self.type}, {self.bytes})"
70
+
71
+
72
+ class TDEngineError(Exception):
73
+ pass
74
+
75
+
76
+ class ErrorResult:
77
+ def __init__(self, tb, err):
78
+ self.tb = tb
79
+ self.err = err
80
+
81
+
82
+ def _get_timestamp_column(
83
+ values: list, timestamp_precision: TimestampPrecision
84
+ ) -> taosws.PyColumnView:
85
+ factor, to_col_func = _TS_PRECISION_TO_FACTOR_AND_FUNC[timestamp_precision]
86
+ timestamps = [round(timestamp.timestamp() * factor) for timestamp in values]
87
+ return to_col_func(timestamps)
88
+
89
+
90
+ def values_to_column(
91
+ values: list,
92
+ column_type: str,
93
+ timestamp_precision: TimestampPrecision = TimestampPrecision.ms,
94
+ ) -> taosws.PyColumnView:
95
+ if column_type == "TIMESTAMP":
96
+ return _get_timestamp_column(values, timestamp_precision)
97
+ if column_type == "FLOAT":
98
+ return taosws.floats_to_column(values)
99
+ if column_type == "INT":
100
+ return taosws.ints_to_column(values)
101
+ if column_type.startswith("BINARY"):
102
+ return taosws.binary_to_column(values)
103
+
104
+ raise NotImplementedError(f"Unsupported column type '{column_type}'")
105
+
106
+
107
+ class Statement:
108
+ def __init__(
109
+ self,
110
+ columns: dict[str, str],
111
+ subtable: str,
112
+ values: dict[str, Any],
113
+ timestamp_precision: str = TimestampPrecision.ms,
114
+ ) -> None:
115
+ self.columns = columns
116
+ self.subtable = subtable
117
+ self.values = values
118
+ self.timestamp_precision = TimestampPrecision[timestamp_precision]
119
+
120
+ def prepare(self, statement: TaosStmt) -> TaosStmt:
121
+ question_marks = ", ".join("?" * len(self.columns))
122
+ statement.prepare(f"INSERT INTO ? VALUES ({question_marks});")
123
+ statement.set_tbname(self.subtable)
124
+
125
+ bind_params = []
126
+
127
+ for col_name, col_type in self.columns.items():
128
+ val = self.values[col_name]
129
+ bind_params.append(
130
+ values_to_column(
131
+ [val], col_type, timestamp_precision=self.timestamp_precision
132
+ )
133
+ )
134
+
135
+ statement.bind_param(bind_params)
136
+ statement.add_batch()
137
+ return statement
138
+
139
+
140
+ def _run(connection_string, prefix_statements, q, statements, query):
141
+ try:
142
+ conn = taosws.connect(connection_string)
143
+
144
+ for statement in prefix_statements + statements:
145
+ if isinstance(statement, Statement):
146
+ prepared_statement = statement.prepare(conn.statement())
147
+ prepared_statement.execute()
148
+ else:
149
+ conn.execute(statement)
150
+
151
+ if not query:
152
+ q.put(None)
153
+ return
154
+
155
+ res = conn.query(query)
156
+
157
+ # taosws.TaosField is not serializable
158
+ fields = [
159
+ Field(field.name(), field.type(), field.bytes()) for field in res.fields
160
+ ]
161
+
162
+ q.put(QueryResult(list(res), fields))
163
+ except Exception as e:
164
+ tb = traceback.format_exc()
165
+ q.put(ErrorResult(tb, e))
166
+
167
+
168
+ class TDEngineConnection:
169
+ def __init__(self, connection_string):
170
+ self._connection_string = connection_string
171
+ self.prefix_statements = []
172
+
173
+ self._conn = taosws.connect(self._connection_string)
174
+
175
+ def run(
176
+ self,
177
+ statements: Optional[Union[str, Statement, list[Union[str, Statement]]]] = None,
178
+ query: Optional[str] = None,
179
+ ) -> Optional[QueryResult]:
180
+ statements = statements or []
181
+ if not isinstance(statements, list):
182
+ statements = [statements]
183
+
184
+ for statement in self.prefix_statements + statements:
185
+ if isinstance(statement, Statement):
186
+ try:
187
+ prepared_statement = statement.prepare(self._conn.statement())
188
+ prepared_statement.execute()
189
+ except taosws.Error as e:
190
+ raise TDEngineError(
191
+ f"Failed to run prepared statement `{self._conn.statement()}`: {e}"
192
+ ) from e
193
+ else:
194
+ try:
195
+ self._conn.execute(statement)
196
+ except taosws.Error as e:
197
+ raise TDEngineError(
198
+ f"Failed to run statement `{statement}`: {e}"
199
+ ) from e
200
+
201
+ if not query:
202
+ return None
203
+
204
+ try:
205
+ res = self._conn.query(query)
206
+ except taosws.Error as e:
207
+ raise TDEngineError(f"Failed to run query `{query}`: {e}") from e
208
+
209
+ fields = [
210
+ Field(field.name(), field.type(), field.bytes()) for field in res.fields
211
+ ]
212
+
213
+ return QueryResult(list(res), fields)
@@ -12,17 +12,12 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- import asyncio
16
15
  from datetime import datetime, timedelta
17
16
  from threading import Lock
18
17
  from typing import Callable, Final, Literal, Optional, Union
19
18
 
20
19
  import pandas as pd
21
20
  import taosws
22
- from taoswswrap.tdengine_connection import (
23
- Statement,
24
- TDEngineConnection,
25
- )
26
21
 
27
22
  import mlrun.common.schemas.model_monitoring as mm_schemas
28
23
  import mlrun.common.types
@@ -30,6 +25,10 @@ import mlrun.model_monitoring.db.tsdb.tdengine.schemas as tdengine_schemas
30
25
  import mlrun.model_monitoring.db.tsdb.tdengine.stream_graph_steps
31
26
  from mlrun.datastore.datastore_profile import DatastoreProfile
32
27
  from mlrun.model_monitoring.db import TSDBConnector
28
+ from mlrun.model_monitoring.db.tsdb.tdengine.tdengine_connection import (
29
+ Statement,
30
+ TDEngineConnection,
31
+ )
33
32
  from mlrun.model_monitoring.helpers import get_invocations_fqn
34
33
  from mlrun.utils import logger
35
34
 
@@ -75,12 +74,6 @@ class TDEngineConnector(TSDBConnector):
75
74
 
76
75
  self._init_super_tables()
77
76
 
78
- self._run_directly = (
79
- mlrun.mlconf.model_endpoint_monitoring.tdengine.run_directly
80
- )
81
- self._timeout = mlrun.mlconf.model_endpoint_monitoring.tdengine.timeout
82
- self._retries = mlrun.mlconf.model_endpoint_monitoring.tdengine.retries
83
-
84
77
  @property
85
78
  def connection(self) -> TDEngineConnection:
86
79
  global _connection
@@ -98,7 +91,7 @@ class TDEngineConnector(TSDBConnector):
98
91
  """Establish a connection to the TSDB server."""
99
92
  logger.debug("Creating a new connection to TDEngine", project=self.project)
100
93
  conn = TDEngineConnection(
101
- self._tdengine_connection_profile.dsn(), run_directly=self._run_directly
94
+ self._tdengine_connection_profile.dsn(),
102
95
  )
103
96
  conn.prefix_statements = [f"USE {self.database}"]
104
97
 
@@ -126,8 +119,6 @@ class TDEngineConnector(TSDBConnector):
126
119
  self.connection.prefix_statements = []
127
120
  self.connection.run(
128
121
  statements=f"CREATE DATABASE IF NOT EXISTS {self.database} PRECISION '{self._timestamp_precision}'",
129
- timeout=self._timeout,
130
- retries=self._retries,
131
122
  )
132
123
  self.connection.prefix_statements = [f"USE {self.database}"]
133
124
  logger.debug(
@@ -147,8 +138,6 @@ class TDEngineConnector(TSDBConnector):
147
138
  conn = self.connection
148
139
  conn.run(
149
140
  statements=create_table_query,
150
- timeout=self._timeout,
151
- retries=self._retries,
152
141
  )
153
142
 
154
143
  def write_application_event(
@@ -208,8 +197,6 @@ class TDEngineConnector(TSDBConnector):
208
197
  create_table_sql,
209
198
  insert_statement,
210
199
  ],
211
- timeout=self._timeout,
212
- retries=self._retries,
213
200
  )
214
201
 
215
202
  @staticmethod
@@ -313,7 +300,8 @@ class TDEngineConnector(TSDBConnector):
313
300
  )
314
301
 
315
302
  def delete_tsdb_records(
316
- self, endpoint_ids: list[str], delete_timeout: Optional[int] = None
303
+ self,
304
+ endpoint_ids: list[str],
317
305
  ):
318
306
  """
319
307
  To delete subtables within TDEngine, we first query the subtables names with the provided endpoint_ids.
@@ -334,8 +322,6 @@ class TDEngineConnector(TSDBConnector):
334
322
  )
335
323
  subtables_result = self.connection.run(
336
324
  query=get_subtable_query,
337
- timeout=self._timeout,
338
- retries=self._retries,
339
325
  )
340
326
  subtables.extend([subtable[0] for subtable in subtables_result.data])
341
327
  except Exception as e:
@@ -356,8 +342,6 @@ class TDEngineConnector(TSDBConnector):
356
342
  try:
357
343
  self.connection.run(
358
344
  statements=drop_statements,
359
- timeout=delete_timeout or self._timeout,
360
- retries=self._retries,
361
345
  )
362
346
  except Exception as e:
363
347
  logger.warning(
@@ -388,8 +372,6 @@ class TDEngineConnector(TSDBConnector):
388
372
  try:
389
373
  self.connection.run(
390
374
  statements=drop_statements,
391
- timeout=self._timeout,
392
- retries=self._retries,
393
375
  )
394
376
  except Exception as e:
395
377
  logger.warning(
@@ -413,8 +395,6 @@ class TDEngineConnector(TSDBConnector):
413
395
  try:
414
396
  table_name = self.connection.run(
415
397
  query=query_random_table_name,
416
- timeout=self._timeout,
417
- retries=self._retries,
418
398
  )
419
399
  if len(table_name.data) == 0:
420
400
  # no tables were found under the database
@@ -437,8 +417,6 @@ class TDEngineConnector(TSDBConnector):
437
417
  try:
438
418
  self.connection.run(
439
419
  statements=drop_database_query,
440
- timeout=self._timeout,
441
- retries=self._retries,
442
420
  )
443
421
  logger.debug(
444
422
  "The TDEngine database has been successfully dropped",
@@ -531,7 +509,7 @@ class TDEngineConnector(TSDBConnector):
531
509
  logger.debug("Querying TDEngine", query=full_query)
532
510
  try:
533
511
  query_result = self.connection.run(
534
- query=full_query, timeout=self._timeout, retries=self._retries
512
+ query=full_query,
535
513
  )
536
514
  except taosws.QueryError as e:
537
515
  raise mlrun.errors.MLRunInvalidArgumentError(
@@ -908,6 +886,7 @@ class TDEngineConnector(TSDBConnector):
908
886
  model_endpoint_objects: list[mlrun.common.schemas.ModelEndpoint],
909
887
  project: str,
910
888
  run_in_threadpool: Callable,
889
+ metric_list: Optional[list[str]] = None,
911
890
  ) -> list[mlrun.common.schemas.ModelEndpoint]:
912
891
  """
913
892
  Add basic metrics to the model endpoint object.
@@ -916,24 +895,28 @@ class TDEngineConnector(TSDBConnector):
916
895
  be filled with the relevant basic metrics.
917
896
  :param project: The name of the project.
918
897
  :param run_in_threadpool: A function that runs another function in a thread pool.
898
+ :param metric_list: List of metrics to include from the time series DB. Defaults to all metrics.
919
899
 
920
900
  :return: A list of `ModelEndpointMonitoringMetric` objects.
921
901
  """
922
902
 
923
903
  uids = [mep.metadata.uid for mep in model_endpoint_objects]
924
- coroutines = [
925
- run_in_threadpool(self.get_error_count, endpoint_ids=uids),
926
- run_in_threadpool(self.get_last_request, endpoint_ids=uids),
927
- run_in_threadpool(self.get_avg_latency, endpoint_ids=uids),
928
- run_in_threadpool(self.get_drift_status, endpoint_ids=uids),
929
- ]
930
-
931
- (
932
- error_count_df,
933
- last_request_df,
934
- avg_latency_df,
935
- drift_status_df,
936
- ) = await asyncio.gather(*coroutines)
904
+
905
+ metric_name_to_function = {
906
+ "error_count": self.get_error_count,
907
+ "last_request": self.get_last_request,
908
+ "avg_latency": self.get_avg_latency,
909
+ "result_status": self.get_drift_status,
910
+ }
911
+ if metric_list is not None:
912
+ for metric_name in list(metric_name_to_function):
913
+ if metric_name not in metric_list:
914
+ del metric_name_to_function[metric_name]
915
+
916
+ metric_name_to_df = {
917
+ metric_name: function(endpoint_ids=uids)
918
+ for metric_name, function in metric_name_to_function.items()
919
+ }
937
920
 
938
921
  def add_metrics(
939
922
  mep: mlrun.common.schemas.ModelEndpoint,
@@ -955,12 +938,7 @@ class TDEngineConnector(TSDBConnector):
955
938
  map(
956
939
  lambda mep: add_metrics(
957
940
  mep=mep,
958
- df_dictionary={
959
- "error_count": error_count_df,
960
- "last_request": last_request_df,
961
- "avg_latency": avg_latency_df,
962
- "result_status": drift_status_df,
963
- },
941
+ df_dictionary=metric_name_to_df,
964
942
  ),
965
943
  model_endpoint_objects,
966
944
  )
@@ -470,7 +470,8 @@ class V3IOTSDBConnector(TSDBConnector):
470
470
  store.rm(tsdb_path, recursive=True)
471
471
 
472
472
  def delete_tsdb_records(
473
- self, endpoint_ids: list[str], delete_timeout: Optional[int] = None
473
+ self,
474
+ endpoint_ids: list[str],
474
475
  ):
475
476
  logger.debug(
476
477
  "Deleting model endpoints resources using the V3IO TSDB connector",
@@ -1085,6 +1086,7 @@ class V3IOTSDBConnector(TSDBConnector):
1085
1086
  model_endpoint_objects: list[mlrun.common.schemas.ModelEndpoint],
1086
1087
  project: str,
1087
1088
  run_in_threadpool: Callable,
1089
+ metric_list: Optional[list[str]] = None,
1088
1090
  ) -> list[mlrun.common.schemas.ModelEndpoint]:
1089
1091
  """
1090
1092
  Fetch basic metrics from V3IO TSDB and add them to MEP objects.
@@ -1093,6 +1095,7 @@ class V3IOTSDBConnector(TSDBConnector):
1093
1095
  be filled with the relevant basic metrics.
1094
1096
  :param project: The name of the project.
1095
1097
  :param run_in_threadpool: A function that runs another function in a thread pool.
1098
+ :param metric_list: List of metrics to include from the time series DB. Defaults to all metrics.
1096
1099
 
1097
1100
  :return: A list of `ModelEndpointMonitoringMetric` objects.
1098
1101
  """
@@ -1104,15 +1107,27 @@ class V3IOTSDBConnector(TSDBConnector):
1104
1107
  uids.append(uid)
1105
1108
  model_endpoint_objects_by_uid[uid] = model_endpoint_object
1106
1109
 
1107
- error_count_res = await run_in_threadpool(
1108
- self.get_error_count, endpoint_ids=uids, get_raw=True
1109
- )
1110
- avg_latency_res = await run_in_threadpool(
1111
- self.get_avg_latency, endpoint_ids=uids, get_raw=True
1112
- )
1113
- drift_status_res = await run_in_threadpool(
1114
- self.get_drift_status, endpoint_ids=uids, get_raw=True
1115
- )
1110
+ metric_name_to_function_and_column_name = {
1111
+ "error_count": (self.get_error_count, "count(error_count)"),
1112
+ "avg_latency": (self.get_avg_latency, "avg(latency)"),
1113
+ "result_status": (self.get_drift_status, "max(result_status)"),
1114
+ }
1115
+ if metric_list is not None:
1116
+ for metric_name in list(metric_name_to_function_and_column_name):
1117
+ if metric_name not in metric_list:
1118
+ del metric_name_to_function_and_column_name[metric_name]
1119
+
1120
+ metric_name_to_result = {}
1121
+
1122
+ for metric_name, (
1123
+ function,
1124
+ _,
1125
+ ) in metric_name_to_function_and_column_name.items():
1126
+ metric_name_to_result[metric_name] = await run_in_threadpool(
1127
+ function,
1128
+ endpoint_ids=uids,
1129
+ get_raw=True,
1130
+ )
1116
1131
 
1117
1132
  def add_metric(
1118
1133
  metric: str,
@@ -1128,26 +1143,16 @@ class V3IOTSDBConnector(TSDBConnector):
1128
1143
  if mep and value is not None and not math.isnan(value):
1129
1144
  setattr(mep.status, metric, value)
1130
1145
 
1131
- add_metric(
1132
- "error_count",
1133
- "count(error_count)",
1134
- error_count_res,
1135
- )
1136
-
1137
- add_metric(
1138
- "avg_latency",
1139
- "avg(latency)",
1140
- avg_latency_res,
1141
- )
1142
- add_metric(
1143
- "result_status",
1144
- "max(result_status)",
1145
- drift_status_res,
1146
- )
1147
-
1148
- self._enrich_mep_with_last_request(
1149
- model_endpoint_objects_by_uid=model_endpoint_objects_by_uid
1150
- )
1146
+ for metric_name, result in metric_name_to_result.items():
1147
+ add_metric(
1148
+ metric_name,
1149
+ metric_name_to_function_and_column_name[metric_name][1],
1150
+ result,
1151
+ )
1152
+ if metric_list is None or "last_request" in metric_list:
1153
+ self._enrich_mep_with_last_request(
1154
+ model_endpoint_objects_by_uid=model_endpoint_objects_by_uid
1155
+ )
1151
1156
 
1152
1157
  return list(model_endpoint_objects_by_uid.values())
1153
1158
 
@@ -384,9 +384,6 @@ class ProcessEndpointEvent(mlrun.feature_store.steps.MapClass):
384
384
  # Set time for the first request of the current endpoint
385
385
  self.first_request[endpoint_id] = timestamp
386
386
 
387
- # Set time for the last reqeust of the current endpoint
388
- self.last_request[endpoint_id] = timestamp
389
-
390
387
  if not self.is_valid(
391
388
  validation_function=is_not_none,
392
389
  field=request_id,
@@ -413,7 +410,7 @@ class ProcessEndpointEvent(mlrun.feature_store.steps.MapClass):
413
410
  return None
414
411
 
415
412
  # Convert timestamp to a datetime object
416
- timestamp = datetime.datetime.fromisoformat(timestamp)
413
+ timestamp_obj = datetime.datetime.fromisoformat(timestamp)
417
414
 
418
415
  # Separate each model invocation into sub events that will be stored as dictionary
419
416
  # in list of events. This list will be used as the body for the storey event.
@@ -454,16 +451,16 @@ class ProcessEndpointEvent(mlrun.feature_store.steps.MapClass):
454
451
  EventFieldType.FUNCTION_URI: function_uri,
455
452
  EventFieldType.ENDPOINT_NAME: event.get(EventFieldType.MODEL),
456
453
  EventFieldType.MODEL_CLASS: model_class,
457
- EventFieldType.TIMESTAMP: timestamp,
454
+ EventFieldType.TIMESTAMP: timestamp_obj,
458
455
  EventFieldType.ENDPOINT_ID: endpoint_id,
459
456
  EventFieldType.REQUEST_ID: request_id,
460
457
  EventFieldType.LATENCY: latency,
461
458
  EventFieldType.FEATURES: feature,
462
459
  EventFieldType.PREDICTION: prediction,
463
460
  EventFieldType.FIRST_REQUEST: self.first_request[endpoint_id],
464
- EventFieldType.LAST_REQUEST: self.last_request[endpoint_id],
461
+ EventFieldType.LAST_REQUEST: timestamp,
465
462
  EventFieldType.LAST_REQUEST_TIMESTAMP: mlrun.utils.enrich_datetime_with_tz_info(
466
- self.last_request[endpoint_id]
463
+ timestamp
467
464
  ).timestamp(),
468
465
  EventFieldType.LABELS: event.get(EventFieldType.LABELS, {}),
469
466
  EventFieldType.METRICS: event.get(EventFieldType.METRICS, {}),
@@ -492,6 +489,7 @@ class ProcessEndpointEvent(mlrun.feature_store.steps.MapClass):
492
489
  project=self.project,
493
490
  endpoint_id=endpoint_id,
494
491
  name=endpoint_name,
492
+ tsdb_metrics=False,
495
493
  )
496
494
  .flat_dict()
497
495
  )
@@ -503,10 +501,6 @@ class ProcessEndpointEvent(mlrun.feature_store.steps.MapClass):
503
501
  if first_request:
504
502
  self.first_request[endpoint_id] = first_request
505
503
 
506
- last_request = endpoint_record.get(EventFieldType.LAST_REQUEST)
507
- if last_request:
508
- self.last_request[endpoint_id] = last_request
509
-
510
504
  # add endpoint to endpoints set
511
505
  self.endpoints.add(endpoint_id)
512
506
 
@@ -619,6 +613,7 @@ class MapFeatureNames(mlrun.feature_store.steps.MapClass):
619
613
  project=self.project,
620
614
  endpoint_id=endpoint_id,
621
615
  name=event[EventFieldType.ENDPOINT_NAME],
616
+ tsdb_metrics=False,
622
617
  )
623
618
  .flat_dict()
624
619
  )
@@ -692,6 +687,7 @@ class MapFeatureNames(mlrun.feature_store.steps.MapClass):
692
687
  project=self.project,
693
688
  endpoint_id=endpoint_id,
694
689
  name=event[EventFieldType.ENDPOINT_NAME],
690
+ tsdb_metrics=False,
695
691
  )
696
692
  .flat_dict()
697
693
  )
mlrun/projects/project.py CHANGED
@@ -3796,6 +3796,7 @@ class MlrunProject(ModelObj):
3796
3796
  uids: Optional[list[str]] = None,
3797
3797
  latest_only: bool = False,
3798
3798
  tsdb_metrics: bool = True,
3799
+ metric_list: Optional[list[str]] = None,
3799
3800
  ) -> mlrun.common.schemas.ModelEndpointList:
3800
3801
  """
3801
3802
  Returns a list of `ModelEndpoint` objects. Each `ModelEndpoint` object represents the current state of a
@@ -3825,10 +3826,15 @@ class MlrunProject(ModelObj):
3825
3826
  or just `"label"` for key existence.
3826
3827
  - A comma-separated string formatted as `"label1=value1,label2"` to match entities with
3827
3828
  the specified key-value pairs or key existence.
3828
- :param start: The start time to filter by.Corresponding to the `created` field.
3829
- :param end: The end time to filter by. Corresponding to the `created` field.
3830
- :param top_level: if true will return only routers and endpoint that are NOT children of any router
3831
- :param uids: if passed will return a list `ModelEndpoint` object with uid in uids
3829
+ :param start: The start time to filter by.Corresponding to the `created` field.
3830
+ :param end: The end time to filter by. Corresponding to the `created` field.
3831
+ :param top_level: If true will return only routers and endpoint that are NOT children of any router.
3832
+ :param uids: If passed will return a list `ModelEndpoint` object with uid in uids.
3833
+ :param tsdb_metrics: When True, the time series metrics will be added to the output
3834
+ of the resulting.
3835
+ :param metric_list: List of metrics to include from the time series DB. Defaults to all metrics.
3836
+ If tsdb_metrics=False, this parameter will be ignored and no tsdb metrics
3837
+ will be included.
3832
3838
 
3833
3839
  :returns: Returns a list of `ModelEndpoint` objects.
3834
3840
  """
@@ -3847,6 +3853,7 @@ class MlrunProject(ModelObj):
3847
3853
  uids=uids,
3848
3854
  latest_only=latest_only,
3849
3855
  tsdb_metrics=tsdb_metrics,
3856
+ metric_list=metric_list,
3850
3857
  )
3851
3858
 
3852
3859
  def run_function(
@@ -4315,7 +4322,7 @@ class MlrunProject(ModelObj):
4315
4322
  :param kind: Return artifacts of the requested kind.
4316
4323
  :param category: Return artifacts of the requested category.
4317
4324
  :param tree: Return artifacts of the requested tree.
4318
- :param limit: Maximum number of artifacts to return.
4325
+ :param limit: Deprecated - Maximum number of artifacts to return (will be removed in 1.10.0).
4319
4326
  :param format_: The format in which to return the artifacts. Default is 'full'.
4320
4327
  :param partition_by: Field to group results by. When `partition_by` is specified, the `partition_sort_by`
4321
4328
  parameter must be provided as well.
@@ -4326,6 +4333,14 @@ class MlrunProject(ModelObj):
4326
4333
  :param partition_order: Order of sorting within partitions - `asc` or `desc`. Default is `desc`.
4327
4334
  """
4328
4335
  db = mlrun.db.get_run_db(secrets=self._secrets)
4336
+
4337
+ if limit:
4338
+ # TODO: Remove this in 1.10.0
4339
+ warnings.warn(
4340
+ "'limit' is deprecated and will be removed in 1.10.0. Use 'page' and 'page_size' instead.",
4341
+ FutureWarning,
4342
+ )
4343
+
4329
4344
  return db.list_artifacts(
4330
4345
  name,
4331
4346
  self.metadata.name,
@@ -1000,7 +1000,7 @@ class RemoteRuntime(KubeResource):
1000
1000
  else:
1001
1001
  http_client_kwargs["json"] = body
1002
1002
  try:
1003
- logger.info("Invoking function", method=method, path=path)
1003
+ logger.debug("Invoking function", method=method, path=path)
1004
1004
  if not getattr(self, "_http_session", None):
1005
1005
  self._http_session = requests.Session()
1006
1006
  resp = self._http_session.request(
mlrun/serving/states.py CHANGED
@@ -415,15 +415,18 @@ class BaseStep(ModelObj):
415
415
  steps: list[Union[str, StepToDict, dict[str, Any]]],
416
416
  force: bool = False,
417
417
  ):
418
- """set list of steps as downstream from this step, in the order specified. This will overwrite any existing
418
+ """
419
+ Set list of steps as downstream from this step, in the order specified. This will overwrite any existing
419
420
  downstream steps.
420
421
 
421
422
  :param steps: list of steps to follow this one
422
423
  :param force: whether to overwrite existing downstream steps. If False, this method will fail if any downstream
423
- steps have already been defined. Defaults to False.
424
+ steps have already been defined. Defaults to False.
425
+
424
426
  :return: the last step added to the flow
425
427
 
426
- example:
428
+ example::
429
+
427
430
  The below code sets the downstream nodes of step1 by using a list of steps (provided to `set_flow()`) and a
428
431
  single step (provided to `to()`), resulting in the graph (step1 -> step2 -> step3 -> step4).
429
432
  Notice that using `force=True` is required in case step1 already had downstream nodes (e.g. if the existing
@@ -16,6 +16,7 @@ import re
16
16
  import typing
17
17
 
18
18
  import aiohttp
19
+ import orjson
19
20
 
20
21
  import mlrun.common.schemas
21
22
  import mlrun.lists
@@ -86,9 +87,14 @@ class WebhookNotification(NotificationBase):
86
87
  # we automatically handle it as `ssl=None` for their convenience.
87
88
  verify_ssl = verify_ssl and None if url.startswith("https") else None
88
89
 
89
- async with aiohttp.ClientSession() as session:
90
+ async with aiohttp.ClientSession(
91
+ json_serialize=self._encoder,
92
+ ) as session:
90
93
  response = await getattr(session, method)(
91
- url, headers=headers, json=request_body, ssl=verify_ssl
94
+ url,
95
+ headers=headers,
96
+ json=request_body,
97
+ ssl=verify_ssl,
92
98
  )
93
99
  response.raise_for_status()
94
100
 
@@ -128,3 +134,13 @@ class WebhookNotification(NotificationBase):
128
134
  )
129
135
 
130
136
  return override_body
137
+
138
+ @property
139
+ def _encoder(self):
140
+ return lambda body: orjson.dumps(
141
+ body,
142
+ option=orjson.OPT_NAIVE_UTC
143
+ | orjson.OPT_SERIALIZE_NUMPY
144
+ | orjson.OPT_NON_STR_KEYS
145
+ | orjson.OPT_SORT_KEYS,
146
+ ).decode()
@@ -1,4 +1,4 @@
1
1
  {
2
- "git_commit": "73f7c48f424b72bc46d43b4a27f7b470e5290d5c",
3
- "version": "1.9.0-rc2"
2
+ "git_commit": "f19c66499d330c4ab0f375d6fb392bf9c6ffb6db",
3
+ "version": "1.9.0-rc4"
4
4
  }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mlrun
3
- Version: 1.9.0rc2
3
+ Version: 1.9.0rc4
4
4
  Summary: Tracking and config of machine learning runs
5
5
  Home-page: https://github.com/mlrun/mlrun
6
6
  Author: Yaron Haviv
@@ -44,7 +44,7 @@ Requires-Dist: semver~=3.0
44
44
  Requires-Dist: dependency-injector~=4.41
45
45
  Requires-Dist: fsspec<2024.7,>=2023.9.2
46
46
  Requires-Dist: v3iofs~=0.1.17
47
- Requires-Dist: storey~=1.8.11
47
+ Requires-Dist: storey~=1.9.0
48
48
  Requires-Dist: inflection~=0.5.0
49
49
  Requires-Dist: python-dotenv~=1.0
50
50
  Requires-Dist: setuptools>=75.2
@@ -99,7 +99,6 @@ Requires-Dist: ossfs==2023.12.0; extra == "alibaba-oss"
99
99
  Requires-Dist: oss2==2.18.1; extra == "alibaba-oss"
100
100
  Provides-Extra: tdengine
101
101
  Requires-Dist: taos-ws-py==0.3.2; extra == "tdengine"
102
- Requires-Dist: taoswswrap~=0.3.5; extra == "tdengine"
103
102
  Provides-Extra: snowflake
104
103
  Requires-Dist: snowflake-connector-python~=3.7; extra == "snowflake"
105
104
  Provides-Extra: kfp18
@@ -152,7 +151,6 @@ Requires-Dist: s3fs<2024.7,>=2023.9.2; extra == "all"
152
151
  Requires-Dist: snowflake-connector-python~=3.7; extra == "all"
153
152
  Requires-Dist: sqlalchemy~=1.4; extra == "all"
154
153
  Requires-Dist: taos-ws-py==0.3.2; extra == "all"
155
- Requires-Dist: taoswswrap~=0.3.5; extra == "all"
156
154
  Provides-Extra: complete
157
155
  Requires-Dist: adlfs==2023.9.0; extra == "complete"
158
156
  Requires-Dist: aiobotocore<2.16,>=2.5.0; extra == "complete"
@@ -184,7 +182,6 @@ Requires-Dist: s3fs<2024.7,>=2023.9.2; extra == "complete"
184
182
  Requires-Dist: snowflake-connector-python~=3.7; extra == "complete"
185
183
  Requires-Dist: sqlalchemy~=1.4; extra == "complete"
186
184
  Requires-Dist: taos-ws-py==0.3.2; extra == "complete"
187
- Requires-Dist: taoswswrap~=0.3.5; extra == "complete"
188
185
  Provides-Extra: complete-api
189
186
  Requires-Dist: adlfs==2023.9.0; extra == "complete-api"
190
187
  Requires-Dist: aiobotocore<2.16,>=2.5.0; extra == "complete-api"
@@ -229,7 +226,6 @@ Requires-Dist: s3fs<2024.7,>=2023.9.2; extra == "complete-api"
229
226
  Requires-Dist: snowflake-connector-python~=3.7; extra == "complete-api"
230
227
  Requires-Dist: sqlalchemy~=1.4; extra == "complete-api"
231
228
  Requires-Dist: taos-ws-py==0.3.2; extra == "complete-api"
232
- Requires-Dist: taoswswrap~=0.3.5; extra == "complete-api"
233
229
  Requires-Dist: timelength~=1.1; extra == "complete-api"
234
230
  Requires-Dist: uvicorn~=0.32.1; extra == "complete-api"
235
231
  Dynamic: author
@@ -1,6 +1,6 @@
1
1
  mlrun/__init__.py,sha256=Cqm9U9eCEdLpMejhU2BEhubu0mHL71igJJIwYa738EA,7450
2
2
  mlrun/__main__.py,sha256=0NDzPf9VFRO8KFfGgb8mkGUPIDS285aASV8Hbxs-ND0,45920
3
- mlrun/config.py,sha256=JptQ5cano4qGdSt8sFiEMQpT96Wr9Rv4A9q_cyMJgOo,72127
3
+ mlrun/config.py,sha256=OYzmm0WrHPiKFPYQ8xrABfYNLzTgnj80_P4iu5H2aQI,71930
4
4
  mlrun/errors.py,sha256=LkcbXTLANGdsgo2CRX2pdbyNmt--lMsjGv0XZMgP-Nc,8222
5
5
  mlrun/execution.py,sha256=FUktsD3puSFjc3LZJU35b-OmFBrBPBNntViCLQVuwnk,50008
6
6
  mlrun/features.py,sha256=ReBaNGsBYXqcbgI012n-SO_j6oHIbk_Vpv0CGPXbUmo,15842
@@ -75,7 +75,7 @@ mlrun/common/schemas/workflow.py,sha256=6u9niXfXpV-_c2rZL97gFIdAnOfM5WK-OCbrM5Kk
75
75
  mlrun/common/schemas/model_monitoring/__init__.py,sha256=SxHG-GIdcTEuFxpKzkUdT9zKaU5Xqz9qF1uCwXvZ2z8,1709
76
76
  mlrun/common/schemas/model_monitoring/constants.py,sha256=wbNe_n5wX98gD1XQ6jmt97Jh59S9GsE54UBPZl9Pg20,12570
77
77
  mlrun/common/schemas/model_monitoring/grafana.py,sha256=THQlLfPBevBksta8p5OaIsBaJtsNSXexLvHrDxOaVns,2095
78
- mlrun/common/schemas/model_monitoring/model_endpoints.py,sha256=O0i-pvzcXJVgf9E_tNcudDTa1xLaJchzPGfZZ8MNdD4,11482
78
+ mlrun/common/schemas/model_monitoring/model_endpoints.py,sha256=YYFai89qBTnKM8dSUncVD25uwz8QdcTLrEb7vMefyTc,12391
79
79
  mlrun/data_types/__init__.py,sha256=wdxGS1PTnaKXiNZ7PYGxxo86OifHH7NYoArIjDJksLA,1054
80
80
  mlrun/data_types/data_types.py,sha256=0_oKLC6-sXL2_nnaDMP_HSXB3fD1nJAG4J2Jq6sGNNw,4998
81
81
  mlrun/data_types/infer.py,sha256=Ogp3rsENVkjU0GDaGa9J1vjGrvMxgzwbSEuG51nt61E,6477
@@ -108,10 +108,10 @@ mlrun/datastore/wasbfs/__init__.py,sha256=s5Ul-0kAhYqFjKDR2X0O2vDGDbLQQduElb32Ev
108
108
  mlrun/datastore/wasbfs/fs.py,sha256=ge8NK__5vTcFT-krI155_8RDUywQw4SIRX6BWATXy9Q,6299
109
109
  mlrun/db/__init__.py,sha256=WqJ4x8lqJ7ZoKbhEyFqkYADd9P6E3citckx9e9ZLcIU,1163
110
110
  mlrun/db/auth_utils.py,sha256=hpg8D2r82oN0BWabuWN04BTNZ7jYMAF242YSUpK7LFM,5211
111
- mlrun/db/base.py,sha256=Uo28PyTRkauFLGHZPF6IkDbF-WyEA03GObC3su87Pr8,30716
111
+ mlrun/db/base.py,sha256=4ILHlN9vMw3n78qiiTJ1997ykgDKKqxDkLl7lHVVKJg,30814
112
112
  mlrun/db/factory.py,sha256=yP2vVmveUE7LYTCHbS6lQIxP9rW--zdISWuPd_I3d_4,2111
113
- mlrun/db/httpdb.py,sha256=l4qdr7MWfLHuq3gV5fHQspLbAxXbJinGlN0kO-sqftA,231598
114
- mlrun/db/nopdb.py,sha256=TwyU1B6Z4S6n5iu6pftxRqimhvroz1PnPwFhAoXxr4c,27098
113
+ mlrun/db/httpdb.py,sha256=6CfmyhTG5ZiRUnfayIJN5O1jiYmtarqIY_8FU_gyl0Y,232601
114
+ mlrun/db/nopdb.py,sha256=4TujePdRef5WpZY-TiGL9BmXphilNAypKREiGnqnKtg,27196
115
115
  mlrun/feature_store/__init__.py,sha256=SlI845bWt6xX34SXunHHqhmFAR9-5v2ak8N-qpcAPGo,1328
116
116
  mlrun/feature_store/api.py,sha256=qKj5Tk6prTab6XWatWhBuPRVp0eJEctoxRMN2wz48vA,32168
117
117
  mlrun/feature_store/common.py,sha256=Z7USI-d1fo0iwBMsqMBtJflJfyuiV3BLoDXQPSAoBAs,12826
@@ -219,10 +219,10 @@ mlrun/launcher/local.py,sha256=775HY-8S9LFUX5ubGXrLO0N1lVh8bn-DHFmNYuNqQPA,11451
219
219
  mlrun/launcher/remote.py,sha256=rLJW4UAnUT5iUb4BsGBOAV3K4R29a0X4lFtRkVKlyYU,7709
220
220
  mlrun/model_monitoring/__init__.py,sha256=ELy7njEtZnz09Dc6PGZSFFEGtnwI15bJNWM3Pj4_YIs,753
221
221
  mlrun/model_monitoring/api.py,sha256=LU58dzE4QZiMH23lgiqfI__3m2E3eEZP-DQe2ioUSwM,28317
222
- mlrun/model_monitoring/controller.py,sha256=m4Zx_NQ0C-A7WtjBoXnqBmS11RRtLvBaFgbFbIgrdVc,36847
222
+ mlrun/model_monitoring/controller.py,sha256=V5eLOIYsVB6SYMlDQD3--FEW2qN133D1J5I61yzMDn0,36880
223
223
  mlrun/model_monitoring/features_drift_table.py,sha256=c6GpKtpOJbuT1u5uMWDL_S-6N4YPOmlktWMqPme3KFY,25308
224
224
  mlrun/model_monitoring/helpers.py,sha256=8QsoYRPOVSnR3Lcv99m4XYrp_cR6hSqBUflYSOkJmFQ,21019
225
- mlrun/model_monitoring/stream_processing.py,sha256=CEVcIFJ0jYvkIMu8hKsIH0HEkrn5l_NoHsxNLk72D5E,33583
225
+ mlrun/model_monitoring/stream_processing.py,sha256=Gu3TQzYoNjbreZYI73-F49QpYrod9RZOyGSgininBsA,33373
226
226
  mlrun/model_monitoring/tracking_policy.py,sha256=PBIGrUYWrwcE5gwXupBIVzOb0QRRwPJsgQm_yLGQxB4,5595
227
227
  mlrun/model_monitoring/writer.py,sha256=ibbhvfSHb8Reqlb7RGFEAUNM4iTyK1gk8-2m46mP6VM,8428
228
228
  mlrun/model_monitoring/applications/__init__.py,sha256=xDBxkBjl-whHSG_4t1mLkxiypLH-fzn8TmAW9Mjo2uI,759
@@ -237,15 +237,16 @@ mlrun/model_monitoring/db/__init__.py,sha256=r47xPGZpIfMuv8J3PQCZTSqVPMhUta4sSJC
237
237
  mlrun/model_monitoring/db/_schedules.py,sha256=RWn4wtKsIXg668gMLpxO9I8GlkxvPSaA5y7w-wFDcgE,9048
238
238
  mlrun/model_monitoring/db/_stats.py,sha256=VVMWLMqG3Us3ozBkLaokJF22Ewv8WKmVE1-OvS_g9vA,6943
239
239
  mlrun/model_monitoring/db/tsdb/__init__.py,sha256=4S86V_Ot_skE16SLkw0WwsaAUB0ECH6SoJdp-TIu6s8,4645
240
- mlrun/model_monitoring/db/tsdb/base.py,sha256=55lZfKmAWPW_Zi8DJhGib6euYhRhNxEpj528_rfh9Ww,26894
240
+ mlrun/model_monitoring/db/tsdb/base.py,sha256=mvV9S_adfKaAObzT2w6m4ko30UnRxPrh30eL0dshVyA,26914
241
241
  mlrun/model_monitoring/db/tsdb/helpers.py,sha256=0oUXc4aUkYtP2SGP6jTb3uPPKImIUsVsrb9otX9a7O4,1189
242
242
  mlrun/model_monitoring/db/tsdb/tdengine/__init__.py,sha256=vgBdsKaXUURKqIf3M0y4sRatmSVA4CQiJs7J5dcVBkQ,620
243
243
  mlrun/model_monitoring/db/tsdb/tdengine/schemas.py,sha256=EslhaR65jfeNdD5Ibk-3Hb4e5r5qYPfHb9rTChX3sG0,12689
244
244
  mlrun/model_monitoring/db/tsdb/tdengine/stream_graph_steps.py,sha256=Uadj0UvAmln2MxDWod-kAzau1uNlqZh981rPhbUH_5M,2857
245
- mlrun/model_monitoring/db/tsdb/tdengine/tdengine_connector.py,sha256=rpE-RB5sqe5GAkd9MZB4JFzSP1skxs0loC5hhAkNgKk,38747
245
+ mlrun/model_monitoring/db/tsdb/tdengine/tdengine_connection.py,sha256=8xo2O_yQrJGNDoYYB3Bwtdwwvzs3U9dT3BtPot0zENQ,6449
246
+ mlrun/model_monitoring/db/tsdb/tdengine/tdengine_connector.py,sha256=h0ZrNgOwTlBRd_DaYDc6eeVM9f_8CLJMUPEAIrZpbyU,37803
246
247
  mlrun/model_monitoring/db/tsdb/v3io/__init__.py,sha256=aL3bfmQsUQ-sbvKGdNihFj8gLCK3mSys0qDcXtYOwgc,616
247
248
  mlrun/model_monitoring/db/tsdb/v3io/stream_graph_steps.py,sha256=_-zo9relCDtjGgievxAcAP9gVN9nDWs8BzGtFwTjb9M,6284
248
- mlrun/model_monitoring/db/tsdb/v3io/v3io_connector.py,sha256=IzdThNwWMBWo0D0VzXV-WVvGg-z7Y9e8ke8_LYJTeVA,46214
249
+ mlrun/model_monitoring/db/tsdb/v3io/v3io_connector.py,sha256=7USfELnW2pwDhjbmFb0nmdqwq7glKfYt-HE7GxPlsEM,46777
249
250
  mlrun/model_monitoring/metrics/__init__.py,sha256=6CsTXAxeLbbf8yfCADTaxmiavqwrLEdYFJ-qc5kgDAY,569
250
251
  mlrun/model_monitoring/metrics/histogram_distance.py,sha256=E9_WIl2vd6qNvoHVHoFcnuQk3ekbFWOdi8aU7sHrfk4,4724
251
252
  mlrun/package/__init__.py,sha256=v7VDyK9kDOOuDvFo4oiGV2fx-vM1KL7fdN9pGLakhUQ,7008
@@ -270,7 +271,7 @@ mlrun/platforms/iguazio.py,sha256=6VBTq8eQ3mzT96tzjYhAtcMQ2VjF4x8LpIPW5DAcX2Q,13
270
271
  mlrun/projects/__init__.py,sha256=0Krf0WIKfnZa71WthYOg0SoaTodGg3sV_hK3f_OlTPI,1220
271
272
  mlrun/projects/operations.py,sha256=TzPbTYBgmYrjxTKP_wOtBJYFFFwDCQtaVvF1Snr0TfM,20029
272
273
  mlrun/projects/pipelines.py,sha256=wud7ezeEmhIJvfYE_wzQbA4ygEfGXHtbOtoOpan6poY,48556
273
- mlrun/projects/project.py,sha256=WsNZUz_k52llBI5rLBwJeGuIzSlAapVXBQfCL7NVI8E,235765
274
+ mlrun/projects/project.py,sha256=NVYJdUHEei2Hnqn4gNepr9rkZOJUOgIzDMMlgmtjvXc,236543
274
275
  mlrun/runtimes/__init__.py,sha256=J9Sy2HiyMlztNv6VUurMzF5H2XzttNil8nRsWDsqLyg,8923
275
276
  mlrun/runtimes/base.py,sha256=EL14Kmc1vWEjnBPJwLj5hHC6CtRAQHJLmohCD3sFEHo,37855
276
277
  mlrun/runtimes/daskjob.py,sha256=JwuGvOiPsxEDHHMMUS4Oie4hLlYYIZwihAl6DjroTY0,19521
@@ -292,7 +293,7 @@ mlrun/runtimes/mpijob/abstract.py,sha256=JGMjcJ4dvpJbctF6psU9UvYyNCutMxTMgBQeTlz
292
293
  mlrun/runtimes/mpijob/v1.py,sha256=1XQZC7AIMGX_AQCbApcwpH8I7y39-v0v2O35MvxjXoo,3213
293
294
  mlrun/runtimes/nuclio/__init__.py,sha256=gx1kizzKv8pGT5TNloN1js1hdbxqDw3rM90sLVYVffY,794
294
295
  mlrun/runtimes/nuclio/api_gateway.py,sha256=vH9ClKVP4Mb24rvA67xPuAvAhX-gAv6vVtjVxyplhdc,26969
295
- mlrun/runtimes/nuclio/function.py,sha256=8wzAFYCpSs0KoGPSN6DC19smSfYh8dVqDUhpicr8sJ0,54540
296
+ mlrun/runtimes/nuclio/function.py,sha256=mJ719djvzin7ee9QKoD-DIItuOUvTgrDHhzHgr1Q5zI,54541
296
297
  mlrun/runtimes/nuclio/nuclio.py,sha256=sLK8KdGO1LbftlL3HqPZlFOFTAAuxJACZCVl1c0Ha6E,2942
297
298
  mlrun/runtimes/nuclio/serving.py,sha256=d0nzPALUYXO4fKFFhxW3hY-_NU-ZhBLWXa2vWIetBRI,33434
298
299
  mlrun/runtimes/nuclio/application/__init__.py,sha256=rRs5vasy_G9IyoTpYIjYDafGoL6ifFBKgBtsXn31Atw,614
@@ -306,7 +307,7 @@ mlrun/serving/remote.py,sha256=gxJkj_J3j-sZcVUbUzbAmJafP6t6y4NVFsu0kWmYngA,18818
306
307
  mlrun/serving/routers.py,sha256=SY6AsaiSnh8ssXq8hQE2z9MYapOxFOFJBx9QomiZMO8,53915
307
308
  mlrun/serving/server.py,sha256=KiNhW0nTV5STZPzR6kEAUFVzCCAX8qv0g9AoCopARrM,23429
308
309
  mlrun/serving/serving_wrapper.py,sha256=R670-S6PX_d5ER6jiHtRvacuPyFzQH0mEf2K0sBIIOM,836
309
- mlrun/serving/states.py,sha256=Hh3FBoQbHoO4KiofHfSwi_aUx7mQ26iXpKijcGiDJ6c,73341
310
+ mlrun/serving/states.py,sha256=PaVdgZ8GyE8bxr_-RvuSUINwHuPypJmqaQs27aEPweo,73367
310
311
  mlrun/serving/utils.py,sha256=k2EIYDWHUGkE-IBI6T0UNT32fw-KySsccIJM_LObI00,4171
311
312
  mlrun/serving/v1_serving.py,sha256=c6J_MtpE-Tqu00-6r4eJOCO6rUasHDal9W2eBIcrl50,11853
312
313
  mlrun/serving/v2_serving.py,sha256=b3C5Utv2_AOPrH_hPi3NarjNbAK3kRoeIfqMU4qNuUo,25362
@@ -338,13 +339,13 @@ mlrun/utils/notifications/notification/git.py,sha256=t2lqRrPRBO4awf_uhxJreH9Cpcb
338
339
  mlrun/utils/notifications/notification/ipython.py,sha256=9uZvI1uOLFaNuAsfJPXmL3l6dOzFoWdBK5GYNYFAfks,2282
339
340
  mlrun/utils/notifications/notification/mail.py,sha256=ZyJ3eqd8simxffQmXzqd3bgbAqp1vij7C6aRJ9h2mgs,6012
340
341
  mlrun/utils/notifications/notification/slack.py,sha256=eQvmctTh6wIG5xVOesLLV9S1-UUCu5UEQ9JIJOor3ts,7183
341
- mlrun/utils/notifications/notification/webhook.py,sha256=NeyIMSBojjjTJaUHmPbxMByp34GxYkl1-16NqzU27fU,4943
342
+ mlrun/utils/notifications/notification/webhook.py,sha256=zxh8CAlbPnTazsk6r05X5TKwqUZVOH5KBU2fJbzQlG4,5330
342
343
  mlrun/utils/version/__init__.py,sha256=7kkrB7hEZ3cLXoWj1kPoDwo4MaswsI2JVOBpbKgPAgc,614
343
- mlrun/utils/version/version.json,sha256=tuXJq2nSzgMkR_1BOzctty9vrj-bvCoa4ec-YhoGWco,88
344
+ mlrun/utils/version/version.json,sha256=FWbZ7M4qsgWn3DG-fqtofJ0dIpahf_LNjaAXvMs_PE8,88
344
345
  mlrun/utils/version/version.py,sha256=eEW0tqIAkU9Xifxv8Z9_qsYnNhn3YH7NRAfM-pPLt1g,1878
345
- mlrun-1.9.0rc2.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
346
- mlrun-1.9.0rc2.dist-info/METADATA,sha256=pkNMIypdTNvy1-_p1nJ_KsfFG2DbtD5mRNA0BpuMM-U,25916
347
- mlrun-1.9.0rc2.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
348
- mlrun-1.9.0rc2.dist-info/entry_points.txt,sha256=1Owd16eAclD5pfRCoJpYC2ZJSyGNTtUr0nCELMioMmU,46
349
- mlrun-1.9.0rc2.dist-info/top_level.txt,sha256=NObLzw3maSF9wVrgSeYBv-fgnHkAJ1kEkh12DLdd5KM,6
350
- mlrun-1.9.0rc2.dist-info/RECORD,,
346
+ mlrun-1.9.0rc4.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
347
+ mlrun-1.9.0rc4.dist-info/METADATA,sha256=SWQdOG5QHseA3co1P5RRcPnSOrapdPSHcMS9MJMQuJo,25700
348
+ mlrun-1.9.0rc4.dist-info/WHEEL,sha256=0CuiUZ_p9E4cD6NyLD6UG80LBXYyiSYZOKDm5lp32xk,91
349
+ mlrun-1.9.0rc4.dist-info/entry_points.txt,sha256=1Owd16eAclD5pfRCoJpYC2ZJSyGNTtUr0nCELMioMmU,46
350
+ mlrun-1.9.0rc4.dist-info/top_level.txt,sha256=NObLzw3maSF9wVrgSeYBv-fgnHkAJ1kEkh12DLdd5KM,6
351
+ mlrun-1.9.0rc4.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (78.1.0)
2
+ Generator: setuptools (80.3.1)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5