SIENTIAPDE-1478
Refactor validation script and improve logging in API and model repository - Updated validation script to include 'e2e/' directory in code formatting and linting checks. - Enhanced error logging in API class to improve readability of error messages. - Refactored debug logging in model repository for better structured output. - Cleaned up import statements in various files for improved organization.
This commit is contained in:
@@ -148,7 +148,10 @@ class API(SientiaMonitoring):
|
|||||||
if len(written_tags) != len(tag_names):
|
if len(written_tags) != len(tag_names):
|
||||||
message = f'The number of written tags does not match the number of tag names: Expected {tag_names} tags, but {written_tags} tags were written.'
|
message = f'The number of written tags does not match the number of tag names: Expected {tag_names} tags, but {written_tags} tags were written.'
|
||||||
|
|
||||||
self.error(f"{message}\nResponse:\n {json.dumps(response_data, indent=4)}\nTags:\n {json.dumps(tags, indent=4)}", metadata)
|
self.error(
|
||||||
|
f'{message}\nResponse:\n {json.dumps(response_data, indent=4)}\nTags:\n {json.dumps(tags, indent=4)}',
|
||||||
|
metadata,
|
||||||
|
)
|
||||||
|
|
||||||
await self.send_notification_async(
|
await self.send_notification_async(
|
||||||
metadata=metadata,
|
metadata=metadata,
|
||||||
|
|||||||
@@ -6,13 +6,13 @@ with workflow.unsafe.imports_passed_through():
|
|||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from pandas import DataFrame
|
from pandas import DataFrame
|
||||||
from sientia_do.utils.formatters import create_sample_dict
|
|
||||||
from sientia_do.notifications.handlers import CoreNotificationHandler as NotificationHandler
|
from sientia_do.notifications.handlers import CoreNotificationHandler as NotificationHandler
|
||||||
from sientia_do.notifications.models import NotificationLevel
|
from sientia_do.notifications.models import NotificationLevel
|
||||||
from sientia_do.observability.logger import Logger
|
from sientia_do.observability.logger import Logger
|
||||||
from sientia_do.observability.metrics_controller import MetricsController
|
from sientia_do.observability.metrics_controller import MetricsController
|
||||||
from sientia_do.observability.sientia_monitoring import SientiaMonitoring
|
from sientia_do.observability.sientia_monitoring import SientiaMonitoring
|
||||||
from sientia_do.temporal.constants import DATETIME_FORMAT_WITH_TZ, now
|
from sientia_do.temporal.constants import DATETIME_FORMAT_WITH_TZ, now
|
||||||
|
from sientia_do.utils.formatters import create_sample_dict
|
||||||
|
|
||||||
from laborious import metrics
|
from laborious import metrics
|
||||||
from laborious.utils.filters.conditional_filters import (
|
from laborious.utils.filters.conditional_filters import (
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ with workflow.unsafe.imports_passed_through():
|
|||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from pandas import DataFrame, to_datetime
|
from pandas import DataFrame, to_datetime
|
||||||
from sientia_do.utils.formatters import create_sample_dict
|
|
||||||
from sientia_do.notifications.handlers import CoreNotificationHandler as NotificationHandler
|
from sientia_do.notifications.handlers import CoreNotificationHandler as NotificationHandler
|
||||||
from sientia_do.notifications.models import NotificationLevel
|
from sientia_do.notifications.models import NotificationLevel
|
||||||
from sientia_do.observability.logger import Logger
|
from sientia_do.observability.logger import Logger
|
||||||
@@ -18,6 +17,7 @@ with workflow.unsafe.imports_passed_through():
|
|||||||
DATETIME_FORMAT_WITH_TZ,
|
DATETIME_FORMAT_WITH_TZ,
|
||||||
now,
|
now,
|
||||||
)
|
)
|
||||||
|
from sientia_do.utils.formatters import create_sample_dict
|
||||||
|
|
||||||
from laborious.utils.repository.minio_repository import MinioRepository
|
from laborious.utils.repository.minio_repository import MinioRepository
|
||||||
from laborious.utils.repository.model_repository import MLFlowRepository
|
from laborious.utils.repository.model_repository import MLFlowRepository
|
||||||
@@ -159,7 +159,6 @@ class MLFlow(SientiaMonitoring):
|
|||||||
|
|
||||||
self.debug(f'Processed input data: \n {data.to_csv()}', metadata)
|
self.debug(f'Processed input data: \n {data.to_csv()}', metadata)
|
||||||
|
|
||||||
|
|
||||||
# Request transformation from MLFlow model
|
# Request transformation from MLFlow model
|
||||||
response_data = await self.model_monitoring_repository.transform(
|
response_data = await self.model_monitoring_repository.transform(
|
||||||
model_name, data, model_config, metadata
|
model_name, data, model_config, metadata
|
||||||
|
|||||||
@@ -1254,7 +1254,9 @@ class MLFlowRepository(SientiaMonitoring):
|
|||||||
input_index = data.index
|
input_index = data.index
|
||||||
start_time = datetime.now()
|
start_time = datetime.now()
|
||||||
|
|
||||||
self.debug(f'Data received for model prediction: {data.to_dict(orient="records")}', metadata)
|
self.debug(
|
||||||
|
f'Data received for model prediction: {data.to_dict(orient="records")}', metadata
|
||||||
|
)
|
||||||
|
|
||||||
# data.to_csv(
|
# data.to_csv(
|
||||||
# f"tmp/treated_data_{model_name}.csv", index=True)
|
# f"tmp/treated_data_{model_name}.csv", index=True)
|
||||||
@@ -1272,7 +1274,8 @@ class MLFlowRepository(SientiaMonitoring):
|
|||||||
|
|
||||||
if isinstance(predict_data, pd.DataFrame):
|
if isinstance(predict_data, pd.DataFrame):
|
||||||
self.debug(
|
self.debug(
|
||||||
f'Data received from model prediction: {predict_data.to_dict(orient="records")}', metadata
|
f'Data received from model prediction: {predict_data.to_dict(orient="records")}',
|
||||||
|
metadata,
|
||||||
)
|
)
|
||||||
|
|
||||||
# predict_data.to_csv(
|
# predict_data.to_csv(
|
||||||
|
|||||||
@@ -31,27 +31,20 @@ Environment Variables:
|
|||||||
|
|
||||||
from temporalio import client, workflow
|
from temporalio import client, workflow
|
||||||
from temporalio.runtime import PrometheusConfig, Runtime, TelemetryConfig
|
from temporalio.runtime import PrometheusConfig, Runtime, TelemetryConfig
|
||||||
from temporalio.worker import (
|
|
||||||
PollerBehaviorAutoscaling,
|
|
||||||
ResourceBasedSlotConfig,
|
|
||||||
Worker,
|
|
||||||
WorkerTuner,
|
|
||||||
)
|
|
||||||
|
|
||||||
with workflow.unsafe.imports_passed_through():
|
with workflow.unsafe.imports_passed_through():
|
||||||
import asyncio
|
import asyncio
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
from datetime import timedelta
|
|
||||||
|
|
||||||
from prometheus_client import start_http_server
|
from prometheus_client import start_http_server
|
||||||
|
from sientia_do.notifications.handlers import CoreNotificationHandler as NotificationHandler
|
||||||
|
from sientia_do.observability.logger import get_logger
|
||||||
from sientia_do.utils.connectors_config import (
|
from sientia_do.utils.connectors_config import (
|
||||||
build_api_config,
|
build_api_config,
|
||||||
build_mongodb_config,
|
build_mongodb_config,
|
||||||
build_postgres_config,
|
build_postgres_config,
|
||||||
)
|
)
|
||||||
from sientia_do.notifications.handlers import CoreNotificationHandler as NotificationHandler
|
|
||||||
from sientia_do.observability.logger import get_logger
|
|
||||||
|
|
||||||
from laborious import metrics
|
from laborious import metrics
|
||||||
from laborious.activities.activities import Activities
|
from laborious.activities.activities import Activities
|
||||||
@@ -60,6 +53,7 @@ with workflow.unsafe.imports_passed_through():
|
|||||||
build_mlflow_config,
|
build_mlflow_config,
|
||||||
build_opc_config,
|
build_opc_config,
|
||||||
)
|
)
|
||||||
|
from laborious.worker.prepare_worker import prepare_worker
|
||||||
from laborious.workflows.drift import Drift
|
from laborious.workflows.drift import Drift
|
||||||
from laborious.workflows.minimal_retrain import MinimalRetrain
|
from laborious.workflows.minimal_retrain import MinimalRetrain
|
||||||
from laborious.workflows.predictions_batch import PredictionsBatch
|
from laborious.workflows.predictions_batch import PredictionsBatch
|
||||||
@@ -68,11 +62,11 @@ with workflow.unsafe.imports_passed_through():
|
|||||||
FormatAndExportPrediction,
|
FormatAndExportPrediction,
|
||||||
)
|
)
|
||||||
from laborious.workflows.sub_workflows.prediction_process import PredictionProcess
|
from laborious.workflows.sub_workflows.prediction_process import PredictionProcess
|
||||||
from laborious.worker.prepare_worker import prepare_worker
|
|
||||||
|
|
||||||
POD_ID = os.getenv('POD_ID')
|
POD_ID = os.getenv('POD_ID')
|
||||||
SDK_METRICS_PORT = int(os.getenv('HTTP_SDK_METRICS_PORT', '9091'))
|
SDK_METRICS_PORT = int(os.getenv('HTTP_SDK_METRICS_PORT', '9091'))
|
||||||
|
|
||||||
|
|
||||||
async def main():
|
async def main():
|
||||||
"""
|
"""
|
||||||
Main entry point for the Laborious worker application.
|
Main entry point for the Laborious worker application.
|
||||||
@@ -215,7 +209,7 @@ async def main():
|
|||||||
activities.write_metrics,
|
activities.write_metrics,
|
||||||
],
|
],
|
||||||
logger=logger,
|
logger=logger,
|
||||||
)
|
),
|
||||||
]
|
]
|
||||||
|
|
||||||
handlers = []
|
handlers = []
|
||||||
|
|||||||
@@ -333,11 +333,13 @@ async def test_process_pi_web_api_response_with_errors(api):
|
|||||||
)
|
)
|
||||||
|
|
||||||
assert confidence == PI_WEB_API_PREDICTION_ERROR_CONFIDENCE
|
assert confidence == PI_WEB_API_PREDICTION_ERROR_CONFIDENCE
|
||||||
assert message == "The number of written tags does not match the number of tag names: Expected ['tag1', 'tag2'] tags, but ['tag2'] tags were written."
|
assert (
|
||||||
|
message
|
||||||
|
== "The number of written tags does not match the number of tag names: Expected ['tag1', 'tag2'] tags, but ['tag2'] tags were written."
|
||||||
|
)
|
||||||
assert api.emit_metric.call_count == 2
|
assert api.emit_metric.call_count == 2
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@mark.asyncio
|
@mark.asyncio
|
||||||
async def test_process_pi_web_api_response_missing_tags(api):
|
async def test_process_pi_web_api_response_missing_tags(api):
|
||||||
"""Test processing response when number of written tags doesn't match expected."""
|
"""Test processing response when number of written tags doesn't match expected."""
|
||||||
@@ -361,7 +363,10 @@ async def test_process_pi_web_api_response_missing_tags(api):
|
|||||||
)
|
)
|
||||||
|
|
||||||
assert confidence == PI_WEB_API_PREDICTION_ERROR_CONFIDENCE
|
assert confidence == PI_WEB_API_PREDICTION_ERROR_CONFIDENCE
|
||||||
assert message == "The number of written tags does not match the number of tag names: Expected ['tag1', 'tag2'] tags, but ['tag1'] tags were written."
|
assert (
|
||||||
|
message
|
||||||
|
== "The number of written tags does not match the number of tag names: Expected ['tag1', 'tag2'] tags, but ['tag1'] tags were written."
|
||||||
|
)
|
||||||
api.send_notification_async.assert_called_once()
|
api.send_notification_async.assert_called_once()
|
||||||
call_args = api.send_notification_async.call_args
|
call_args = api.send_notification_async.call_args
|
||||||
assert call_args.kwargs['notification_id'] == 'WRITE_PI_WEB_API_PREDICTION_ERROR'
|
assert call_args.kwargs['notification_id'] == 'WRITE_PI_WEB_API_PREDICTION_ERROR'
|
||||||
@@ -392,7 +397,10 @@ async def test_process_pi_web_api_response_missing_webid(api):
|
|||||||
)
|
)
|
||||||
|
|
||||||
assert confidence == PI_WEB_API_PREDICTION_ERROR_CONFIDENCE
|
assert confidence == PI_WEB_API_PREDICTION_ERROR_CONFIDENCE
|
||||||
assert message == "The number of written tags does not match the number of tag names: Expected ['tag1', 'tag2'] tags, but ['tag2'] tags were written."
|
assert (
|
||||||
|
message
|
||||||
|
== "The number of written tags does not match the number of tag names: Expected ['tag1', 'tag2'] tags, but ['tag2'] tags were written."
|
||||||
|
)
|
||||||
api.error.assert_any_call('The response did not contain some WebIds', metadata['metadata'])
|
api.error.assert_any_call('The response did not contain some WebIds', metadata['metadata'])
|
||||||
|
|
||||||
|
|
||||||
@@ -419,7 +427,10 @@ async def test_process_pi_web_api_response_missing_tag_name(api):
|
|||||||
)
|
)
|
||||||
|
|
||||||
assert confidence == PI_WEB_API_PREDICTION_ERROR_CONFIDENCE
|
assert confidence == PI_WEB_API_PREDICTION_ERROR_CONFIDENCE
|
||||||
assert message == "The number of written tags does not match the number of tag names: Expected ['tag1'] tags, but [] tags were written."
|
assert (
|
||||||
|
message
|
||||||
|
== "The number of written tags does not match the number of tag names: Expected ['tag1'] tags, but [] tags were written."
|
||||||
|
)
|
||||||
api.error.assert_any_call(
|
api.error.assert_any_call(
|
||||||
'The response did not contain the tag name for WebId unknown_web_id', metadata['metadata']
|
'The response did not contain the tag name for WebId unknown_web_id', metadata['metadata']
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -812,7 +812,14 @@ async def test_fit_models_not_df_target_name_none_and_not_in_model(
|
|||||||
data = MagicMock()
|
data = MagicMock()
|
||||||
|
|
||||||
output = await mlflow_repository.fit_models(
|
output = await mlflow_repository.fit_models(
|
||||||
'model_name', data, 'latest_production_id', metadata['metadata'], 'sklearn', False, 'pyfunc', None
|
'model_name',
|
||||||
|
data,
|
||||||
|
'latest_production_id',
|
||||||
|
metadata['metadata'],
|
||||||
|
'sklearn',
|
||||||
|
False,
|
||||||
|
'pyfunc',
|
||||||
|
None,
|
||||||
)
|
)
|
||||||
|
|
||||||
mlflow_repository.download_model.assert_has_calls(
|
mlflow_repository.download_model.assert_has_calls(
|
||||||
|
|||||||
@@ -70,14 +70,14 @@ FAILED_STEPS=()
|
|||||||
# Step 1: Code Formatting Check (Ruff)
|
# Step 1: Code Formatting Check (Ruff)
|
||||||
# - default: check only
|
# - default: check only
|
||||||
# - --fix: write changes
|
# - --fix: write changes
|
||||||
if ! run_step "1. Code Formatting (Ruff)" "if \$FIX_MODE; then ruff format laborious/ tests/; else ruff format --check laborious/ tests/; fi"; then
|
if ! run_step "1. Code Formatting (Ruff)" "if \$FIX_MODE; then ruff format laborious/ tests/; else ruff format --check laborious/ tests/ e2e/; fi"; then
|
||||||
FAILED_STEPS+=("Code Formatting")
|
FAILED_STEPS+=("Code Formatting")
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Step 2: Linting (Ruff)
|
# Step 2: Linting (Ruff)
|
||||||
# - default: check only
|
# - default: check only
|
||||||
# - --fix: apply autofixes
|
# - --fix: apply autofixes
|
||||||
if ! run_step "2. Code Linting (Ruff)" "if \$FIX_MODE; then ruff check --fix laborious/ tests/; else ruff check laborious/ tests/; fi"; then
|
if ! run_step "2. Code Linting (Ruff)" "if \$FIX_MODE; then ruff check --fix laborious/ tests/; else ruff check laborious/ tests/ e2e/; fi"; then
|
||||||
FAILED_STEPS+=("Linting")
|
FAILED_STEPS+=("Linting")
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user