mlrun 1.7.0rc18__py3-none-any.whl → 1.7.0rc19__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 +5 -2
- mlrun/common/constants.py +64 -3
- mlrun/common/formatters/__init__.py +16 -0
- mlrun/common/formatters/base.py +59 -0
- mlrun/common/formatters/function.py +41 -0
- mlrun/common/runtimes/constants.py +29 -4
- mlrun/common/schemas/__init__.py +0 -1
- mlrun/common/schemas/api_gateway.py +52 -0
- mlrun/common/schemas/frontend_spec.py +1 -0
- mlrun/common/schemas/model_monitoring/__init__.py +6 -3
- mlrun/common/schemas/model_monitoring/constants.py +2 -7
- mlrun/config.py +7 -2
- mlrun/datastore/sources.py +16 -22
- mlrun/datastore/store_resources.py +5 -1
- mlrun/datastore/targets.py +3 -2
- mlrun/datastore/utils.py +42 -0
- mlrun/execution.py +16 -6
- mlrun/feature_store/ingestion.py +7 -6
- mlrun/feature_store/retrieval/job.py +4 -1
- mlrun/frameworks/parallel_coordinates.py +2 -1
- mlrun/frameworks/tf_keras/__init__.py +4 -1
- mlrun/launcher/client.py +4 -2
- mlrun/launcher/local.py +8 -2
- mlrun/launcher/remote.py +8 -2
- mlrun/model.py +5 -1
- mlrun/model_monitoring/db/stores/__init__.py +0 -2
- mlrun/model_monitoring/db/stores/base/store.py +1 -2
- mlrun/model_monitoring/db/stores/sqldb/models/__init__.py +43 -21
- mlrun/model_monitoring/db/stores/sqldb/models/base.py +32 -2
- mlrun/model_monitoring/db/stores/sqldb/models/mysql.py +25 -5
- mlrun/model_monitoring/db/stores/sqldb/models/sqlite.py +5 -0
- mlrun/model_monitoring/db/stores/sqldb/sql_store.py +207 -139
- mlrun/model_monitoring/db/tsdb/__init__.py +1 -1
- mlrun/model_monitoring/db/tsdb/base.py +225 -38
- mlrun/model_monitoring/db/tsdb/helpers.py +30 -0
- mlrun/model_monitoring/db/tsdb/tdengine/schemas.py +48 -15
- mlrun/model_monitoring/db/tsdb/tdengine/tdengine_connector.py +182 -16
- mlrun/model_monitoring/db/tsdb/v3io/v3io_connector.py +229 -42
- mlrun/model_monitoring/helpers.py +13 -0
- mlrun/model_monitoring/writer.py +36 -11
- mlrun/projects/operations.py +8 -5
- mlrun/projects/pipelines.py +42 -15
- mlrun/projects/project.py +22 -6
- mlrun/runtimes/base.py +2 -1
- mlrun/runtimes/local.py +4 -1
- mlrun/runtimes/nuclio/api_gateway.py +32 -8
- mlrun/runtimes/nuclio/application/application.py +3 -3
- mlrun/runtimes/nuclio/function.py +1 -4
- mlrun/runtimes/utils.py +5 -6
- mlrun/serving/server.py +2 -1
- mlrun/utils/helpers.py +8 -6
- mlrun/utils/logger.py +28 -1
- mlrun/utils/notifications/notification/__init__.py +14 -9
- mlrun/utils/notifications/notification_pusher.py +10 -3
- mlrun/utils/v3io_clients.py +0 -1
- mlrun/utils/version/version.json +2 -2
- {mlrun-1.7.0rc18.dist-info → mlrun-1.7.0rc19.dist-info}/METADATA +3 -3
- {mlrun-1.7.0rc18.dist-info → mlrun-1.7.0rc19.dist-info}/RECORD +62 -59
- mlrun/model_monitoring/db/v3io_tsdb_reader.py +0 -335
- {mlrun-1.7.0rc18.dist-info → mlrun-1.7.0rc19.dist-info}/LICENSE +0 -0
- {mlrun-1.7.0rc18.dist-info → mlrun-1.7.0rc19.dist-info}/WHEEL +0 -0
- {mlrun-1.7.0rc18.dist-info → mlrun-1.7.0rc19.dist-info}/entry_points.txt +0 -0
- {mlrun-1.7.0rc18.dist-info → mlrun-1.7.0rc19.dist-info}/top_level.txt +0 -0
mlrun/execution.py
CHANGED
|
@@ -22,6 +22,7 @@ import yaml
|
|
|
22
22
|
from dateutil import parser
|
|
23
23
|
|
|
24
24
|
import mlrun
|
|
25
|
+
import mlrun.common.constants as mlrun_constants
|
|
25
26
|
from mlrun.artifacts import ModelArtifact
|
|
26
27
|
from mlrun.datastore.store_resources import get_store_resource
|
|
27
28
|
from mlrun.errors import MLRunInvalidArgumentError
|
|
@@ -129,7 +130,9 @@ class MLClientCtx:
|
|
|
129
130
|
@property
|
|
130
131
|
def tag(self):
|
|
131
132
|
"""Run tag (uid or workflow id if exists)"""
|
|
132
|
-
return
|
|
133
|
+
return (
|
|
134
|
+
self._labels.get(mlrun_constants.MLRunInternalLabels.workflow) or self._uid
|
|
135
|
+
)
|
|
133
136
|
|
|
134
137
|
@property
|
|
135
138
|
def state(self):
|
|
@@ -329,8 +332,10 @@ class MLClientCtx:
|
|
|
329
332
|
"uri": uri,
|
|
330
333
|
"owner": get_in(self._labels, "owner"),
|
|
331
334
|
}
|
|
332
|
-
if
|
|
333
|
-
resp[
|
|
335
|
+
if mlrun_constants.MLRunInternalLabels.workflow in self._labels:
|
|
336
|
+
resp[mlrun_constants.MLRunInternalLabels.workflow] = self._labels[
|
|
337
|
+
mlrun_constants.MLRunInternalLabels.workflow
|
|
338
|
+
]
|
|
334
339
|
return resp
|
|
335
340
|
|
|
336
341
|
@classmethod
|
|
@@ -396,7 +401,7 @@ class MLClientCtx:
|
|
|
396
401
|
self._set_input(k, v)
|
|
397
402
|
|
|
398
403
|
if host and not is_api:
|
|
399
|
-
self.set_label(
|
|
404
|
+
self.set_label(mlrun_constants.MLRunInternalLabels.host, host)
|
|
400
405
|
|
|
401
406
|
start = get_in(attrs, "status.start_time")
|
|
402
407
|
if start:
|
|
@@ -990,10 +995,15 @@ class MLClientCtx:
|
|
|
990
995
|
# If it's a OpenMPI job, get the global rank and compare to the logging rank (worker) set in MLRun's
|
|
991
996
|
# configuration:
|
|
992
997
|
labels = self.labels
|
|
993
|
-
if
|
|
998
|
+
if (
|
|
999
|
+
mlrun_constants.MLRunInternalLabels.host in labels
|
|
1000
|
+
and labels.get(mlrun_constants.MLRunInternalLabels.kind, "job") == "mpijob"
|
|
1001
|
+
):
|
|
994
1002
|
# The host (pod name) of each worker is created by k8s, and by default it uses the rank number as the id in
|
|
995
1003
|
# the following template: ...-worker-<rank>
|
|
996
|
-
rank = int(
|
|
1004
|
+
rank = int(
|
|
1005
|
+
labels[mlrun_constants.MLRunInternalLabels.host].rsplit("-", 1)[1]
|
|
1006
|
+
)
|
|
997
1007
|
return rank == mlrun.mlconf.packagers.logging_worker
|
|
998
1008
|
|
|
999
1009
|
# Single worker is always the logging worker:
|
mlrun/feature_store/ingestion.py
CHANGED
|
@@ -17,6 +17,7 @@ import uuid
|
|
|
17
17
|
import pandas as pd
|
|
18
18
|
|
|
19
19
|
import mlrun
|
|
20
|
+
import mlrun.common.constants as mlrun_constants
|
|
20
21
|
from mlrun.datastore.sources import get_source_from_dict, get_source_step
|
|
21
22
|
from mlrun.datastore.targets import (
|
|
22
23
|
add_target_steps,
|
|
@@ -263,13 +264,13 @@ def run_ingestion_job(name, featureset, run_config, schedule=None, spark_service
|
|
|
263
264
|
out_path=featureset.spec.output_path,
|
|
264
265
|
)
|
|
265
266
|
task.spec.secret_sources = run_config.secret_sources
|
|
266
|
-
task.set_label(
|
|
267
|
-
"feature-
|
|
268
|
-
)
|
|
267
|
+
task.set_label(
|
|
268
|
+
mlrun_constants.MLRunInternalLabels.job_type, "feature-ingest"
|
|
269
|
+
).set_label("feature-set", featureset.uri)
|
|
269
270
|
if run_config.owner:
|
|
270
|
-
task.set_label(
|
|
271
|
-
|
|
272
|
-
)
|
|
271
|
+
task.set_label(
|
|
272
|
+
mlrun_constants.MLRunInternalLabels.owner, run_config.owner
|
|
273
|
+
).set_label(mlrun_constants.MLRunInternalLabels.v3io_user, run_config.owner)
|
|
273
274
|
|
|
274
275
|
# set run UID and save in the feature set status (linking the features et to the job)
|
|
275
276
|
task.metadata.uid = uuid.uuid4().hex
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
import uuid
|
|
16
16
|
|
|
17
17
|
import mlrun
|
|
18
|
+
import mlrun.common.constants as mlrun_constants
|
|
18
19
|
from mlrun.config import config as mlconf
|
|
19
20
|
from mlrun.model import DataTargetBase, new_task
|
|
20
21
|
from mlrun.runtimes.function_reference import FunctionReference
|
|
@@ -122,7 +123,9 @@ def run_merge_job(
|
|
|
122
123
|
inputs={"entity_rows": entity_rows} if entity_rows is not None else {},
|
|
123
124
|
)
|
|
124
125
|
task.spec.secret_sources = run_config.secret_sources
|
|
125
|
-
task.set_label(
|
|
126
|
+
task.set_label(
|
|
127
|
+
mlrun_constants.MLRunInternalLabels.job_type, "feature-merge"
|
|
128
|
+
).set_label(mlrun_constants.MLRunInternalLabels.feature_vector, vector.uri)
|
|
126
129
|
task.metadata.uid = uuid.uuid4().hex
|
|
127
130
|
vector.status.run_uri = task.metadata.uid
|
|
128
131
|
vector.save()
|
|
@@ -295,7 +295,7 @@ def compare_db_runs(
|
|
|
295
295
|
iter=False,
|
|
296
296
|
start_time_from: datetime = None,
|
|
297
297
|
hide_identical: bool = True,
|
|
298
|
-
exclude: list =
|
|
298
|
+
exclude: list = None,
|
|
299
299
|
show=None,
|
|
300
300
|
colorscale: str = "Blues",
|
|
301
301
|
filename=None,
|
|
@@ -332,6 +332,7 @@ def compare_db_runs(
|
|
|
332
332
|
**query_args,
|
|
333
333
|
)
|
|
334
334
|
|
|
335
|
+
exclude = exclude or []
|
|
335
336
|
runs_df = _runs_list_to_df(runs_list)
|
|
336
337
|
plot_as_html = gen_pcp_plot(
|
|
337
338
|
runs_df,
|
|
@@ -18,6 +18,7 @@ from typing import Any, Union
|
|
|
18
18
|
from tensorflow import keras
|
|
19
19
|
|
|
20
20
|
import mlrun
|
|
21
|
+
import mlrun.common.constants as mlrun_constants
|
|
21
22
|
|
|
22
23
|
from .callbacks import MLRunLoggingCallback, TensorboardLoggingCallback
|
|
23
24
|
from .mlrun_interface import TFKerasMLRunInterface
|
|
@@ -126,7 +127,9 @@ def apply_mlrun(
|
|
|
126
127
|
# # Use horovod:
|
|
127
128
|
if use_horovod is None:
|
|
128
129
|
use_horovod = (
|
|
129
|
-
context.labels.get(
|
|
130
|
+
context.labels.get(mlrun_constants.MLRunInternalLabels.kind, "") == "mpijob"
|
|
131
|
+
if context is not None
|
|
132
|
+
else False
|
|
130
133
|
)
|
|
131
134
|
|
|
132
135
|
# Create a model handler:
|
mlrun/launcher/client.py
CHANGED
|
@@ -16,6 +16,7 @@ from typing import Optional
|
|
|
16
16
|
|
|
17
17
|
import IPython
|
|
18
18
|
|
|
19
|
+
import mlrun.common.constants as mlrun_constants
|
|
19
20
|
import mlrun.errors
|
|
20
21
|
import mlrun.launcher.base as launcher
|
|
21
22
|
import mlrun.lists
|
|
@@ -69,13 +70,14 @@ class ClientBaseLauncher(launcher.BaseLauncher, abc.ABC):
|
|
|
69
70
|
def _store_function(
|
|
70
71
|
runtime: "mlrun.runtimes.BaseRuntime", run: "mlrun.run.RunObject"
|
|
71
72
|
):
|
|
72
|
-
run.metadata.labels[
|
|
73
|
+
run.metadata.labels[mlrun_constants.MLRunInternalLabels.kind] = runtime.kind
|
|
73
74
|
mlrun.runtimes.utils.enrich_run_labels(
|
|
74
75
|
run.metadata.labels, [mlrun.common.runtimes.constants.RunLabels.owner]
|
|
75
76
|
)
|
|
76
77
|
if run.spec.output_path:
|
|
77
78
|
run.spec.output_path = run.spec.output_path.replace(
|
|
78
|
-
"{{run.user}}",
|
|
79
|
+
"{{run.user}}",
|
|
80
|
+
run.metadata.labels[mlrun_constants.MLRunInternalLabels.owner],
|
|
79
81
|
)
|
|
80
82
|
db = runtime._get_db()
|
|
81
83
|
if db and runtime.kind != "handler":
|
mlrun/launcher/local.py
CHANGED
|
@@ -15,6 +15,7 @@ import os
|
|
|
15
15
|
import pathlib
|
|
16
16
|
from typing import Callable, Optional, Union
|
|
17
17
|
|
|
18
|
+
import mlrun.common.constants as mlrun_constants
|
|
18
19
|
import mlrun.common.schemas.schedule
|
|
19
20
|
import mlrun.errors
|
|
20
21
|
import mlrun.launcher.client as launcher
|
|
@@ -132,8 +133,13 @@ class ClientLocalLauncher(launcher.ClientBaseLauncher):
|
|
|
132
133
|
runtime: "mlrun.runtimes.BaseRuntime",
|
|
133
134
|
run: Optional[Union["mlrun.run.RunTemplate", "mlrun.run.RunObject"]] = None,
|
|
134
135
|
):
|
|
135
|
-
if
|
|
136
|
-
|
|
136
|
+
if (
|
|
137
|
+
"V3IO_USERNAME" in os.environ
|
|
138
|
+
and mlrun_constants.MLRunInternalLabels.v3io_user not in run.metadata.labels
|
|
139
|
+
):
|
|
140
|
+
run.metadata.labels[mlrun_constants.MLRunInternalLabels.v3io_user] = (
|
|
141
|
+
os.environ.get("V3IO_USERNAME")
|
|
142
|
+
)
|
|
137
143
|
|
|
138
144
|
# store function object in db unless running from within a run pod
|
|
139
145
|
if not runtime.is_child:
|
mlrun/launcher/remote.py
CHANGED
|
@@ -17,6 +17,7 @@ from typing import Optional, Union
|
|
|
17
17
|
import pandas as pd
|
|
18
18
|
import requests
|
|
19
19
|
|
|
20
|
+
import mlrun.common.constants as mlrun_constants
|
|
20
21
|
import mlrun.common.schemas.schedule
|
|
21
22
|
import mlrun.db
|
|
22
23
|
import mlrun.errors
|
|
@@ -100,8 +101,13 @@ class ClientRemoteLauncher(launcher.ClientBaseLauncher):
|
|
|
100
101
|
if runtime.verbose:
|
|
101
102
|
logger.info(f"runspec:\n{run.to_yaml()}")
|
|
102
103
|
|
|
103
|
-
if
|
|
104
|
-
|
|
104
|
+
if (
|
|
105
|
+
"V3IO_USERNAME" in os.environ
|
|
106
|
+
and mlrun_constants.MLRunInternalLabels.v3io_user not in run.metadata.labels
|
|
107
|
+
):
|
|
108
|
+
run.metadata.labels[mlrun_constants.MLRunInternalLabels.v3io_user] = (
|
|
109
|
+
os.environ.get("V3IO_USERNAME")
|
|
110
|
+
)
|
|
105
111
|
|
|
106
112
|
logger.info(
|
|
107
113
|
"Storing function",
|
mlrun/model.py
CHANGED
|
@@ -27,6 +27,7 @@ from typing import Any, Optional, Union
|
|
|
27
27
|
import pydantic.error_wrappers
|
|
28
28
|
|
|
29
29
|
import mlrun
|
|
30
|
+
import mlrun.common.constants as mlrun_constants
|
|
30
31
|
import mlrun.common.schemas.notification
|
|
31
32
|
|
|
32
33
|
from .utils import (
|
|
@@ -770,7 +771,10 @@ class RunMetadata(ModelObj):
|
|
|
770
771
|
def is_workflow_runner(self):
|
|
771
772
|
if not self.labels:
|
|
772
773
|
return False
|
|
773
|
-
return
|
|
774
|
+
return (
|
|
775
|
+
self.labels.get(mlrun_constants.MLRunInternalLabels.job_type, "")
|
|
776
|
+
== "workflow-runner"
|
|
777
|
+
)
|
|
774
778
|
|
|
775
779
|
|
|
776
780
|
class HyperParamStrategies:
|
|
@@ -12,8 +12,6 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
-
# flake8: noqa - this is until we take care of the F401 violations with respect to __all__ & sphinx
|
|
16
|
-
|
|
17
15
|
import enum
|
|
18
16
|
import typing
|
|
19
17
|
import warnings
|
|
@@ -125,7 +125,6 @@ class StoreBase(ABC):
|
|
|
125
125
|
object.
|
|
126
126
|
:param kind: The type of the event, can be either "result" or "metric".
|
|
127
127
|
"""
|
|
128
|
-
pass
|
|
129
128
|
|
|
130
129
|
@abstractmethod
|
|
131
130
|
def get_last_analyzed(self, endpoint_id: str, application_name: str) -> int:
|
|
@@ -168,5 +167,5 @@ class StoreBase(ABC):
|
|
|
168
167
|
:param: endpoint_id: The model endpoint identifier.
|
|
169
168
|
:param: type: The type of the requested metrics ("result" or "metric").
|
|
170
169
|
|
|
171
|
-
:return:
|
|
170
|
+
:return: A list of the available metrics.
|
|
172
171
|
"""
|
|
@@ -12,38 +12,60 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
-
from
|
|
15
|
+
from functools import partial
|
|
16
|
+
from typing import Optional, TypeVar, Union
|
|
16
17
|
|
|
18
|
+
from .mysql import ApplicationMetricsTable as MySQLApplicationMetricsTable
|
|
17
19
|
from .mysql import ApplicationResultTable as MySQLApplicationResultTable
|
|
18
20
|
from .mysql import ModelEndpointsTable as MySQLModelEndpointsTable
|
|
19
21
|
from .mysql import MonitoringSchedulesTable as MySQLMonitoringSchedulesTable
|
|
22
|
+
from .sqlite import ApplicationMetricsTable as SQLiteApplicationMetricsTable
|
|
20
23
|
from .sqlite import ApplicationResultTable as SQLiteApplicationResultTable
|
|
21
24
|
from .sqlite import ModelEndpointsTable as SQLiteModelEndpointsTable
|
|
22
25
|
from .sqlite import MonitoringSchedulesTable as SQLiteMonitoringSchedulesTable
|
|
23
26
|
|
|
27
|
+
MySQLTableType = TypeVar("MySQLTableType")
|
|
28
|
+
SQLiteTableType = TypeVar("SQLiteTableType")
|
|
24
29
|
|
|
25
|
-
|
|
26
|
-
connection_string: Optional[str] = None,
|
|
27
|
-
) -> Union[type[MySQLModelEndpointsTable], type[SQLiteModelEndpointsTable]]:
|
|
28
|
-
"""Return ModelEndpointsTable based on the provided connection string"""
|
|
29
|
-
if connection_string and "mysql:" in connection_string:
|
|
30
|
-
return MySQLModelEndpointsTable
|
|
31
|
-
return SQLiteModelEndpointsTable
|
|
30
|
+
_MYSQL_SCHEME = "mysql:"
|
|
32
31
|
|
|
33
32
|
|
|
34
|
-
def
|
|
33
|
+
def _get_sql_table(
|
|
34
|
+
*,
|
|
35
|
+
mysql_table: MySQLTableType,
|
|
36
|
+
sqlite_table: SQLiteTableType,
|
|
35
37
|
connection_string: Optional[str] = None,
|
|
36
|
-
) -> Union[
|
|
37
|
-
"""
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
38
|
+
) -> Union[MySQLTableType, SQLiteTableType]:
|
|
39
|
+
"""
|
|
40
|
+
Return a SQLAlchemy table for MySQL or SQLite according to the connection string.
|
|
41
|
+
Note: this function should not be directly used in other modules.
|
|
42
|
+
"""
|
|
43
|
+
if connection_string and _MYSQL_SCHEME in connection_string:
|
|
44
|
+
return mysql_table
|
|
45
|
+
return sqlite_table
|
|
41
46
|
|
|
42
47
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
48
|
+
_get_model_endpoints_table = partial(
|
|
49
|
+
_get_sql_table,
|
|
50
|
+
mysql_table=MySQLModelEndpointsTable,
|
|
51
|
+
sqlite_table=SQLiteModelEndpointsTable,
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
_get_application_result_table = partial(
|
|
56
|
+
_get_sql_table,
|
|
57
|
+
mysql_table=MySQLApplicationResultTable,
|
|
58
|
+
sqlite_table=SQLiteApplicationResultTable,
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
_get_application_metrics_table = partial(
|
|
62
|
+
_get_sql_table,
|
|
63
|
+
mysql_table=MySQLApplicationMetricsTable,
|
|
64
|
+
sqlite_table=SQLiteApplicationMetricsTable,
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
_get_monitoring_schedules_table = partial(
|
|
68
|
+
_get_sql_table,
|
|
69
|
+
mysql_table=MySQLMonitoringSchedulesTable,
|
|
70
|
+
sqlite_table=SQLiteMonitoringSchedulesTable,
|
|
71
|
+
)
|
|
@@ -24,6 +24,7 @@ from sqlalchemy import (
|
|
|
24
24
|
from mlrun.common.schemas.model_monitoring import (
|
|
25
25
|
EventFieldType,
|
|
26
26
|
FileTargetKind,
|
|
27
|
+
MetricData,
|
|
27
28
|
ResultData,
|
|
28
29
|
SchedulingKeys,
|
|
29
30
|
WriterEvent,
|
|
@@ -89,11 +90,11 @@ class ModelEndpointsBaseTable(BaseModel):
|
|
|
89
90
|
metrics = Column(EventFieldType.METRICS, Text)
|
|
90
91
|
first_request = Column(
|
|
91
92
|
EventFieldType.FIRST_REQUEST,
|
|
92
|
-
TIMESTAMP,
|
|
93
|
+
TIMESTAMP(timezone=True),
|
|
93
94
|
)
|
|
94
95
|
last_request = Column(
|
|
95
96
|
EventFieldType.LAST_REQUEST,
|
|
96
|
-
TIMESTAMP,
|
|
97
|
+
TIMESTAMP(timezone=True),
|
|
97
98
|
)
|
|
98
99
|
|
|
99
100
|
|
|
@@ -135,6 +136,35 @@ class ApplicationResultBaseTable(BaseModel):
|
|
|
135
136
|
current_stats = Column(ResultData.CURRENT_STATS, Text)
|
|
136
137
|
|
|
137
138
|
|
|
139
|
+
class ApplicationMetricsBaseTable(BaseModel):
|
|
140
|
+
__tablename__ = FileTargetKind.APP_METRICS
|
|
141
|
+
|
|
142
|
+
uid = Column(EventFieldType.UID, String(120), primary_key=True)
|
|
143
|
+
application_name = Column(
|
|
144
|
+
WriterEvent.APPLICATION_NAME,
|
|
145
|
+
String(40),
|
|
146
|
+
nullable=True,
|
|
147
|
+
)
|
|
148
|
+
endpoint_id = Column(
|
|
149
|
+
WriterEvent.ENDPOINT_ID,
|
|
150
|
+
String(40),
|
|
151
|
+
nullable=True,
|
|
152
|
+
)
|
|
153
|
+
start_infer_time = Column(
|
|
154
|
+
WriterEvent.START_INFER_TIME,
|
|
155
|
+
TIMESTAMP(timezone=True),
|
|
156
|
+
)
|
|
157
|
+
end_infer_time = Column(
|
|
158
|
+
WriterEvent.END_INFER_TIME,
|
|
159
|
+
TIMESTAMP(timezone=True),
|
|
160
|
+
)
|
|
161
|
+
metric_name = Column(
|
|
162
|
+
MetricData.METRIC_NAME,
|
|
163
|
+
String(40),
|
|
164
|
+
)
|
|
165
|
+
metric_value = Column(MetricData.METRIC_VALUE, Float)
|
|
166
|
+
|
|
167
|
+
|
|
138
168
|
class MonitoringSchedulesBaseTable(BaseModel):
|
|
139
169
|
__tablename__ = FileTargetKind.MONITORING_SCHEDULES
|
|
140
170
|
|
|
@@ -22,6 +22,7 @@ from mlrun.common.schemas.model_monitoring import (
|
|
|
22
22
|
)
|
|
23
23
|
|
|
24
24
|
from .base import (
|
|
25
|
+
ApplicationMetricsBaseTable,
|
|
25
26
|
ApplicationResultBaseTable,
|
|
26
27
|
ModelEndpointsBaseTable,
|
|
27
28
|
MonitoringSchedulesBaseTable,
|
|
@@ -33,22 +34,29 @@ Base = declarative_base()
|
|
|
33
34
|
class ModelEndpointsTable(Base, ModelEndpointsBaseTable):
|
|
34
35
|
first_request = Column(
|
|
35
36
|
EventFieldType.FIRST_REQUEST,
|
|
36
|
-
sqlalchemy.dialects.mysql.TIMESTAMP(fsp=3),
|
|
37
|
+
sqlalchemy.dialects.mysql.TIMESTAMP(fsp=3, timezone=True),
|
|
37
38
|
)
|
|
38
39
|
last_request = Column(
|
|
39
40
|
EventFieldType.LAST_REQUEST,
|
|
40
|
-
sqlalchemy.dialects.mysql.TIMESTAMP(fsp=3),
|
|
41
|
+
sqlalchemy.dialects.mysql.TIMESTAMP(fsp=3, timezone=True),
|
|
41
42
|
)
|
|
42
43
|
|
|
43
44
|
|
|
44
|
-
class
|
|
45
|
+
class _ApplicationResultOrMetric:
|
|
46
|
+
"""
|
|
47
|
+
This class sets common columns of `ApplicationResultTable` and `ApplicationMetricsTable`
|
|
48
|
+
to the correct values in MySQL.
|
|
49
|
+
Note: This class must come before the base tables in the inheritance order to override
|
|
50
|
+
the relevant columns.
|
|
51
|
+
"""
|
|
52
|
+
|
|
45
53
|
start_infer_time = Column(
|
|
46
54
|
WriterEvent.START_INFER_TIME,
|
|
47
|
-
sqlalchemy.dialects.mysql.TIMESTAMP(fsp=3),
|
|
55
|
+
sqlalchemy.dialects.mysql.TIMESTAMP(fsp=3, timezone=True),
|
|
48
56
|
)
|
|
49
57
|
end_infer_time = Column(
|
|
50
58
|
WriterEvent.END_INFER_TIME,
|
|
51
|
-
sqlalchemy.dialects.mysql.TIMESTAMP(fsp=3),
|
|
59
|
+
sqlalchemy.dialects.mysql.TIMESTAMP(fsp=3, timezone=True),
|
|
52
60
|
)
|
|
53
61
|
|
|
54
62
|
@declared_attr
|
|
@@ -59,6 +67,18 @@ class ApplicationResultTable(Base, ApplicationResultBaseTable):
|
|
|
59
67
|
)
|
|
60
68
|
|
|
61
69
|
|
|
70
|
+
class ApplicationResultTable(
|
|
71
|
+
Base, _ApplicationResultOrMetric, ApplicationResultBaseTable
|
|
72
|
+
):
|
|
73
|
+
pass
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
class ApplicationMetricsTable(
|
|
77
|
+
Base, _ApplicationResultOrMetric, ApplicationMetricsBaseTable
|
|
78
|
+
):
|
|
79
|
+
pass
|
|
80
|
+
|
|
81
|
+
|
|
62
82
|
class MonitoringSchedulesTable(Base, MonitoringSchedulesBaseTable):
|
|
63
83
|
@declared_attr
|
|
64
84
|
def endpoint_id(cls):
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
from sqlalchemy.ext.declarative import declarative_base
|
|
16
16
|
|
|
17
17
|
from .base import (
|
|
18
|
+
ApplicationMetricsBaseTable,
|
|
18
19
|
ApplicationResultBaseTable,
|
|
19
20
|
ModelEndpointsBaseTable,
|
|
20
21
|
MonitoringSchedulesBaseTable,
|
|
@@ -31,5 +32,9 @@ class ApplicationResultTable(Base, ApplicationResultBaseTable):
|
|
|
31
32
|
pass
|
|
32
33
|
|
|
33
34
|
|
|
35
|
+
class ApplicationMetricsTable(Base, ApplicationMetricsBaseTable):
|
|
36
|
+
pass
|
|
37
|
+
|
|
38
|
+
|
|
34
39
|
class MonitoringSchedulesTable(Base, MonitoringSchedulesBaseTable):
|
|
35
40
|
pass
|