mlrun 1.8.0rc44__py3-none-any.whl → 1.8.0rc45__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/config.py CHANGED
@@ -549,6 +549,10 @@ default_config = {
549
549
  },
550
550
  },
551
551
  "model_endpoint_monitoring": {
552
+ # Scaling Rule
553
+ # The fundamental scaling rule to maintain is: Shards/Partitions = Replicas * Workers
554
+ # In other words, the number of shards (V3IO) or partitions (Kafka) must be equal to the
555
+ # total number of worker processes across all pods.
552
556
  "serving_stream": {
553
557
  "v3io": {
554
558
  "shard_count": 2,
@@ -822,6 +826,8 @@ default_config = {
822
826
  # maximum allowed alert config cache size in alert's CRUD
823
827
  # for the best performance, it is recommended to set this value to the maximum number of alerts
824
828
  "max_allowed_cache_size": 20000,
829
+ # default limit for listing alert configs
830
+ "default_list_alert_configs_limit": 2000,
825
831
  },
826
832
  "auth_with_client_id": {
827
833
  "enabled": False,
mlrun/db/base.py CHANGED
@@ -889,7 +889,9 @@ class RunDBInterface(ABC):
889
889
  pass
890
890
 
891
891
  @abstractmethod
892
- def list_alerts_configs(self, project=""):
892
+ def list_alerts_configs(
893
+ self, project="", limit: Optional[int] = None, offset: Optional[int] = None
894
+ ):
893
895
  pass
894
896
 
895
897
  @abstractmethod
@@ -1105,12 +1107,6 @@ class RunDBInterface(ABC):
1105
1107
  ) -> bool:
1106
1108
  pass
1107
1109
 
1108
- @abstractmethod
1109
- def deploy_histogram_data_drift_app(
1110
- self, project: str, image: str = "mlrun/mlrun"
1111
- ) -> None:
1112
- pass
1113
-
1114
1110
  @abstractmethod
1115
1111
  def set_model_monitoring_credentials(
1116
1112
  self,
mlrun/db/httpdb.py CHANGED
@@ -4080,21 +4080,6 @@ class HTTPRunDB(RunDBInterface):
4080
4080
  deletion_failed = True
4081
4081
  return not deletion_failed
4082
4082
 
4083
- def deploy_histogram_data_drift_app(
4084
- self, project: str, image: str = "mlrun/mlrun"
4085
- ) -> None:
4086
- """
4087
- Deploy the histogram data drift application.
4088
-
4089
- :param project: Project name.
4090
- :param image: The image on which the application will run.
4091
- """
4092
- self.api_call(
4093
- method=mlrun.common.types.HTTPMethod.PUT,
4094
- path=f"projects/{project}/model-monitoring/histogram-data-drift-app",
4095
- params={"image": image},
4096
- )
4097
-
4098
4083
  def set_model_monitoring_credentials(
4099
4084
  self,
4100
4085
  project: str,
@@ -4818,20 +4803,33 @@ class HTTPRunDB(RunDBInterface):
4818
4803
  response = self.api_call("GET", endpoint_path, error_message)
4819
4804
  return AlertConfig.from_dict(response.json())
4820
4805
 
4821
- def list_alerts_configs(self, project="") -> list[AlertConfig]:
4806
+ def list_alerts_configs(
4807
+ self, project="", limit: Optional[int] = None, offset: Optional[int] = None
4808
+ ) -> list[AlertConfig]:
4822
4809
  """
4823
4810
  Retrieve list of alerts of a project.
4824
4811
 
4825
4812
  :param project: The project name.
4813
+ :param limit: The maximum number of alerts to return.
4814
+ Defaults to `mlconf.alerts.default_list_alert_configs_limit` if not provided.
4815
+ :param offset: The number of alerts to skip.
4826
4816
 
4827
4817
  :returns: All the alerts objects of the project.
4828
4818
  """
4829
4819
  project = project or config.default_project
4830
4820
  endpoint_path = f"projects/{project}/alerts"
4831
4821
  error_message = f"get alerts {project}/alerts"
4832
- response = self.api_call("GET", endpoint_path, error_message).json()
4822
+ params = {}
4823
+ # TODO: Deprecate limit and offset when pagination is implemented
4824
+ if limit:
4825
+ params["page-size"] = limit
4826
+ if offset:
4827
+ params["offset"] = offset
4828
+ response = self.api_call(
4829
+ "GET", endpoint_path, error_message, params=params
4830
+ ).json()
4833
4831
  results = []
4834
- for item in response:
4832
+ for item in response.get("alerts", []):
4835
4833
  results.append(AlertConfig(**item))
4836
4834
  return results
4837
4835
 
mlrun/db/nopdb.py CHANGED
@@ -883,11 +883,6 @@ class NopDB(RunDBInterface):
883
883
  ) -> bool:
884
884
  pass
885
885
 
886
- def deploy_histogram_data_drift_app(
887
- self, project: str, image: str = "mlrun/mlrun"
888
- ) -> None:
889
- pass
890
-
891
886
  def set_model_monitoring_credentials(
892
887
  self,
893
888
  project: str,
@@ -107,16 +107,14 @@ class HistogramDataDriftApplication(ModelMonitoringApplicationBase):
107
107
  * JSON with the general drift value per feature, produced by default.
108
108
  * Plotly table with the various metrics and histograms per feature (disabled by default due to performance issues).
109
109
 
110
- This application is deployed by default when calling:
111
-
112
- .. code-block:: python
113
-
114
- project.enable_model_monitoring()
115
-
110
+ This application is deployed by default when calling
111
+ :py:func:`~mlrun.projects.MlrunProject.enable_model_monitoring`.
116
112
  To avoid it, pass :code:`deploy_histogram_data_drift_app=False`.
117
113
 
118
114
  If you want to change the application defaults, such as the classifier or which artifacts to produce, you
119
115
  need to inherit from this class and deploy it as any other model monitoring application.
116
+ Please make sure to keep the default application name. This ensures that the full functionality of the application,
117
+ including the statistics view in the UI, is available.
120
118
  """
121
119
 
122
120
  NAME: Final[str] = HistogramDataDriftApplicationConstants.NAME
@@ -140,8 +138,8 @@ class HistogramDataDriftApplication(ModelMonitoringApplicationBase):
140
138
  produce_plotly_artifact: bool = False,
141
139
  ) -> None:
142
140
  """
143
- :param value_classifier: Classifier object that adheres to the `ValueClassifier` protocol.
144
- If not provided, the default `DataDriftClassifier()` is used.
141
+ :param value_classifier: Classifier object that adheres to the :py:class:`~ValueClassifier` protocol.
142
+ If not provided, the default :py:class:`~DataDriftClassifier` is used.
145
143
  """
146
144
  self._value_classifier = value_classifier or DataDriftClassifier()
147
145
  assert self._REQUIRED_METRICS <= set(
@@ -181,10 +179,7 @@ class HistogramDataDriftApplication(ModelMonitoringApplicationBase):
181
179
  return metrics_per_feature
182
180
 
183
181
  def _get_general_drift_result(
184
- self,
185
- metrics: list[mm_results.ModelMonitoringApplicationMetric],
186
- monitoring_context: mm_context.MonitoringApplicationContext,
187
- metrics_per_feature: DataFrame,
182
+ self, metrics: list[mm_results.ModelMonitoringApplicationMetric]
188
183
  ) -> mm_results.ModelMonitoringApplicationResult:
189
184
  """Get the general drift result from the metrics list"""
190
185
  value = cast(
@@ -237,7 +232,8 @@ class HistogramDataDriftApplication(ModelMonitoringApplicationBase):
237
232
  monitoring_context: mm_context.MonitoringApplicationContext,
238
233
  ) -> list[mm_results._ModelMonitoringApplicationStats]:
239
234
  """
240
- list the application calculated stats
235
+ Return a list of the statistics.
236
+
241
237
  :param metrics: the calculated metrics
242
238
  :param metrics_per_feature: metric calculated per feature
243
239
  :param monitoring_context: context object for current monitoring application
@@ -376,11 +372,7 @@ class HistogramDataDriftApplication(ModelMonitoringApplicationBase):
376
372
  )
377
373
  monitoring_context.logger.debug("Computing average per metric")
378
374
  metrics = self._get_metrics(metrics_per_feature)
379
- result = self._get_general_drift_result(
380
- metrics=metrics,
381
- monitoring_context=monitoring_context,
382
- metrics_per_feature=metrics_per_feature,
383
- )
375
+ result = self._get_general_drift_result(metrics=metrics)
384
376
  stats = self._get_stats(
385
377
  metrics=metrics,
386
378
  monitoring_context=monitoring_context,
@@ -33,7 +33,12 @@ _TSDB_BE = "tsdb"
33
33
  _TSDB_RATE = "1/s"
34
34
  _CONTAINER = "users"
35
35
 
36
- V3IO_MEPS_LIMIT = 200
36
+ V3IO_FRAMESD_MEPS_LIMIT = (
37
+ 200 # Maximum number of model endpoints per single request when using V3IO Frames
38
+ )
39
+ V3IO_CLIENT_MEPS_LIMIT = (
40
+ 150 # Maximum number of model endpoints per single request when using V3IO Client
41
+ )
37
42
 
38
43
 
39
44
  def _is_no_schema_error(exc: v3io_frames.Error) -> bool:
@@ -475,8 +480,8 @@ class V3IOTSDBConnector(TSDBConnector):
475
480
  tables = mm_schemas.V3IOTSDBTables.list()
476
481
 
477
482
  # Split the endpoint ids into chunks to avoid exceeding the v3io-engine filter-expression limit
478
- for i in range(0, len(endpoint_ids), V3IO_MEPS_LIMIT):
479
- endpoint_id_chunk = endpoint_ids[i : i + V3IO_MEPS_LIMIT]
483
+ for i in range(0, len(endpoint_ids), V3IO_FRAMESD_MEPS_LIMIT):
484
+ endpoint_id_chunk = endpoint_ids[i : i + V3IO_FRAMESD_MEPS_LIMIT]
480
485
  filter_query = f"endpoint_id IN({str(endpoint_id_chunk)[1:-1]}) "
481
486
  for table in tables:
482
487
  try:
@@ -684,11 +689,11 @@ class V3IOTSDBConnector(TSDBConnector):
684
689
  if isinstance(endpoint_id, str):
685
690
  return f"endpoint_id=='{endpoint_id}'"
686
691
  elif isinstance(endpoint_id, list):
687
- if len(endpoint_id) > V3IO_MEPS_LIMIT:
692
+ if len(endpoint_id) > V3IO_FRAMESD_MEPS_LIMIT:
688
693
  logger.info(
689
694
  "The number of endpoint ids exceeds the v3io-engine filter-expression limit, "
690
695
  "retrieving all the model endpoints from the db.",
691
- limit=V3IO_MEPS_LIMIT,
696
+ limit=V3IO_FRAMESD_MEPS_LIMIT,
692
697
  amount=len(endpoint_id),
693
698
  )
694
699
  return None
@@ -880,23 +885,41 @@ class V3IOTSDBConnector(TSDBConnector):
880
885
  start: Optional[datetime] = None,
881
886
  end: Optional[datetime] = None,
882
887
  ) -> dict[str, float]:
883
- if isinstance(endpoint_ids, str):
884
- filter_expression = f"__name=='{endpoint_ids}'"
885
- else:
886
- filter_expression = " OR ".join(
887
- [f"__name=='{endpoint_id}'" for endpoint_id in endpoint_ids]
888
- )
889
-
890
888
  # Get the last request timestamp for each endpoint from the KV table.
891
889
  # The result of the query is a list of dictionaries,
892
890
  # each dictionary contains the endpoint id and the last request timestamp.
891
+ last_request_timestamps = {}
892
+ if isinstance(endpoint_ids, str):
893
+ endpoint_ids = [endpoint_ids]
893
894
 
894
895
  try:
895
- res = self.v3io_client.kv.new_cursor(
896
- container=self.container,
897
- table_path=self.last_request_table,
898
- filter_expression=filter_expression,
899
- ).all()
896
+ if len(endpoint_ids) > V3IO_CLIENT_MEPS_LIMIT:
897
+ logger.warning(
898
+ "The number of endpoint ids exceeds the v3io-engine filter-expression limit, "
899
+ "retrieving last request for all the model endpoints from the KV table.",
900
+ limit=V3IO_CLIENT_MEPS_LIMIT,
901
+ amount=len(endpoint_ids),
902
+ )
903
+
904
+ res = self.v3io_client.kv.new_cursor(
905
+ container=self.container,
906
+ table_path=self.last_request_table,
907
+ ).all()
908
+ last_request_timestamps.update(
909
+ {d["__name"]: d["last_request_timestamp"] for d in res}
910
+ )
911
+ else:
912
+ filter_expression = " OR ".join(
913
+ [f"__name=='{endpoint_id}'" for endpoint_id in endpoint_ids]
914
+ )
915
+ res = self.v3io_client.kv.new_cursor(
916
+ container=self.container,
917
+ table_path=self.last_request_table,
918
+ filter_expression=filter_expression,
919
+ ).all()
920
+ last_request_timestamps.update(
921
+ {d["__name"]: d["last_request_timestamp"] for d in res}
922
+ )
900
923
  except Exception as e:
901
924
  logger.warning(
902
925
  "Failed to get last request timestamp from V3IO KV table.",
@@ -904,9 +927,8 @@ class V3IOTSDBConnector(TSDBConnector):
904
927
  project=self.project,
905
928
  table=self.last_request_table,
906
929
  )
907
- return {}
908
930
 
909
- return {d["__name"]: d["last_request_timestamp"] for d in res}
931
+ return last_request_timestamps
910
932
 
911
933
  def get_drift_status(
912
934
  self,
@@ -1131,4 +1153,8 @@ class V3IOTSDBConnector(TSDBConnector):
1131
1153
  endpoint_ids=list(model_endpoint_objects_by_uid.keys())
1132
1154
  )
1133
1155
  for uid, mep in model_endpoint_objects_by_uid.items():
1134
- mep.status.last_request = last_request_dictionary.get(uid)
1156
+ # Set the last request timestamp to the MEP object. If not found, keep the existing value from the
1157
+ # DB (relevant for batch EP).
1158
+ mep.status.last_request = last_request_dictionary.get(
1159
+ uid, mep.status.last_request
1160
+ )
@@ -180,7 +180,7 @@ class ModelMonitoringWriter(StepToDict):
180
180
  data, timestamp
181
181
  )
182
182
  logger.info(
183
- "Updating the model endpoint statistics",
183
+ "Updated the model endpoint statistics",
184
184
  endpoint_id=endpoint_id,
185
185
  stats_kind=stat_kind,
186
186
  )
mlrun/projects/project.py CHANGED
@@ -2451,7 +2451,22 @@ class MlrunProject(ModelObj):
2451
2451
  :param image: The image of the model monitoring controller, writer, monitoring
2452
2452
  stream & histogram data drift functions, which are real time nuclio
2453
2453
  functions. By default, the image is mlrun/mlrun.
2454
- :param deploy_histogram_data_drift_app: If true, deploy the default histogram-based data drift application.
2454
+ :param deploy_histogram_data_drift_app: If true, deploy the default histogram-based data drift application:
2455
+ :py:class:`~mlrun.model_monitoring.applications.histogram_data_drift.HistogramDataDriftApplication`.
2456
+ If false, and you want to deploy the histogram data drift application
2457
+ afterwards, you may use the
2458
+ :py:func:`~set_model_monitoring_function` method::
2459
+
2460
+ import mlrun.model_monitoring.applications.histogram_data_drift as histogram_data_drift
2461
+
2462
+ hist_app = project.set_model_monitoring_function(
2463
+ name=histogram_data_drift.HistogramDataDriftApplicationConstants.NAME, # keep the default name
2464
+ func=histogram_data_drift.__file__,
2465
+ application_class=histogram_data_drift.HistogramDataDriftApplication.__name__,
2466
+ )
2467
+
2468
+ project.deploy_function(hist_app)
2469
+
2455
2470
  :param wait_for_deployment: If true, return only after the deployment is done on the backend.
2456
2471
  Otherwise, deploy the model monitoring infrastructure on the
2457
2472
  background, including the histogram data drift app if selected.
@@ -2488,30 +2503,6 @@ class MlrunProject(ModelObj):
2488
2503
  )
2489
2504
  self._wait_for_functions_deployment(deployment_functions)
2490
2505
 
2491
- def deploy_histogram_data_drift_app(
2492
- self,
2493
- *,
2494
- image: str = "mlrun/mlrun",
2495
- db: Optional[mlrun.db.RunDBInterface] = None,
2496
- wait_for_deployment: bool = False,
2497
- ) -> None:
2498
- """
2499
- Deploy the histogram data drift application.
2500
-
2501
- :param image: The image on which the application will run.
2502
- :param db: An optional DB object.
2503
- :param wait_for_deployment: If true, return only after the deployment is done on the backend.
2504
- Otherwise, deploy the application on the background.
2505
- """
2506
- if db is None:
2507
- db = mlrun.db.get_run_db(secrets=self._secrets)
2508
- db.deploy_histogram_data_drift_app(project=self.name, image=image)
2509
-
2510
- if wait_for_deployment:
2511
- self._wait_for_functions_deployment(
2512
- [mm_constants.HistogramDataDriftApplicationConstants.NAME]
2513
- )
2514
-
2515
2506
  def update_model_monitoring_controller(
2516
2507
  self,
2517
2508
  base_period: int = 10,
@@ -5034,14 +5025,20 @@ class MlrunProject(ModelObj):
5034
5025
  db = mlrun.db.get_run_db(secrets=self._secrets)
5035
5026
  return db.get_alert_config(alert_name, self.metadata.name)
5036
5027
 
5037
- def list_alerts_configs(self) -> list[AlertConfig]:
5028
+ def list_alerts_configs(
5029
+ self, limit: Optional[int] = None, offset: Optional[int] = None
5030
+ ) -> list[AlertConfig]:
5038
5031
  """
5039
5032
  Retrieve list of alerts of a project.
5040
5033
 
5034
+ :param limit: The maximum number of alerts to return.
5035
+ Defaults to `mlconf.alerts.default_list_alert_configs_limit` if not provided.
5036
+ :param offset: The number of alerts to skip before starting to collect alerts.
5037
+
5041
5038
  :return: All the alerts objects of the project.
5042
5039
  """
5043
5040
  db = mlrun.db.get_run_db(secrets=self._secrets)
5044
- return db.list_alerts_configs(self.metadata.name)
5041
+ return db.list_alerts_configs(self.metadata.name, limit=limit, offset=offset)
5045
5042
 
5046
5043
  def delete_alert_config(
5047
5044
  self, alert_data: AlertConfig = None, alert_name: Optional[str] = None
@@ -4,7 +4,7 @@
4
4
  // you may not use this file except in compliance with the License.
5
5
  // You may obtain a copy of the License at
6
6
  //
7
- // http://www.apache.org/licenses/LICENSE-2.0
7
+ // http://www.apache.org/licenses/LICENSE-2.0
8
8
  //
9
9
  // Unless required by applicable law or agreed to in writing, software
10
10
  // distributed under the License is distributed on an "AS IS" BASIS,
@@ -14,82 +14,84 @@
14
14
  package main
15
15
 
16
16
  import (
17
- "bytes"
18
- "fmt"
19
- "net/http"
20
- "net/http/httptest"
21
- "net/http/httputil"
22
- "net/url"
23
- "os"
24
- "strings"
17
+ "bytes"
18
+ "fmt"
19
+ "net/http"
20
+ "net/http/httptest"
21
+ "net/http/httputil"
22
+ "net/url"
23
+ "os"
24
+ "strings"
25
25
 
26
- nuclio "github.com/nuclio/nuclio-sdk-go"
26
+ nuclio "github.com/nuclio/nuclio-sdk-go"
27
27
  )
28
28
 
29
29
  func Handler(context *nuclio.Context, event nuclio.Event) (interface{}, error) {
30
- reverseProxy := context.UserData.(map[string]interface{})["reverseProxy"].(*httputil.ReverseProxy)
31
- sidecarUrl := context.UserData.(map[string]interface{})["server"].(string)
30
+ reverseProxy := context.UserData.(map[string]interface{})["reverseProxy"].(*httputil.ReverseProxy)
31
+ sidecarUrl := context.UserData.(map[string]interface{})["server"].(string)
32
32
 
33
- // populate reverse proxy http request
34
- httpRequest, err := http.NewRequest(event.GetMethod(), event.GetPath(), bytes.NewReader(event.GetBody()))
35
- if err != nil {
36
- context.Logger.ErrorWith("Failed to create a reverse proxy request")
37
- return nil, err
38
- }
39
- for k, v := range event.GetHeaders() {
40
- httpRequest.Header[k] = []string{v.(string)}
41
- }
33
+ // populate reverse proxy http request
34
+ httpRequest, err := http.NewRequest(event.GetMethod(), event.GetPath(), bytes.NewReader(event.GetBody()))
35
+ if err != nil {
36
+ context.Logger.ErrorWith("Failed to create a reverse proxy request")
37
+ return nil, err
38
+ }
39
+ for k, v := range event.GetHeaders() {
40
+ httpRequest.Header[k] = []string{v.(string)}
41
+ }
42
42
 
43
- // populate query params
44
- query := httpRequest.URL.Query()
45
- for k, v := range event.GetFields() {
46
- query.Set(k, v.(string))
47
- }
48
- httpRequest.URL.RawQuery = query.Encode()
43
+ // populate query params
44
+ query := httpRequest.URL.Query()
45
+ for k, v := range event.GetFields() {
46
+ query.Set(k, v.(string))
47
+ }
48
+ httpRequest.URL.RawQuery = query.Encode()
49
49
 
50
- recorder := httptest.NewRecorder()
51
- reverseProxy.ServeHTTP(recorder, httpRequest)
50
+ recorder := httptest.NewRecorder()
51
+ reverseProxy.ServeHTTP(recorder, httpRequest)
52
52
 
53
- // send request to sidecar
54
- context.Logger.DebugWith("Forwarding request to sidecar", "sidecarUrl", sidecarUrl, "query", httpRequest.URL.Query())
55
- response := recorder.Result()
53
+ // send request to sidecar
54
+ context.Logger.DebugWith("Forwarding request to sidecar",
55
+ "sidecarUrl", sidecarUrl,
56
+ "method", event.GetMethod())
57
+ response := recorder.Result()
56
58
 
57
- headers := make(map[string]interface{})
58
- for key, value := range response.Header {
59
- headers[key] = value[0]
60
- }
59
+ headers := make(map[string]interface{})
60
+ for key, value := range response.Header {
61
+ headers[key] = value[0]
62
+ }
61
63
 
62
- // let the processor calculate the content length
63
- delete(headers, "Content-Length")
64
- return nuclio.Response{
65
- StatusCode: response.StatusCode,
66
- Body: recorder.Body.Bytes(),
67
- ContentType: response.Header.Get("Content-Type"),
68
- Headers: headers,
69
- }, nil
64
+ // let the processor calculate the content length
65
+ delete(headers, "Content-Length")
66
+ return nuclio.Response{
67
+ StatusCode: response.StatusCode,
68
+ Body: recorder.Body.Bytes(),
69
+ ContentType: response.Header.Get("Content-Type"),
70
+ Headers: headers,
71
+ }, nil
70
72
  }
71
73
 
72
74
  func InitContext(context *nuclio.Context) error {
73
- sidecarHost := os.Getenv("SIDECAR_HOST")
74
- sidecarPort := os.Getenv("SIDECAR_PORT")
75
- if sidecarHost == "" {
76
- sidecarHost = "http://localhost"
77
- } else if !strings.Contains(sidecarHost, "://") {
78
- sidecarHost = fmt.Sprintf("http://%s", sidecarHost)
79
- }
75
+ sidecarHost := os.Getenv("SIDECAR_HOST")
76
+ sidecarPort := os.Getenv("SIDECAR_PORT")
77
+ if sidecarHost == "" {
78
+ sidecarHost = "http://localhost"
79
+ } else if !strings.Contains(sidecarHost, "://") {
80
+ sidecarHost = fmt.Sprintf("http://%s", sidecarHost)
81
+ }
80
82
 
81
- // url for request forwarding
82
- sidecarUrl := fmt.Sprintf("%s:%s", sidecarHost, sidecarPort)
83
- parsedURL, err := url.Parse(sidecarUrl)
84
- if err != nil {
85
- context.Logger.ErrorWith("Failed to parse sidecar url", "sidecarUrl", sidecarUrl)
86
- return err
87
- }
88
- reverseProxy := httputil.NewSingleHostReverseProxy(parsedURL)
83
+ // url for request forwarding
84
+ sidecarUrl := fmt.Sprintf("%s:%s", sidecarHost, sidecarPort)
85
+ parsedURL, err := url.Parse(sidecarUrl)
86
+ if err != nil {
87
+ context.Logger.ErrorWith("Failed to parse sidecar url", "sidecarUrl", sidecarUrl)
88
+ return err
89
+ }
90
+ reverseProxy := httputil.NewSingleHostReverseProxy(parsedURL)
89
91
 
90
- context.UserData = map[string]interface{}{
91
- "server": sidecarUrl,
92
- "reverseProxy": reverseProxy,
93
- }
94
- return nil
92
+ context.UserData = map[string]interface{}{
93
+ "server": sidecarUrl,
94
+ "reverseProxy": reverseProxy,
95
+ }
96
+ return nil
95
97
  }
@@ -1,4 +1,4 @@
1
1
  {
2
- "git_commit": "636cd70a5d3e77937a343927a8fe4bc5c24d0a58",
3
- "version": "1.8.0-rc44"
2
+ "git_commit": "b434e35c26bb66407a60bedddb7a9af71141902b",
3
+ "version": "1.8.0-rc45"
4
4
  }
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.2
1
+ Metadata-Version: 2.4
2
2
  Name: mlrun
3
- Version: 1.8.0rc44
3
+ Version: 1.8.0rc45
4
4
  Summary: Tracking and config of machine learning runs
5
5
  Home-page: https://github.com/mlrun/mlrun
6
6
  Author: Yaron Haviv
@@ -240,6 +240,7 @@ Dynamic: description-content-type
240
240
  Dynamic: home-page
241
241
  Dynamic: keywords
242
242
  Dynamic: license
243
+ Dynamic: license-file
243
244
  Dynamic: provides-extra
244
245
  Dynamic: requires-dist
245
246
  Dynamic: requires-python
@@ -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=5b3y_cZIYRl_OTZ1CR7bcwDu1dHKbeAuP2nup88pLjI,71446
3
+ mlrun/config.py,sha256=JEE29XflgA8NsdAOeSmIFBKhS_r-FKHUFwMjcSOYq30,71820
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
@@ -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=U77W97LMeVGRmXHH_gafZE95TiFLcI27HJVkAmLTPaQ,30788
111
+ mlrun/db/base.py,sha256=Uo28PyTRkauFLGHZPF6IkDbF-WyEA03GObC3su87Pr8,30716
112
112
  mlrun/db/factory.py,sha256=yP2vVmveUE7LYTCHbS6lQIxP9rW--zdISWuPd_I3d_4,2111
113
- mlrun/db/httpdb.py,sha256=O1PCDOfax3YdwAlYKj-nALcBVTBM9EHWQyhQwNlJS44,231559
114
- mlrun/db/nopdb.py,sha256=kjvoaWWc4OmQ7AdQKomtRzviJy1_dK3jdMCJNkic34o,27223
113
+ mlrun/db/httpdb.py,sha256=l4qdr7MWfLHuq3gV5fHQspLbAxXbJinGlN0kO-sqftA,231598
114
+ mlrun/db/nopdb.py,sha256=TwyU1B6Z4S6n5iu6pftxRqimhvroz1PnPwFhAoXxr4c,27098
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
@@ -224,12 +224,12 @@ mlrun/model_monitoring/features_drift_table.py,sha256=c6GpKtpOJbuT1u5uMWDL_S-6N4
224
224
  mlrun/model_monitoring/helpers.py,sha256=Q4vcc7x41lCJdFQIE8UFPY0WIQ8a-4tSGhziMA4ib4w,22003
225
225
  mlrun/model_monitoring/stream_processing.py,sha256=4M0H4txMlsC2Q5iKTPp992KWoNPAJjPHj9rqWhXbl8w,33321
226
226
  mlrun/model_monitoring/tracking_policy.py,sha256=PBIGrUYWrwcE5gwXupBIVzOb0QRRwPJsgQm_yLGQxB4,5595
227
- mlrun/model_monitoring/writer.py,sha256=vbL7bqTyNu8q4bNcebX72sUMybVDAoTWg-CXq4fov3Y,8429
227
+ mlrun/model_monitoring/writer.py,sha256=ibbhvfSHb8Reqlb7RGFEAUNM4iTyK1gk8-2m46mP6VM,8428
228
228
  mlrun/model_monitoring/applications/__init__.py,sha256=xDBxkBjl-whHSG_4t1mLkxiypLH-fzn8TmAW9Mjo2uI,759
229
229
  mlrun/model_monitoring/applications/_application_steps.py,sha256=PxULZznKW66Oq-fKaraOAbsTuGnV0zgXh6_91wX3KUo,8367
230
230
  mlrun/model_monitoring/applications/base.py,sha256=7XL12idItWkoE3CJ_48F6cwVx5pJH3bgfG92hb8LcN8,24872
231
231
  mlrun/model_monitoring/applications/context.py,sha256=Wou9lviSETjEqyMoIAi0Ko58luRkx0uy3ZDUVyRheNA,16144
232
- mlrun/model_monitoring/applications/histogram_data_drift.py,sha256=RnrSRkNM5WYOjhiEIdkmYmUDGNnuRL8xtV-CpJ83r1U,15233
232
+ mlrun/model_monitoring/applications/histogram_data_drift.py,sha256=09t0tfC35W0SeJA3fzN29pJiB6G-V_8GlcvULVq6H9Q,15179
233
233
  mlrun/model_monitoring/applications/results.py,sha256=_qmj6TWT0SR2bi7gUyRKBU418eGgGoLW2_hTJ7S-ock,5782
234
234
  mlrun/model_monitoring/applications/evidently/__init__.py,sha256=-DqdPnBSrjZhFvKOu_Ie3MiFvlur9sPTZpZ1u0_1AE8,690
235
235
  mlrun/model_monitoring/applications/evidently/base.py,sha256=C8402vQJH7jmY-i49DnYjy6p6dETWex4Tdi8ylFLecA,5097
@@ -245,7 +245,7 @@ mlrun/model_monitoring/db/tsdb/tdengine/stream_graph_steps.py,sha256=Uadj0UvAmln
245
245
  mlrun/model_monitoring/db/tsdb/tdengine/tdengine_connector.py,sha256=gDK6nNbAwTprs2UAI1r7r6loZB40I_8iQ2JvedvAs78,37765
246
246
  mlrun/model_monitoring/db/tsdb/v3io/__init__.py,sha256=aL3bfmQsUQ-sbvKGdNihFj8gLCK3mSys0qDcXtYOwgc,616
247
247
  mlrun/model_monitoring/db/tsdb/v3io/stream_graph_steps.py,sha256=_-zo9relCDtjGgievxAcAP9gVN9nDWs8BzGtFwTjb9M,6284
248
- mlrun/model_monitoring/db/tsdb/v3io/v3io_connector.py,sha256=4jpHjG_xV6RePyrw2Xg_Y1netMorMDeZHPtU_2YZlog,44719
248
+ mlrun/model_monitoring/db/tsdb/v3io/v3io_connector.py,sha256=GLxg8N1eK7agKgPanOoA1JNbXEH9_kesNRzAPYOgtAQ,46033
249
249
  mlrun/model_monitoring/metrics/__init__.py,sha256=6CsTXAxeLbbf8yfCADTaxmiavqwrLEdYFJ-qc5kgDAY,569
250
250
  mlrun/model_monitoring/metrics/histogram_distance.py,sha256=E9_WIl2vd6qNvoHVHoFcnuQk3ekbFWOdi8aU7sHrfk4,4724
251
251
  mlrun/package/__init__.py,sha256=v7VDyK9kDOOuDvFo4oiGV2fx-vM1KL7fdN9pGLakhUQ,7008
@@ -270,7 +270,7 @@ mlrun/platforms/iguazio.py,sha256=6VBTq8eQ3mzT96tzjYhAtcMQ2VjF4x8LpIPW5DAcX2Q,13
270
270
  mlrun/projects/__init__.py,sha256=0Krf0WIKfnZa71WthYOg0SoaTodGg3sV_hK3f_OlTPI,1220
271
271
  mlrun/projects/operations.py,sha256=TzPbTYBgmYrjxTKP_wOtBJYFFFwDCQtaVvF1Snr0TfM,20029
272
272
  mlrun/projects/pipelines.py,sha256=wud7ezeEmhIJvfYE_wzQbA4ygEfGXHtbOtoOpan6poY,48556
273
- mlrun/projects/project.py,sha256=Xf1dHTJ5zkxxh9e8ZyuMRz0WtfQp06Ympc1r3Edv-tk,235138
273
+ mlrun/projects/project.py,sha256=H-mjTHqV_T9PhfCfGQRNm1R-7cM-7boS1Jd1TN9SyYo,235337
274
274
  mlrun/runtimes/__init__.py,sha256=J9Sy2HiyMlztNv6VUurMzF5H2XzttNil8nRsWDsqLyg,8923
275
275
  mlrun/runtimes/base.py,sha256=EL14Kmc1vWEjnBPJwLj5hHC6CtRAQHJLmohCD3sFEHo,37855
276
276
  mlrun/runtimes/daskjob.py,sha256=JwuGvOiPsxEDHHMMUS4Oie4hLlYYIZwihAl6DjroTY0,19521
@@ -297,7 +297,7 @@ mlrun/runtimes/nuclio/nuclio.py,sha256=sLK8KdGO1LbftlL3HqPZlFOFTAAuxJACZCVl1c0Ha
297
297
  mlrun/runtimes/nuclio/serving.py,sha256=1QPza0oG63bt3Bpib2VGhDcW3PNEjjsBUzIYBhiYR0s,32666
298
298
  mlrun/runtimes/nuclio/application/__init__.py,sha256=rRs5vasy_G9IyoTpYIjYDafGoL6ifFBKgBtsXn31Atw,614
299
299
  mlrun/runtimes/nuclio/application/application.py,sha256=VPX-ruYQJ7-7yd5c2sWdF4U5JCGSS3kYjUfOgev6l_Y,29186
300
- mlrun/runtimes/nuclio/application/reverse_proxy.go,sha256=JIIYae6bXzCLf3jXuu49KWPQYoXr_FDQ2Rbo1OWKAd0,3150
300
+ mlrun/runtimes/nuclio/application/reverse_proxy.go,sha256=lEHH74vr2PridIHp1Jkc_NjkrWb5b6zawRrNxHQhwGU,2913
301
301
  mlrun/runtimes/sparkjob/__init__.py,sha256=GPP_ekItxiU9Ydn3mJa4Obph02Bg6DO-JYs791_MV58,607
302
302
  mlrun/runtimes/sparkjob/spark3job.py,sha256=E777WdlSe7Yx2kpg1bK0zZokn93bOQiUbtvtbcHV7ig,41610
303
303
  mlrun/serving/__init__.py,sha256=FhOlOCnBC5HFXOHzSDe4NHBs6mNUDP_Qqy6WMNsCwws,1307
@@ -340,11 +340,11 @@ mlrun/utils/notifications/notification/mail.py,sha256=ZyJ3eqd8simxffQmXzqd3bgbAq
340
340
  mlrun/utils/notifications/notification/slack.py,sha256=eQvmctTh6wIG5xVOesLLV9S1-UUCu5UEQ9JIJOor3ts,7183
341
341
  mlrun/utils/notifications/notification/webhook.py,sha256=NeyIMSBojjjTJaUHmPbxMByp34GxYkl1-16NqzU27fU,4943
342
342
  mlrun/utils/version/__init__.py,sha256=7kkrB7hEZ3cLXoWj1kPoDwo4MaswsI2JVOBpbKgPAgc,614
343
- mlrun/utils/version/version.json,sha256=ciygJ1gAo0RxZORLqRbG9wRR1xO-sfHP3MdbVhPBs0Y,89
343
+ mlrun/utils/version/version.json,sha256=M386FKHwnC4eHpp3xG7fFtQEQllorzsiu9pDs5U8888,89
344
344
  mlrun/utils/version/version.py,sha256=eEW0tqIAkU9Xifxv8Z9_qsYnNhn3YH7NRAfM-pPLt1g,1878
345
- mlrun-1.8.0rc44.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
346
- mlrun-1.8.0rc44.dist-info/METADATA,sha256=P7-B2qIlhAydIA_24hVz9_SpUYvtyOwCCtm5R7YKoWY,25986
347
- mlrun-1.8.0rc44.dist-info/WHEEL,sha256=beeZ86-EfXScwlR_HKu4SllMC9wUEj_8Z_4FJ3egI2w,91
348
- mlrun-1.8.0rc44.dist-info/entry_points.txt,sha256=1Owd16eAclD5pfRCoJpYC2ZJSyGNTtUr0nCELMioMmU,46
349
- mlrun-1.8.0rc44.dist-info/top_level.txt,sha256=NObLzw3maSF9wVrgSeYBv-fgnHkAJ1kEkh12DLdd5KM,6
350
- mlrun-1.8.0rc44.dist-info/RECORD,,
345
+ mlrun-1.8.0rc45.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
346
+ mlrun-1.8.0rc45.dist-info/METADATA,sha256=Hrx8b3n6ywe0Ttl7L2PHZSvuIXzm9ELWceKlutJ-7jk,26008
347
+ mlrun-1.8.0rc45.dist-info/WHEEL,sha256=1tXe9gY0PYatrMPMDd6jXqjfpz_B-Wqm32CPfRC58XU,91
348
+ mlrun-1.8.0rc45.dist-info/entry_points.txt,sha256=1Owd16eAclD5pfRCoJpYC2ZJSyGNTtUr0nCELMioMmU,46
349
+ mlrun-1.8.0rc45.dist-info/top_level.txt,sha256=NObLzw3maSF9wVrgSeYBv-fgnHkAJ1kEkh12DLdd5KM,6
350
+ mlrun-1.8.0rc45.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (76.1.0)
2
+ Generator: setuptools (77.0.3)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5