mlrun 1.7.0rc15__py3-none-any.whl → 1.7.0rc17__py3-none-any.whl

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

Potentially problematic release.


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

Files changed (77) hide show
  1. mlrun/__init__.py +10 -1
  2. mlrun/__main__.py +18 -4
  3. mlrun/alerts/__init__.py +15 -0
  4. mlrun/alerts/alert.py +144 -0
  5. mlrun/artifacts/__init__.py +7 -1
  6. mlrun/artifacts/base.py +28 -3
  7. mlrun/artifacts/dataset.py +8 -0
  8. mlrun/artifacts/manager.py +18 -0
  9. mlrun/artifacts/model.py +8 -1
  10. mlrun/artifacts/plots.py +13 -0
  11. mlrun/common/schemas/__init__.py +10 -2
  12. mlrun/common/schemas/alert.py +64 -5
  13. mlrun/common/schemas/api_gateway.py +4 -0
  14. mlrun/common/schemas/artifact.py +15 -0
  15. mlrun/common/schemas/auth.py +2 -0
  16. mlrun/common/schemas/model_monitoring/__init__.py +4 -1
  17. mlrun/common/schemas/model_monitoring/constants.py +17 -1
  18. mlrun/common/schemas/model_monitoring/model_endpoints.py +60 -1
  19. mlrun/common/schemas/project.py +5 -1
  20. mlrun/config.py +11 -4
  21. mlrun/datastore/datastore_profile.py +10 -7
  22. mlrun/db/base.py +24 -4
  23. mlrun/db/httpdb.py +97 -43
  24. mlrun/db/nopdb.py +25 -4
  25. mlrun/errors.py +5 -0
  26. mlrun/launcher/base.py +3 -2
  27. mlrun/lists.py +4 -0
  28. mlrun/model.py +15 -8
  29. mlrun/model_monitoring/__init__.py +1 -1
  30. mlrun/model_monitoring/applications/_application_steps.py +1 -2
  31. mlrun/model_monitoring/applications/context.py +1 -1
  32. mlrun/model_monitoring/applications/histogram_data_drift.py +64 -38
  33. mlrun/model_monitoring/db/__init__.py +2 -0
  34. mlrun/model_monitoring/db/stores/base/store.py +9 -36
  35. mlrun/model_monitoring/db/stores/sqldb/sql_store.py +63 -110
  36. mlrun/model_monitoring/db/stores/v3io_kv/kv_store.py +56 -202
  37. mlrun/model_monitoring/db/tsdb/__init__.py +71 -0
  38. mlrun/model_monitoring/db/tsdb/base.py +135 -0
  39. mlrun/model_monitoring/db/tsdb/v3io/__init__.py +15 -0
  40. mlrun/model_monitoring/db/tsdb/v3io/stream_graph_steps.py +117 -0
  41. mlrun/model_monitoring/db/tsdb/v3io/v3io_connector.py +442 -0
  42. mlrun/model_monitoring/db/v3io_tsdb_reader.py +134 -0
  43. mlrun/model_monitoring/stream_processing.py +46 -210
  44. mlrun/model_monitoring/writer.py +50 -100
  45. mlrun/platforms/__init__.py +10 -9
  46. mlrun/platforms/iguazio.py +19 -200
  47. mlrun/projects/operations.py +11 -7
  48. mlrun/projects/pipelines.py +13 -76
  49. mlrun/projects/project.py +62 -17
  50. mlrun/render.py +9 -3
  51. mlrun/run.py +5 -38
  52. mlrun/runtimes/__init__.py +1 -0
  53. mlrun/runtimes/base.py +3 -3
  54. mlrun/runtimes/kubejob.py +2 -1
  55. mlrun/runtimes/nuclio/api_gateway.py +163 -77
  56. mlrun/runtimes/nuclio/application/application.py +160 -7
  57. mlrun/runtimes/nuclio/function.py +25 -45
  58. mlrun/runtimes/pod.py +16 -36
  59. mlrun/runtimes/remotesparkjob.py +1 -1
  60. mlrun/runtimes/sparkjob/spark3job.py +1 -1
  61. mlrun/runtimes/utils.py +0 -38
  62. mlrun/track/tracker.py +2 -1
  63. mlrun/utils/helpers.py +51 -31
  64. mlrun/utils/logger.py +11 -6
  65. mlrun/utils/notifications/notification/base.py +1 -1
  66. mlrun/utils/notifications/notification/slack.py +9 -4
  67. mlrun/utils/notifications/notification/webhook.py +1 -1
  68. mlrun/utils/notifications/notification_pusher.py +21 -14
  69. mlrun/utils/version/version.json +2 -2
  70. {mlrun-1.7.0rc15.dist-info → mlrun-1.7.0rc17.dist-info}/METADATA +4 -3
  71. {mlrun-1.7.0rc15.dist-info → mlrun-1.7.0rc17.dist-info}/RECORD +75 -69
  72. mlrun/kfpops.py +0 -860
  73. mlrun/platforms/other.py +0 -305
  74. {mlrun-1.7.0rc15.dist-info → mlrun-1.7.0rc17.dist-info}/LICENSE +0 -0
  75. {mlrun-1.7.0rc15.dist-info → mlrun-1.7.0rc17.dist-info}/WHEEL +0 -0
  76. {mlrun-1.7.0rc15.dist-info → mlrun-1.7.0rc17.dist-info}/entry_points.txt +0 -0
  77. {mlrun-1.7.0rc15.dist-info → mlrun-1.7.0rc17.dist-info}/top_level.txt +0 -0
