Skip to content

Commit

Permalink
[Model Monitoring] Add MySQL support for saving and querying metrics (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
jond01 committed May 30, 2024
1 parent 36b5ff8 commit 47024a4
Show file tree
Hide file tree
Showing 9 changed files with 237 additions and 64 deletions.
1 change: 1 addition & 0 deletions mlrun/common/schemas/model_monitoring/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@ class FileTargetKind:
APPS_PARQUET = "apps_parquet"
LOG_STREAM = "log_stream"
APP_RESULTS = "app_results"
APP_METRICS = "app_metrics"
MONITORING_SCHEDULES = "monitoring_schedules"
MONITORING_APPLICATION = "monitoring_application"

Expand Down
2 changes: 0 additions & 2 deletions mlrun/model_monitoring/db/stores/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.

# flake8: noqa - this is until we take care of the F401 violations with respect to __all__ & sphinx

import enum
import typing
import warnings
Expand Down
3 changes: 1 addition & 2 deletions mlrun/model_monitoring/db/stores/base/store.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,6 @@ def write_application_event(
object.
:param kind: The type of the event, can be either "result" or "metric".
"""
pass

@abstractmethod
def get_last_analyzed(self, endpoint_id: str, application_name: str) -> int:
Expand Down Expand Up @@ -168,5 +167,5 @@ def get_model_endpoint_metrics(
:param: endpoint_id: The model endpoint identifier.
:param: type: The type of the requested metrics ("result" or "metric").
:return: A list of the available metrics.
:return: A list of the available metrics.
"""
8 changes: 8 additions & 0 deletions mlrun/model_monitoring/db/stores/sqldb/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,11 @@
from functools import partial
from typing import Optional, TypeVar, Union

from .mysql import ApplicationMetricsTable as MySQLApplicationMetricsTable
from .mysql import ApplicationResultTable as MySQLApplicationResultTable
from .mysql import ModelEndpointsTable as MySQLModelEndpointsTable
from .mysql import MonitoringSchedulesTable as MySQLMonitoringSchedulesTable
from .sqlite import ApplicationMetricsTable as SQLiteApplicationMetricsTable
from .sqlite import ApplicationResultTable as SQLiteApplicationResultTable
from .sqlite import ModelEndpointsTable as SQLiteModelEndpointsTable
from .sqlite import MonitoringSchedulesTable as SQLiteMonitoringSchedulesTable
Expand Down Expand Up @@ -56,6 +58,12 @@ def _get_sql_table(
sqlite_table=SQLiteApplicationResultTable,
)

_get_application_metrics_table = partial(
_get_sql_table,
mysql_table=MySQLApplicationMetricsTable,
sqlite_table=SQLiteApplicationMetricsTable,
)

_get_monitoring_schedules_table = partial(
_get_sql_table,
mysql_table=MySQLMonitoringSchedulesTable,
Expand Down
34 changes: 32 additions & 2 deletions mlrun/model_monitoring/db/stores/sqldb/models/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
from mlrun.common.schemas.model_monitoring import (
EventFieldType,
FileTargetKind,
MetricData,
ResultData,
SchedulingKeys,
WriterEvent,
Expand Down Expand Up @@ -89,11 +90,11 @@ class ModelEndpointsBaseTable(BaseModel):
metrics = Column(EventFieldType.METRICS, Text)
first_request = Column(
EventFieldType.FIRST_REQUEST,
TIMESTAMP,
TIMESTAMP(timezone=True),
)
last_request = Column(
EventFieldType.LAST_REQUEST,
TIMESTAMP,
TIMESTAMP(timezone=True),
)


Expand Down Expand Up @@ -135,6 +136,35 @@ class ApplicationResultBaseTable(BaseModel):
current_stats = Column(ResultData.CURRENT_STATS, Text)


class ApplicationMetricsBaseTable(BaseModel):
__tablename__ = FileTargetKind.APP_METRICS

uid = Column(EventFieldType.UID, String(120), primary_key=True)
application_name = Column(
WriterEvent.APPLICATION_NAME,
String(40),
nullable=True,
)
endpoint_id = Column(
WriterEvent.ENDPOINT_ID,
String(40),
nullable=True,
)
start_infer_time = Column(
WriterEvent.START_INFER_TIME,
TIMESTAMP(timezone=True),
)
end_infer_time = Column(
WriterEvent.END_INFER_TIME,
TIMESTAMP(timezone=True),
)
metric_name = Column(
MetricData.METRIC_NAME,
String(40),
)
metric_value = Column(MetricData.METRIC_VALUE, Float)


class MonitoringSchedulesBaseTable(BaseModel):
__tablename__ = FileTargetKind.MONITORING_SCHEDULES

Expand Down
30 changes: 25 additions & 5 deletions mlrun/model_monitoring/db/stores/sqldb/models/mysql.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
)

from .base import (
ApplicationMetricsBaseTable,
ApplicationResultBaseTable,
ModelEndpointsBaseTable,
MonitoringSchedulesBaseTable,
Expand All @@ -33,22 +34,29 @@
class ModelEndpointsTable(Base, ModelEndpointsBaseTable):
first_request = Column(
EventFieldType.FIRST_REQUEST,
sqlalchemy.dialects.mysql.TIMESTAMP(fsp=3),
sqlalchemy.dialects.mysql.TIMESTAMP(fsp=3, timezone=True),
)
last_request = Column(
EventFieldType.LAST_REQUEST,
sqlalchemy.dialects.mysql.TIMESTAMP(fsp=3),
sqlalchemy.dialects.mysql.TIMESTAMP(fsp=3, timezone=True),
)


class ApplicationResultTable(Base, ApplicationResultBaseTable):
class _ApplicationResultOrMetric:
"""
This class sets common columns of `ApplicationResultTable` and `ApplicationMetricsTable`
to the correct values in MySQL.
Note: This class must come before the base tables in the inheritance order to override
the relevant columns.
"""

start_infer_time = Column(
WriterEvent.START_INFER_TIME,
sqlalchemy.dialects.mysql.TIMESTAMP(fsp=3),
sqlalchemy.dialects.mysql.TIMESTAMP(fsp=3, timezone=True),
)
end_infer_time = Column(
WriterEvent.END_INFER_TIME,
sqlalchemy.dialects.mysql.TIMESTAMP(fsp=3),
sqlalchemy.dialects.mysql.TIMESTAMP(fsp=3, timezone=True),
)

@declared_attr
Expand All @@ -59,6 +67,18 @@ def endpoint_id(cls):
)


class ApplicationResultTable(
Base, _ApplicationResultOrMetric, ApplicationResultBaseTable
):
pass


class ApplicationMetricsTable(
Base, _ApplicationResultOrMetric, ApplicationMetricsBaseTable
):
pass


class MonitoringSchedulesTable(Base, MonitoringSchedulesBaseTable):
@declared_attr
def endpoint_id(cls):
Expand Down
5 changes: 5 additions & 0 deletions mlrun/model_monitoring/db/stores/sqldb/models/sqlite.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from sqlalchemy.ext.declarative import declarative_base

from .base import (
ApplicationMetricsBaseTable,
ApplicationResultBaseTable,
ModelEndpointsBaseTable,
MonitoringSchedulesBaseTable,
Expand All @@ -31,5 +32,9 @@ class ApplicationResultTable(Base, ApplicationResultBaseTable):
pass


class ApplicationMetricsTable(Base, ApplicationMetricsBaseTable):
pass


class MonitoringSchedulesTable(Base, MonitoringSchedulesBaseTable):
pass
Loading

0 comments on commit 47024a4

Please sign in to comment.