mlrun 1.10.0rc6__py3-none-any.whl → 1.10.0rc7__py3-none-any.whl

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

Potentially problematic release.


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

mlrun/__main__.py CHANGED
@@ -23,6 +23,7 @@ from ast import literal_eval
23
23
  from base64 import b64decode
24
24
  from os import environ, path, remove
25
25
  from pprint import pprint
26
+ from typing import Optional
26
27
 
27
28
  import click
28
29
  import dotenv
@@ -199,6 +200,13 @@ def main():
199
200
  multiple=True,
200
201
  help="Logging configurations for the handler's returning values",
201
202
  )
203
+ @click.option(
204
+ "--allow-cross-project",
205
+ is_flag=True,
206
+ default=True, # TODO: remove this default in 1.11
207
+ help="Override the loaded project name. This flag ensures awareness of loading an existing project yaml "
208
+ "as a baseline for a new project with a different name",
209
+ )
202
210
  def run(
203
211
  url,
204
212
  param,
@@ -242,6 +250,7 @@ def run(
242
250
  run_args,
243
251
  ensure_project,
244
252
  returns,
253
+ allow_cross_project,
245
254
  ):
246
255
  """Execute a task and inject parameters."""
247
256
 
@@ -293,10 +302,11 @@ def run(
293
302
  mlrun.get_or_create_project(
294
303
  name=project,
295
304
  context="./",
305
+ allow_cross_project=allow_cross_project,
296
306
  )
297
307
  if func_url or kind:
298
308
  if func_url:
299
- runtime = func_url_to_runtime(func_url, ensure_project)
309
+ runtime = func_url_to_runtime(func_url, ensure_project, allow_cross_project)
300
310
  kind = get_in(runtime, "kind", kind or "job")
301
311
  if runtime is None:
302
312
  exit(1)
@@ -494,6 +504,13 @@ def run(
494
504
  default="/tmp/fullimage",
495
505
  help="path to file with full image data",
496
506
  )
507
+ @click.option(
508
+ "--allow-cross-project",
509
+ is_flag=True,
510
+ default=True, # TODO: remove this default in 1.11
511
+ help="Override the loaded project name. This flag ensures awareness of loading an existing project yaml "
512
+ "as a baseline for a new project with a different name",
513
+ )
497
514
  def build(
498
515
  func_url,
499
516
  name,
@@ -516,6 +533,7 @@ def build(
516
533
  state_file_path,
517
534
  image_file_path,
518
535
  full_image_file_path,
536
+ allow_cross_project,
519
537
  ):
520
538
  """Build a container image from code and requirements."""
521
539
 
@@ -591,6 +609,7 @@ def build(
591
609
  mlrun.get_or_create_project(
592
610
  name=project,
593
611
  context="./",
612
+ allow_cross_project=allow_cross_project,
594
613
  )
595
614
 
596
615
  if hasattr(func, "deploy"):
@@ -644,6 +663,13 @@ def build(
644
663
  is_flag=True,
645
664
  help="ensure the project exists, if not, create project",
646
665
  )
666
+ @click.option(
667
+ "--allow-cross-project",
668
+ is_flag=True,
669
+ default=True, # TODO: remove this default in 1.11
670
+ help="Override the loaded project name. This flag ensures awareness of loading an existing project yaml "
671
+ "as a baseline for a new project with a different name",
672
+ )
647
673
  def deploy(
648
674
  spec,
649
675
  source,
@@ -656,6 +682,7 @@ def deploy(
656
682
  verbose,
657
683
  env_file,
658
684
  ensure_project,
685
+ allow_cross_project,
659
686
  ):
660
687
  """Deploy model or function"""
661
688
  if env_file:
@@ -665,10 +692,11 @@ def deploy(
665
692
  mlrun.get_or_create_project(
666
693
  name=project,
667
694
  context="./",
695
+ allow_cross_project=allow_cross_project,
668
696
  )
669
697
 
670
698
  if func_url:
671
- runtime = func_url_to_runtime(func_url, ensure_project)
699
+ runtime = func_url_to_runtime(func_url, ensure_project, allow_cross_project)
672
700
  if runtime is None:
673
701
  exit(1)
674
702
  elif spec:
@@ -971,6 +999,13 @@ def logs(uid, project, offset, db):
971
999
  "destination define: file=notification.json or a "
972
1000
  'dictionary configuration e.g \'{"slack":{"webhook":"<webhook>"}}\'',
973
1001
  )
1002
+ @click.option(
1003
+ "--allow-cross-project",
1004
+ is_flag=True,
1005
+ default=True, # TODO: remove this default in 1.11
1006
+ help="Override the loaded project name. This flag ensures awareness of loading an existing project yaml "
1007
+ "as a baseline for a new project with a different name",
1008
+ )
974
1009
  def project(
975
1010
  context,
976
1011
  name,
@@ -998,6 +1033,7 @@ def project(
998
1033
  notifications,
999
1034
  save_secrets,
1000
1035
  save,
1036
+ allow_cross_project,
1001
1037
  ):
1002
1038
  """load and/or run a project"""
1003
1039
  if env_file:
@@ -1024,6 +1060,7 @@ def project(
1024
1060
  clone=clone,
1025
1061
  save=save,
1026
1062
  parameters=parameters,
1063
+ allow_cross_project=allow_cross_project,
1027
1064
  )
1028
1065
  url_str = " from " + url if url else ""
1029
1066
  print(f"Loading project {proj.name}{url_str} into {context}:\n")
@@ -1337,7 +1374,11 @@ def dict_to_str(struct: dict):
1337
1374
  return ",".join([f"{k}={v}" for k, v in struct.items()])
1338
1375
 
1339
1376
 
1340
- def func_url_to_runtime(func_url, ensure_project: bool = False):
1377
+ def func_url_to_runtime(
1378
+ func_url,
1379
+ ensure_project: bool = False,
1380
+ allow_cross_project: Optional[bool] = None,
1381
+ ):
1341
1382
  try:
1342
1383
  if func_url.startswith("db://"):
1343
1384
  func_url = func_url[5:]
@@ -1348,7 +1389,9 @@ def func_url_to_runtime(func_url, ensure_project: bool = False):
1348
1389
  func_url = "function.yaml" if func_url == "." else func_url
1349
1390
  runtime = import_function_to_dict(func_url, {})
1350
1391
  else:
1351
- mlrun_project = load_project(".", save=ensure_project)
1392
+ mlrun_project = load_project(
1393
+ ".", save=ensure_project, allow_cross_project=allow_cross_project
1394
+ )
1352
1395
  function = mlrun_project.get_function(func_url, enrich=True)
1353
1396
  if function.kind == "local":
1354
1397
  command, function = load_func_code(function)
mlrun/artifacts/base.py CHANGED
@@ -223,28 +223,9 @@ class Artifact(ModelObj):
223
223
  target_path=None,
224
224
  project=None,
225
225
  src_path: typing.Optional[str] = None,
226
- # All params up until here are legacy params for compatibility with legacy artifacts.
227
- # TODO: remove them in 1.10.0.
228
226
  metadata: ArtifactMetadata = None,
229
227
  spec: ArtifactSpec = None,
230
228
  ):
231
- if (
232
- key
233
- or body
234
- or viewer
235
- or is_inline
236
- or format
237
- or size
238
- or target_path
239
- or project
240
- or src_path
241
- ):
242
- warnings.warn(
243
- "Artifact constructor parameters are deprecated in 1.7.0 and will be removed in 1.10.0. "
244
- "Use the metadata and spec parameters instead.",
245
- DeprecationWarning,
246
- )
247
-
248
229
  self._metadata = None
249
230
  self.metadata = metadata
250
231
  self._spec = None
@@ -769,17 +750,9 @@ class LinkArtifact(Artifact):
769
750
  link_key=None,
770
751
  link_tree=None,
771
752
  project=None,
772
- # All params up until here are legacy params for compatibility with legacy artifacts.
773
- # TODO: remove them in 1.10.0.
774
753
  metadata: ArtifactMetadata = None,
775
754
  spec: LinkArtifactSpec = None,
776
755
  ):
777
- if key or target_path or link_iteration or link_key or link_tree or project:
778
- warnings.warn(
779
- "Artifact constructor parameters are deprecated in 1.7.0 and will be removed in 1.10.0. "
780
- "Use the metadata and spec parameters instead.",
781
- DeprecationWarning,
782
- )
783
756
  super().__init__(
784
757
  key, target_path=target_path, project=project, metadata=metadata, spec=spec
785
758
  )
@@ -13,7 +13,6 @@
13
13
  # limitations under the License.
14
14
  import os
15
15
  import pathlib
16
- import warnings
17
16
  from io import StringIO
18
17
  from typing import Optional
19
18
 
@@ -161,13 +160,6 @@ class DatasetArtifact(Artifact):
161
160
  label_column: Optional[str] = None,
162
161
  **kwargs,
163
162
  ):
164
- if key or format or target_path:
165
- warnings.warn(
166
- "Artifact constructor parameters are deprecated in 1.7.0 and will be removed in 1.10.0. "
167
- "Use the metadata and spec parameters instead.",
168
- DeprecationWarning,
169
- )
170
-
171
163
  format = (format or "").lower()
172
164
  super().__init__(key, None, format=format, target_path=target_path)
173
165
  if format and format not in self.SUPPORTED_FORMATS:
mlrun/artifacts/model.py CHANGED
@@ -13,7 +13,6 @@
13
13
  # limitations under the License.
14
14
 
15
15
  import tempfile
16
- import warnings
17
16
  from os import path
18
17
  from typing import Any, Optional, Union
19
18
 
@@ -189,12 +188,6 @@ class ModelArtifact(Artifact):
189
188
  Saved as a sub-dictionary under the parameter.
190
189
  :param kwargs: Arguments to pass to the artifact class.
191
190
  """
192
- if key or body or format or target_path:
193
- warnings.warn(
194
- "Artifact constructor parameters are deprecated in 1.7.0 and will be removed in 1.10.0. "
195
- "Use the metadata and spec parameters instead.",
196
- DeprecationWarning,
197
- )
198
191
  super().__init__(key, body, format=format, target_path=target_path, **kwargs)
199
192
  model_file = str(model_file or "")
200
193
  if model_file and model_url:
mlrun/artifacts/plots.py CHANGED
@@ -13,7 +13,6 @@
13
13
  # limitations under the License.
14
14
  import base64
15
15
  import typing
16
- import warnings
17
16
  from io import BytesIO
18
17
 
19
18
  import mlrun
@@ -35,12 +34,6 @@ class PlotArtifact(Artifact):
35
34
  def __init__(
36
35
  self, key=None, body=None, is_inline=False, target_path=None, title=None
37
36
  ):
38
- if key or body or is_inline or target_path:
39
- warnings.warn(
40
- "Artifact constructor parameters are deprecated in 1.7.0 and will be removed in 1.10.0. "
41
- "Use the metadata and spec parameters instead.",
42
- DeprecationWarning,
43
- )
44
37
  super().__init__(key, body, format="html", target_path=target_path)
45
38
  self.metadata.description = title
46
39
 
@@ -94,12 +87,6 @@ class PlotlyArtifact(Artifact):
94
87
  :param key: Key for the artifact to be stored in the database.
95
88
  :param target_path: Path to save the artifact.
96
89
  """
97
- if key or target_path:
98
- warnings.warn(
99
- "Artifact constructor parameters are deprecated in 1.7.0 and will be removed in 1.10.0. "
100
- "Use the metadata and spec parameters instead.",
101
- DeprecationWarning,
102
- )
103
90
  # Validate the plotly package:
104
91
  try:
105
92
  from plotly.graph_objs import Figure
mlrun/db/base.py CHANGED
@@ -97,9 +97,6 @@ class RunDBInterface(ABC):
97
97
  uid: Optional[Union[str, list[str]]] = None,
98
98
  project: Optional[str] = None,
99
99
  labels: Optional[Union[str, dict[str, Optional[str]], list[str]]] = None,
100
- state: Optional[
101
- mlrun.common.runtimes.constants.RunStates
102
- ] = None, # Backward compatibility
103
100
  states: Optional[list[mlrun.common.runtimes.constants.RunStates]] = None,
104
101
  sort: bool = True,
105
102
  iter: bool = False,
@@ -442,23 +439,6 @@ class RunDBInterface(ABC):
442
439
  ) -> dict:
443
440
  pass
444
441
 
445
- # TODO: remove in 1.10.0
446
- @deprecated(
447
- version="1.7.0",
448
- reason="'list_features' will be removed in 1.10.0, use 'list_features_v2' instead",
449
- category=FutureWarning,
450
- )
451
- @abstractmethod
452
- def list_features(
453
- self,
454
- project: str,
455
- name: Optional[str] = None,
456
- tag: Optional[str] = None,
457
- entities: Optional[list[str]] = None,
458
- labels: Optional[Union[str, dict[str, Optional[str]], list[str]]] = None,
459
- ) -> mlrun.common.schemas.FeaturesOutput:
460
- pass
461
-
462
442
  @abstractmethod
463
443
  def list_features_v2(
464
444
  self,
mlrun/db/httpdb.py CHANGED
@@ -901,9 +901,6 @@ class HTTPRunDB(RunDBInterface):
901
901
  uid: Optional[Union[str, list[str]]] = None,
902
902
  project: Optional[str] = None,
903
903
  labels: Optional[Union[str, dict[str, Optional[str]], list[str]]] = None,
904
- state: Optional[
905
- mlrun.common.runtimes.constants.RunStates
906
- ] = None, # Backward compatibility
907
904
  states: typing.Optional[list[mlrun.common.runtimes.constants.RunStates]] = None,
908
905
  sort: bool = True,
909
906
  iter: bool = False,
@@ -948,7 +945,6 @@ class HTTPRunDB(RunDBInterface):
948
945
  or just `"label"` for key existence.
949
946
  - A comma-separated string formatted as `"label1=value1,label2"` to match entities with
950
947
  the specified key-value pairs or key existence.
951
- :param state: Deprecated - List only runs whose state is specified (will be removed in 1.10.0)
952
948
  :param states: List only runs whose state is one of the provided states.
953
949
  :param sort: Whether to sort the result according to their start time. Otherwise, results will be
954
950
  returned by their internal order in the DB (order will not be guaranteed).
@@ -976,7 +972,6 @@ class HTTPRunDB(RunDBInterface):
976
972
  uid=uid,
977
973
  project=project,
978
974
  labels=labels,
979
- state=state,
980
975
  states=states,
981
976
  sort=sort,
982
977
  iter=iter,
@@ -2483,50 +2478,6 @@ class HTTPRunDB(RunDBInterface):
2483
2478
  resp = self.api_call("GET", path, error_message)
2484
2479
  return FeatureSet.from_dict(resp.json())
2485
2480
 
2486
- def list_features(
2487
- self,
2488
- project: Optional[str] = None,
2489
- name: Optional[str] = None,
2490
- tag: Optional[str] = None,
2491
- entities: Optional[list[str]] = None,
2492
- labels: Optional[Union[str, dict[str, Optional[str]], list[str]]] = None,
2493
- ) -> list[dict]:
2494
- """List feature-sets which contain specific features. This function may return multiple versions of the same
2495
- feature-set if a specific tag is not requested. Note that the various filters of this function actually
2496
- refer to the feature-set object containing the features, not to the features themselves.
2497
-
2498
- :param project: Project which contains these features.
2499
- :param name: Name of the feature to look for. The name is used in a like query, and is not case-sensitive. For
2500
- example, looking for ``feat`` will return features which are named ``MyFeature`` as well as ``defeat``.
2501
- :param tag: Return feature-sets which contain the features looked for, and are tagged with the specific tag.
2502
- :param entities: Return only feature-sets which contain an entity whose name is contained in this list.
2503
- :param labels: Filter feature-sets by label key-value pairs or key existence. This can be provided as:
2504
- - A dictionary in the format `{"label": "value"}` to match specific label key-value pairs,
2505
- or `{"label": None}` to check for key existence.
2506
- - A list of strings formatted as `"label=value"` to match specific label key-value pairs,
2507
- or just `"label"` for key existence.
2508
- - A comma-separated string formatted as `"label1=value1,label2"` to match entities with
2509
- the specified key-value pairs or key existence.
2510
- :returns: A list of mapping from feature to a digest of the feature-set, which contains the feature-set
2511
- meta-data. Multiple entries may be returned for any specific feature due to multiple tags or versions
2512
- of the feature-set.
2513
- """
2514
-
2515
- project = project or config.active_project
2516
- labels = self._parse_labels(labels)
2517
- params = {
2518
- "name": name,
2519
- "tag": tag,
2520
- "entity": entities or [],
2521
- "label": labels,
2522
- }
2523
-
2524
- path = f"projects/{project}/features"
2525
-
2526
- error_message = f"Failed listing features, project: {project}, query: {params}"
2527
- resp = self.api_call("GET", path, error_message, params=params)
2528
- return resp.json()["features"]
2529
-
2530
2481
  def list_features_v2(
2531
2482
  self,
2532
2483
  project: Optional[str] = None,
@@ -5263,9 +5214,6 @@ class HTTPRunDB(RunDBInterface):
5263
5214
  uid: Optional[Union[str, list[str]]] = None,
5264
5215
  project: Optional[str] = None,
5265
5216
  labels: Optional[Union[str, dict[str, Optional[str]], list[str]]] = None,
5266
- state: Optional[
5267
- mlrun.common.runtimes.constants.RunStates
5268
- ] = None, # Backward compatibility
5269
5217
  states: typing.Optional[list[mlrun.common.runtimes.constants.RunStates]] = None,
5270
5218
  sort: bool = True,
5271
5219
  iter: bool = False,
@@ -5299,20 +5247,12 @@ class HTTPRunDB(RunDBInterface):
5299
5247
  "using the `with_notifications` flag."
5300
5248
  )
5301
5249
 
5302
- if state:
5303
- # TODO: Remove this in 1.10.0
5304
- warnings.warn(
5305
- "'state' is deprecated in 1.7.0 and will be removed in 1.10.0. Use 'states' instead.",
5306
- FutureWarning,
5307
- )
5308
-
5309
5250
  labels = self._parse_labels(labels)
5310
5251
 
5311
5252
  if (
5312
5253
  not name
5313
5254
  and not uid
5314
5255
  and not labels
5315
- and not state
5316
5256
  and not states
5317
5257
  and not start_time_from
5318
5258
  and not start_time_to
@@ -5333,11 +5273,7 @@ class HTTPRunDB(RunDBInterface):
5333
5273
  "name": name,
5334
5274
  "uid": uid,
5335
5275
  "label": labels,
5336
- "state": (
5337
- mlrun.utils.helpers.as_list(state)
5338
- if state is not None
5339
- else states or None
5340
- ),
5276
+ "states": states or None,
5341
5277
  "sort": bool2str(sort),
5342
5278
  "iter": bool2str(iter),
5343
5279
  "start_time_from": datetime_to_iso(start_time_from),
mlrun/db/nopdb.py CHANGED
@@ -126,9 +126,6 @@ class NopDB(RunDBInterface):
126
126
  uid: Optional[Union[str, list[str]]] = None,
127
127
  project: Optional[str] = None,
128
128
  labels: Optional[Union[str, dict[str, Optional[str]], list[str]]] = None,
129
- state: Optional[
130
- mlrun.common.runtimes.constants.RunStates
131
- ] = None, # Backward compatibility
132
129
  states: Optional[list[mlrun.common.runtimes.constants.RunStates]] = None,
133
130
  sort: bool = True,
134
131
  iter: bool = False,
@@ -374,16 +371,6 @@ class NopDB(RunDBInterface):
374
371
  ) -> dict:
375
372
  pass
376
373
 
377
- def list_features(
378
- self,
379
- project: str,
380
- name: Optional[str] = None,
381
- tag: Optional[str] = None,
382
- entities: Optional[list[str]] = None,
383
- labels: Optional[Union[str, dict[str, Optional[str]], list[str]]] = None,
384
- ) -> mlrun.common.schemas.FeaturesOutput:
385
- pass
386
-
387
374
  def list_features_v2(
388
375
  self,
389
376
  project: str,
mlrun/launcher/base.py CHANGED
@@ -82,6 +82,7 @@ class BaseLauncher(abc.ABC):
82
82
  runtime: "mlrun.runtimes.base.BaseRuntime",
83
83
  project_name: Optional[str] = "",
84
84
  full: bool = True,
85
+ client_version: str = "",
85
86
  ):
86
87
  pass
87
88
 
mlrun/launcher/client.py CHANGED
@@ -37,6 +37,7 @@ class ClientBaseLauncher(launcher.BaseLauncher, abc.ABC):
37
37
  runtime: "mlrun.runtimes.base.BaseRuntime",
38
38
  project_name: Optional[str] = "",
39
39
  full: bool = True,
40
+ client_version: str = "",
40
41
  ):
41
42
  runtime.try_auto_mount_based_on_config()
42
43
  runtime._fill_credentials()
mlrun/launcher/local.py CHANGED
@@ -13,6 +13,7 @@
13
13
  # limitations under the License.
14
14
  import os
15
15
  import pathlib
16
+ from os import environ
16
17
  from typing import Callable, Optional, Union
17
18
 
18
19
  import mlrun.common.constants as mlrun_constants
@@ -251,6 +252,9 @@ class ClientLocalLauncher(launcher.ClientBaseLauncher):
251
252
  # copy the code/base-spec to the local function (for the UI and code logging)
252
253
  fn.spec.description = runtime.spec.description
253
254
  fn.spec.build = runtime.spec.build
255
+ serving_spec = getattr(runtime.spec, "serving_spec", None)
256
+ if serving_spec:
257
+ environ["SERVING_SPEC_ENV"] = serving_spec
254
258
 
255
259
  run.spec.handler = handler
256
260
  run.spec.reset_on_run = reset_on_run
@@ -13,7 +13,6 @@
13
13
  # limitations under the License.
14
14
 
15
15
  import collections
16
- import json
17
16
  import traceback
18
17
  from collections import OrderedDict
19
18
  from datetime import datetime
@@ -23,10 +22,12 @@ import mlrun.common.schemas
23
22
  import mlrun.common.schemas.alert as alert_objects
24
23
  import mlrun.common.schemas.model_monitoring.constants as mm_constants
25
24
  import mlrun.model_monitoring.helpers
25
+ import mlrun.platforms.iguazio
26
26
  from mlrun.serving import GraphContext
27
27
  from mlrun.serving.utils import StepToDict
28
28
  from mlrun.utils import logger
29
29
 
30
+ from .base import _serialize_context_and_result
30
31
  from .context import MonitoringApplicationContext
31
32
  from .results import (
32
33
  ModelMonitoringApplicationMetric,
@@ -45,7 +46,7 @@ class _PushToMonitoringWriter(StepToDict):
45
46
  :param project: Project name.
46
47
  """
47
48
  self.project = project
48
- self.output_stream = None
49
+ self._output_stream = None
49
50
 
50
51
  def do(
51
52
  self,
@@ -65,48 +66,31 @@ class _PushToMonitoringWriter(StepToDict):
65
66
 
66
67
  :param event: Monitoring result(s) to push and the original event from the controller.
67
68
  """
68
- self._lazy_init()
69
69
  application_results, application_context = event
70
- writer_event = {
71
- mm_constants.WriterEvent.ENDPOINT_NAME: application_context.endpoint_name,
72
- mm_constants.WriterEvent.APPLICATION_NAME: application_context.application_name,
73
- mm_constants.WriterEvent.ENDPOINT_ID: application_context.endpoint_id,
74
- mm_constants.WriterEvent.START_INFER_TIME: application_context.start_infer_time.isoformat(
75
- sep=" ", timespec="microseconds"
76
- ),
77
- mm_constants.WriterEvent.END_INFER_TIME: application_context.end_infer_time.isoformat(
78
- sep=" ", timespec="microseconds"
79
- ),
80
- }
81
- for result in application_results:
82
- data = result.to_dict()
83
- if isinstance(result, ModelMonitoringApplicationResult):
84
- writer_event[mm_constants.WriterEvent.EVENT_KIND] = (
85
- mm_constants.WriterEventKind.RESULT
86
- )
87
- elif isinstance(result, _ModelMonitoringApplicationStats):
88
- writer_event[mm_constants.WriterEvent.EVENT_KIND] = (
89
- mm_constants.WriterEventKind.STATS
90
- )
91
- else:
92
- writer_event[mm_constants.WriterEvent.EVENT_KIND] = (
93
- mm_constants.WriterEventKind.METRIC
94
- )
95
- writer_event[mm_constants.WriterEvent.DATA] = json.dumps(data)
96
- logger.debug(
97
- "Pushing data to output stream", writer_event=str(writer_event)
98
- )
99
- self.output_stream.push(
100
- [writer_event], partition_key=application_context.endpoint_id
101
- )
102
- logger.debug("Pushed data to output stream successfully")
103
70
 
104
- def _lazy_init(self):
105
- if self.output_stream is None:
106
- self.output_stream = mlrun.model_monitoring.helpers.get_output_stream(
71
+ writer_events = [
72
+ _serialize_context_and_result(context=application_context, result=result)
73
+ for result in application_results
74
+ ]
75
+
76
+ logger.debug("Pushing data to output stream", writer_events=str(writer_events))
77
+ self.output_stream.push(
78
+ writer_events, partition_key=application_context.endpoint_id
79
+ )
80
+ logger.debug("Pushed data to output stream successfully")
81
+
82
+ @property
83
+ def output_stream(
84
+ self,
85
+ ) -> Union[
86
+ mlrun.platforms.iguazio.OutputStream, mlrun.platforms.iguazio.KafkaOutputStream
87
+ ]:
88
+ if self._output_stream is None:
89
+ self._output_stream = mlrun.model_monitoring.helpers.get_output_stream(
107
90
  project=self.project,
108
91
  function_name=mm_constants.MonitoringFunctionNames.WRITER,
109
92
  )
93
+ return self._output_stream
110
94
 
111
95
 
112
96
  class _PrepareMonitoringEvent(StepToDict):