mlrun/db/nopdb.py CHANGED
@@ -16,6 +16,7 @@
16
16
  import datetime
17
17
  from typing import Optional, Union
18
18
 
19
+ import mlrun.alerts
19
20
  import mlrun.common.schemas
20
21
  import mlrun.errors
21
22
 
@@ -128,7 +129,18 @@ class NopDB(RunDBInterface):
128
129
  ):
129
130
  pass
130
131
 
131
- def del_artifact(self, key, tag="", project="", tree=None, uid=None):
132
+ def del_artifact(
133
+ self,
134
+ key,
135
+ tag="",
136
+ project="",
137
+ tree=None,
138
+ uid=None,
139
+ deletion_strategy: mlrun.common.schemas.artifact.ArtifactsDeletionStrategies = (
140
+ mlrun.common.schemas.artifact.ArtifactsDeletionStrategies.metadata_only
141
+ ),
142
+ secrets: dict = None,
143
+ ):
132
144
  pass
133
145
 
134
146
  def del_artifacts(self, name="", project="", tag="", labels=None):
@@ -508,8 +520,11 @@ class NopDB(RunDBInterface):
508
520
 
509
521
  def store_api_gateway(
510
522
  self,
511
- project: str,
512
- api_gateway: mlrun.runtimes.nuclio.APIGateway,
523
+ api_gateway: Union[
524
+ mlrun.common.schemas.APIGateway,
525
+ mlrun.runtimes.nuclio.api_gateway.APIGateway,
526
+ ],
527
+ project: str = None,
513
528
  ) -> mlrun.common.schemas.APIGateway:
514
529
  pass
515
530
 
@@ -671,7 +686,7 @@ class NopDB(RunDBInterface):
671
686
  def store_alert_config(
672
687
  self,
673
688
  alert_name: str,
674
- alert_data: Union[dict, mlrun.common.schemas.AlertConfig],
689
+ alert_data: Union[dict, mlrun.alerts.alert.AlertConfig],
675
690
  project="",
676
691
  ):
677
692
  pass
@@ -687,3 +702,9 @@ class NopDB(RunDBInterface):
687
702
 
688
703
  def reset_alert_config(self, alert_name: str, project=""):
689
704
  pass
705
+
706
+ def get_alert_template(self, template_name: str):
707
+ pass
708
+
709
+ def list_alert_templates(self):
710
+ pass
mlrun/errors.py CHANGED
@@ -183,6 +183,10 @@ class MLRunInternalServerError(MLRunHTTPStatusError):
183
183
  error_status_code = HTTPStatus.INTERNAL_SERVER_ERROR.value
184
184
 
185
185
 
186
+ class MLRunNotImplementedServerError(MLRunHTTPStatusError):
187
+ error_status_code = HTTPStatus.NOT_IMPLEMENTED.value
188
+
189
+
186
190
  class MLRunServiceUnavailableError(MLRunHTTPStatusError):
187
191
  error_status_code = HTTPStatus.SERVICE_UNAVAILABLE.value
188
192
 
@@ -234,4 +238,5 @@ STATUS_ERRORS = {
234
238
  HTTPStatus.PRECONDITION_FAILED.value: MLRunPreconditionFailedError,
235
239
  HTTPStatus.INTERNAL_SERVER_ERROR.value: MLRunInternalServerError,
236
240
  HTTPStatus.SERVICE_UNAVAILABLE.value: MLRunServiceUnavailableError,
241
+ HTTPStatus.NOT_IMPLEMENTED.value: MLRunNotImplementedServerError,
237
242
  }
mlrun/launcher/base.py CHANGED
@@ -18,10 +18,11 @@ import os
18
18
  import uuid
19
19
  from typing import Any, Callable, Optional, Union
20
20
 
21
+ import mlrun_pipelines.common.ops
22
+
21
23
  import mlrun.common.schemas
22
24
  import mlrun.config
23
25
  import mlrun.errors
24
- import mlrun.kfpops
25
26
  import mlrun.lists
26
27
  import mlrun.model
27
28
  import mlrun.runtimes
@@ -390,7 +391,7 @@ class BaseLauncher(abc.ABC):
390
391
  return
391
392
 
392
393
  if result and runtime.kfp and err is None:
393
- mlrun.kfpops.write_kfpmeta(result)
394
+ mlrun_pipelines.common.ops.write_kfpmeta(result)
394
395
 
395
396
  self._log_track_results(runtime.is_child, result, run)
396
397
 
mlrun/lists.py CHANGED
@@ -29,12 +29,14 @@ list_header = [
29
29
  "iter",
30
30
  "start",
31
31
  "state",
32
+ "kind",
32
33
  "name",
33
34
  "labels",
34
35
  "inputs",
35
36
  "parameters",
36
37
  "results",
37
38
  "artifacts",
39
+ "artifact_uris",
38
40
  "error",
39
41
  ]
40
42
 
@@ -56,12 +58,14 @@ class RunList(list):
56
58
  get_in(run, "metadata.iteration", ""),
57
59
  get_in(run, "status.start_time", ""),
58
60
  get_in(run, "status.state", ""),
61
+ get_in(run, "step_kind", get_in(run, "kind", "")),
59
62
  get_in(run, "metadata.name", ""),
60
63
  get_in(run, "metadata.labels", ""),
61
64
  get_in(run, "spec.inputs", ""),
62
65
  get_in(run, "spec.parameters", ""),
63
66
  get_in(run, "status.results", ""),
64
67
  get_in(run, "status.artifacts", []),
68
+ get_in(run, "status.artifact_uris", {}),
65
69
  get_in(run, "status.error", ""),
66
70
  ]
67
71
  if extend_iterations and iterations:
mlrun/model.py CHANGED
@@ -681,10 +681,14 @@ class Notification(ModelObj):
681
681
 
682
682
  def __init__(
683
683
  self,
684
- kind=None,
684
+ kind: mlrun.common.schemas.notification.NotificationKind = (
685
+ mlrun.common.schemas.notification.NotificationKind.slack
686
+ ),
685
687
  name=None,
686
688
  message=None,
687
- severity=None,
689
+ severity: mlrun.common.schemas.notification.NotificationSeverity = (
690
+ mlrun.common.schemas.notification.NotificationSeverity.INFO
691
+ ),
688
692
  when=None,
689
693
  condition=None,
690
694
  secret_params=None,
@@ -693,12 +697,10 @@ class Notification(ModelObj):
693
697
  sent_time=None,
694
698
  reason=None,
695
699
  ):
696
- self.kind = kind or mlrun.common.schemas.notification.NotificationKind.slack
700
+ self.kind = kind
697
701
  self.name = name or ""
698
702
  self.message = message or ""
699
- self.severity = (
700
- severity or mlrun.common.schemas.notification.NotificationSeverity.INFO
701
- )
703
+ self.severity = severity
702
704
  self.when = when or ["completed"]
703
705
  self.condition = condition or ""
704
706
  self.secret_params = secret_params or {}
@@ -1207,6 +1209,7 @@ class RunStatus(ModelObj):
1207
1209
  ui_url=None,
1208
1210
  reason: str = None,
1209
1211
  notifications: dict[str, Notification] = None,
1212
+ artifact_uris: dict[str, str] = None,
1210
1213
  ):
1211
1214
  self.state = state or "created"
1212
1215
  self.status_text = status_text
@@ -1221,6 +1224,8 @@ class RunStatus(ModelObj):
1221
1224
  self.ui_url = ui_url
1222
1225
  self.reason = reason
1223
1226
  self.notifications = notifications or {}
1227
+ # Artifact key -> URI mapping, since the full artifacts are not stored in the runs DB table
1228
+ self.artifact_uris = artifact_uris or {}
1224
1229
 
1225
1230
  def is_failed(self) -> Optional[bool]:
1226
1231
  """
@@ -1539,8 +1544,10 @@ class RunObject(RunTemplate):
1539
1544
  iter=self.metadata.iteration,
1540
1545
  )
1541
1546
  if run:
1542
- self.status = RunStatus.from_dict(run.get("status", {}))
1543
- self.status.from_dict(run.get("status", {}))
1547
+ run_status = run.get("status", {})
1548
+ # Artifacts are not stored in the DB, so we need to preserve them here
1549
+ run_status["artifacts"] = self.status.artifacts
1550
+ self.status = RunStatus.from_dict(run_status)
1544
1551
  return self
1545
1552
 
1546
1553
  def show(self):
@@ -15,7 +15,7 @@
15
15
  # flake8: noqa - this is until we take care of the F401 violations with respect to __all__ & sphinx
16
16
  # for backwards compatibility
17
17
 
18
- from .db import get_store_object
18
+ from .db import get_store_object, get_tsdb_connector
19
19
  from .helpers import get_stream_path
20
20
  from .model_endpoint import ModelEndpoint
21
21
  from .tracking_policy import TrackingPolicy
@@ -11,7 +11,6 @@
11
11
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
- import copy
15
14
  import json
16
15
  import typing
17
16
  from typing import Optional
@@ -138,7 +137,7 @@ class _PrepareMonitoringEvent(StepToDict):
138
137
  if not event.get("mlrun_context"):
139
138
  application_context = MonitoringApplicationContext().from_dict(
140
139
  event,
141
- context=copy.deepcopy(self.context),
140
+ context=self.context,
142
141
  model_endpoint_dict=self.model_endpoints,
143
142
  )
144
143
  else:
@@ -113,7 +113,7 @@ class MonitoringApplicationContext(MLClientCtx):
113
113
  attrs.get(mm_constants.ApplicationEvent.FEATURE_STATS, "{}")
114
114
  )
115
115
  self._sample_df_stats = json.loads(
116
- attrs.get(mm_constants.ApplicationEvent.FEATURE_STATS, "{}")
116
+ attrs.get(mm_constants.ApplicationEvent.CURRENT_STATS, "{}")
117
117
  )
118
118
 
119
119
  self.endpoint_id = attrs.get(mm_constants.ApplicationEvent.ENDPOINT_ID)
@@ -11,9 +11,10 @@
11
11
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
- import typing
14
+
15
+ import json
15
16
  from dataclasses import dataclass
16
- from typing import Final, Optional, Protocol, cast
17
+ from typing import Final, Optional, Protocol, Union, cast
17
18
 
18
19
  import numpy as np
19
20
  from pandas import DataFrame, Series
@@ -90,9 +91,27 @@ class HistogramDataDriftApplication(ModelMonitoringApplicationBaseV2):
90
91
  """
91
92
  MLRun's default data drift application for model monitoring.
92
93
 
93
- The application calculates the metrics over the features' histograms.
94
- Each metric is calculated over all the features, the mean is taken,
95
- and the status is returned.
94
+ The application expects tabular numerical data, and calculates three metrics over the features' histograms.
95
+ The three metrics are:
96
+
97
+ * Hellinger distance.
98
+ * Total variance distance.
99
+ * Kullback-Leibler divergence.
100
+
101
+ Each metric is calculated over all the features individually and the mean is taken as the metric value.
102
+ The average of Hellinger and total variance distance is taken as the result.
103
+
104
+ The application logs two artifacts:
105
+
106
+ * A JSON with the general drift per feature.
107
+ * A plotly table different metrics per feature.
108
+
109
+ This application is deployed by default when calling:
110
+
111
+ .. code-block:: python
112
+
113
+ project.enable_model_monitoring()
114
+
96
115
  """
97
116
 
98
117
  NAME: Final[str] = HistogramDataDriftApplicationConstants.NAME
@@ -107,8 +126,6 @@ class HistogramDataDriftApplication(ModelMonitoringApplicationBaseV2):
107
126
 
108
127
  def __init__(self, value_classifier: Optional[ValueClassifier] = None) -> None:
109
128
  """
110
- Initialize the data drift application.
111
-
112
129
  :param value_classifier: Classifier object that adheres to the `ValueClassifier` protocol.
113
130
  If not provided, the default `DataDriftClassifier()` is used.
114
131
  """
@@ -146,35 +163,46 @@ class HistogramDataDriftApplication(ModelMonitoringApplicationBaseV2):
146
163
 
147
164
  return metrics_per_feature
148
165
 
149
- def _add_general_drift_result(
166
+ def _get_general_drift_result(
150
167
  self,
151
168
  metrics: list[mm_results.ModelMonitoringApplicationMetric],
152
- ) -> None:
153
- """Add the general drift result to the results list and log it"""
154
- value = np.mean(
155
- [
156
- metric.value
157
- for metric in metrics
158
- if metric.name
159
- in [
160
- f"{HellingerDistance.NAME}_mean",
161
- f"{TotalVarianceDistance.NAME}_mean",
169
+ monitoring_context: mm_context.MonitoringApplicationContext,
170
+ metrics_per_feature: DataFrame,
171
+ ) -> mm_results.ModelMonitoringApplicationResult:
172
+ """Get the general drift result from the metrics list"""
173
+ value = cast(
174
+ float,
175
+ np.mean(
176
+ [
177
+ metric.value
178
+ for metric in metrics
179
+ if metric.name
180
+ in [
181
+ f"{HellingerDistance.NAME}_mean",
182
+ f"{TotalVarianceDistance.NAME}_mean",
183
+ ]
162
184
  ]
163
- ]
185
+ ),
164
186
  )
165
187
 
166
188
  status = self._value_classifier.value_to_status(value)
167
- metrics.append(
168
- mm_results.ModelMonitoringApplicationResult(
169
- name=HistogramDataDriftApplicationConstants.GENERAL_RESULT_NAME,
170
- value=value,
171
- kind=ResultKindApp.data_drift,
172
- status=status,
173
- )
189
+ return mm_results.ModelMonitoringApplicationResult(
190
+ name=HistogramDataDriftApplicationConstants.GENERAL_RESULT_NAME,
191
+ value=value,
192
+ kind=ResultKindApp.data_drift,
193
+ status=status,
194
+ extra_data={
195
+ EventFieldType.CURRENT_STATS: json.dumps(
196
+ monitoring_context.feature_stats
197
+ ),
198
+ EventFieldType.DRIFT_MEASURES: metrics_per_feature.T.to_json(),
199
+ EventFieldType.DRIFT_STATUS: status.value,
200
+ },
174
201
  )
175
202
 
203
+ @staticmethod
176
204
  def _get_metrics(
177
- self, metrics_per_feature: DataFrame
205
+ metrics_per_feature: DataFrame,
178
206
  ) -> list[mm_results.ModelMonitoringApplicationMetric]:
179
207
  """Average the metrics over the features and add the status"""
180
208
  metrics: list[mm_results.ModelMonitoringApplicationMetric] = []
@@ -206,8 +234,8 @@ class HistogramDataDriftApplication(ModelMonitoringApplicationBaseV2):
206
234
  del sample_set_statistics[EventFieldType.TIMESTAMP]
207
235
  return sample_set_statistics
208
236
 
237
+ @staticmethod
209
238
  def _log_json_artifact(
210
- self,
211
239
  drift_per_feature_values: Series,
212
240
  monitoring_context: mm_context.MonitoringApplicationContext,
213
241
  ) -> None:
@@ -247,7 +275,7 @@ class HistogramDataDriftApplication(ModelMonitoringApplicationBaseV2):
247
275
  mm_drift_table.FeaturesDriftTablePlot().produce(
248
276
  sample_set_statistics=sample_set_statistics,
249
277
  inputs_statistics=inputs_statistics,
250
- metrics=metrics_per_feature.T.to_dict(),
278
+ metrics=metrics_per_feature.T.to_dict(), # pyright: ignore[reportArgumentType]
251
279
  drift_results=drift_results,
252
280
  )
253
281
  )
@@ -281,7 +309,7 @@ class HistogramDataDriftApplication(ModelMonitoringApplicationBaseV2):
281
309
  self,
282
310
  monitoring_context: mm_context.MonitoringApplicationContext,
283
311
  ) -> list[
284
- typing.Union[
312
+ Union[
285
313
  mm_results.ModelMonitoringApplicationResult,
286
314
  mm_results.ModelMonitoringApplicationMetric,
287
315
  ]
@@ -308,15 +336,13 @@ class HistogramDataDriftApplication(ModelMonitoringApplicationBaseV2):
308
336
  metrics_per_feature=metrics_per_feature,
309
337
  )
310
338
  monitoring_context.logger.debug("Computing average per metric")
311
- metrics_and_result: list[
312
- typing.Union[
313
- mm_results.ModelMonitoringApplicationMetric,
314
- mm_results.ModelMonitoringApplicationResult,
315
- ]
316
- ] = self._get_metrics(metrics_per_feature)
317
- self._add_general_drift_result(
318
- metrics=metrics_and_result,
339
+ metrics = self._get_metrics(metrics_per_feature)
340
+ result = self._get_general_drift_result(
341
+ metrics=metrics,
342
+ monitoring_context=monitoring_context,
343
+ metrics_per_feature=metrics_per_feature,
319
344
  )
345
+ metrics_and_result = metrics + [result]
320
346
  monitoring_context.logger.debug(
321
347
  "Finished running the application", results=metrics_and_result
322
348
  )
@@ -14,3 +14,5 @@
14
14
 
15
15
  from .stores import ObjectStoreFactory, get_store_object
16
16
  from .stores.base import StoreBase
17
+ from .tsdb import get_tsdb_connector
18
+ from .tsdb.base import TSDBConnector
@@ -15,6 +15,8 @@
15
15
  import typing
16
16
  from abc import ABC, abstractmethod
17
17
 
18
+ import mlrun.common.schemas.model_monitoring.constants as mm_constants
19
+
18
20
 
19
21
  class StoreBase(ABC):
20
22
  """
@@ -62,12 +64,10 @@ class StoreBase(ABC):
62
64
  pass
63
65
 
64
66
  @abstractmethod
65
- def delete_model_endpoints_resources(self, endpoints: list[dict[str, typing.Any]]):
67
+ def delete_model_endpoints_resources(self):
66
68
  """
67
69
  Delete all model endpoints resources.
68
70
 
69
- :param endpoints: A list of model endpoints flattened dictionaries.
70
-
71
71
  """
72
72
  pass
73
73
 
@@ -112,45 +112,18 @@ class StoreBase(ABC):
112
112
  pass
113
113
 
114
114
  @abstractmethod
115
- def get_endpoint_real_time_metrics(
115
+ def write_application_event(
116
116
  self,
117
- endpoint_id: str,
118
- metrics: list[str],
119
- start: str = "now-1h",
120
- end: str = "now",
121
- access_key: str = None,
122
- ) -> dict[str, list[tuple[str, float]]]:
123
- """
124
- Getting metrics from the time series DB. There are pre-defined metrics for model endpoints such as
125
- `predictions_per_second` and `latency_avg_5m` but also custom metrics defined by the user.
126
-
127
- :param endpoint_id: The unique id of the model endpoint.
128
- :param metrics: A list of real-time metrics to return for the model endpoint.
129
- :param start: The start time of the metrics. Can be represented by a string containing an RFC 3339
130
- time, a Unix timestamp in milliseconds, a relative time (`'now'` or
131
- `'now-[0-9]+[mhd]'`, where `m` = minutes, `h` = hours, and `'d'` = days), or 0 for the
132
- earliest time.
133
- :param end: The end time of the metrics. Can be represented by a string containing an RFC 3339
134
- time, a Unix timestamp in milliseconds, a relative time (`'now'` or
135
- `'now-[0-9]+[mhd]'`, where `m` = minutes, `h` = hours, and `'d'` = days), or 0 for the
136
- earliest time.
137
- :param access_key: V3IO access key that will be used for generating Frames client object. If not
138
- provided, the access key will be retrieved from the environment variables.
139
-
140
- :return: A dictionary of metrics in which the key is a metric name and the value is a list of tuples that
141
- includes timestamps and the values.
142
- """
143
-
144
- pass
145
-
146
- @abstractmethod
147
- def write_application_result(self, event: dict[str, typing.Any]):
117
+ event: dict[str, typing.Any],
118
+ kind: mm_constants.WriterEventKind = mm_constants.WriterEventKind.RESULT,
119
+ ):
148
120
  """
149
- Write a new application result event in the target table.
121
+ Write a new event in the target table.
150
122
 
151
123
  :param event: An event dictionary that represents the application result, should be corresponded to the
152
124
  schema defined in the :py:class:`~mlrun.common.schemas.model_monitoring.constants.WriterEvent`
153
125
  object.
126
+ :param kind: The type of the event, can be either "result" or "metric".
154
127
  """
155
128
  pass
156
129