SIENTIAPDE-1325
Update logging in MLFlowRepository and OpcRepository to use unified logging methods - Refactored logging calls in MLFlowRepository to replace `self.logger.info` and `self.logger.debug` with `self.info` and `self.debug` for consistency. - Updated connection logging in OpcRepository to format the connection message properly. - Adjusted test cases to reflect changes in logging behavior and ensure proper assertions.
This commit is contained in:
1
.github/workflows/release.yml
vendored
1
.github/workflows/release.yml
vendored
@@ -8,6 +8,7 @@ on:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
release:
|
release:
|
||||||
|
if: github.event.pull_request.merged == true
|
||||||
uses: Aignosi/github_workflow_templates/.github/workflows/dataops-module-release.yml@main
|
uses: Aignosi/github_workflow_templates/.github/workflows/dataops-module-release.yml@main
|
||||||
permissions: write-all
|
permissions: write-all
|
||||||
with:
|
with:
|
||||||
|
|||||||
@@ -105,7 +105,9 @@ class OPC(SientiaMonitoring):
|
|||||||
attachment_content=error_data.get('attachment_content', None),
|
attachment_content=error_data.get('attachment_content', None),
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
self.logger.info(f'OPC server {opc_id}:{server["server_name"]} connected successfully.')
|
self.logger.info(
|
||||||
|
f'OPC server {opc_id}:{server["server_name"]} connected successfully.'
|
||||||
|
)
|
||||||
|
|
||||||
async def write_data(
|
async def write_data(
|
||||||
self,
|
self,
|
||||||
|
|||||||
@@ -243,7 +243,7 @@ class MLFlowRepository(SientiaMonitoring):
|
|||||||
rmtree(full_path)
|
rmtree(full_path)
|
||||||
makedirs(output_dir, exist_ok=True)
|
makedirs(output_dir, exist_ok=True)
|
||||||
|
|
||||||
self.logger.info(f'Downloading artifacts from {run_id} to {output_dir}')
|
self.info(f'Downloading artifacts from {run_id} to {output_dir}')
|
||||||
|
|
||||||
core_labels = self.get_core_labels(metadata, operation_type='download_artifacts')
|
core_labels = self.get_core_labels(metadata, operation_type='download_artifacts')
|
||||||
|
|
||||||
@@ -279,7 +279,7 @@ class MLFlowRepository(SientiaMonitoring):
|
|||||||
- Warnings during the model loading process are suppressed.
|
- Warnings during the model loading process are suppressed.
|
||||||
"""
|
"""
|
||||||
model_uri = f'models:/{model_name}/production'
|
model_uri = f'models:/{model_name}/production'
|
||||||
self.logger.info(f'Loading prediction model {model_name} from {model_uri}')
|
self.info(f'Loading prediction model {model_name} from {model_uri}')
|
||||||
|
|
||||||
core_labels = self.get_core_labels(metadata, operation_type='load_predict_model')
|
core_labels = self.get_core_labels(metadata, operation_type='load_predict_model')
|
||||||
start_time = time.time()
|
start_time = time.time()
|
||||||
@@ -326,7 +326,7 @@ class MLFlowRepository(SientiaMonitoring):
|
|||||||
latest_production_id = self.get_model_run_id(model_name=model_name, stage='Production')
|
latest_production_id = self.get_model_run_id(model_name=model_name, stage='Production')
|
||||||
model_uri = self.get_model_uri(latest_production_id, prediction=False)
|
model_uri = self.get_model_uri(latest_production_id, prediction=False)
|
||||||
|
|
||||||
self.logger.info(f'Loading data model {model_name} from {model_uri}')
|
self.info(f'Loading data model {model_name} from {model_uri}')
|
||||||
|
|
||||||
core_labels = self.get_core_labels(metadata, operation_type='load_transform_model')
|
core_labels = self.get_core_labels(metadata, operation_type='load_transform_model')
|
||||||
start_time = time.time()
|
start_time = time.time()
|
||||||
@@ -370,7 +370,7 @@ class MLFlowRepository(SientiaMonitoring):
|
|||||||
tuple[Any, str | None]: Model object and optional artifact path.
|
tuple[Any, str | None]: Model object and optional artifact path.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
self.logger.info(
|
self.info(
|
||||||
f'Downloading {model_type} model {model_name} with flavor {flavor} and load_wrapper {load_wrapper}'
|
f'Downloading {model_type} model {model_name} with flavor {flavor} and load_wrapper {load_wrapper}'
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -380,15 +380,13 @@ class MLFlowRepository(SientiaMonitoring):
|
|||||||
artifact_path = None
|
artifact_path = None
|
||||||
|
|
||||||
if load_wrapper:
|
if load_wrapper:
|
||||||
self.logger.info(
|
self.info(f'Loading wrapper for {model_type} model {model_name} with flavor {flavor}')
|
||||||
f'Loading wrapper for {model_type} model {model_name} with flavor {flavor}'
|
|
||||||
)
|
|
||||||
|
|
||||||
target = 'prediction_model' if model_type == 'predict' else 'data_model'
|
target = 'prediction_model' if model_type == 'predict' else 'data_model'
|
||||||
|
|
||||||
artifact_path = await self.dowload_artifacts(model_name, metadata, target)
|
artifact_path = await self.dowload_artifacts(model_name, metadata, target)
|
||||||
|
|
||||||
self.logger.info(
|
self.info(
|
||||||
f'Model with type {model_type} and name {model_name} is compressed, loading from {artifact_path}'
|
f'Model with type {model_type} and name {model_name} is compressed, loading from {artifact_path}'
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -423,12 +421,16 @@ class MLFlowRepository(SientiaMonitoring):
|
|||||||
Returns:
|
Returns:
|
||||||
pd.DataFrame: DataFrame with converted datetime index.
|
pd.DataFrame: DataFrame with converted datetime index.
|
||||||
"""
|
"""
|
||||||
|
if data.empty:
|
||||||
|
self.info('Data is empty, skipping datetime index detection and parsing', metadata)
|
||||||
|
return data
|
||||||
|
|
||||||
index = data.index
|
index = data.index
|
||||||
|
|
||||||
# Get type of first element of index
|
# Get type of first element of index
|
||||||
index_type = type(index[0])
|
index_type = type(index[0])
|
||||||
|
|
||||||
self.logger.custom_info(f'Index type: {index_type}', metadata)
|
self.info(f'Index type: {index_type}', metadata)
|
||||||
|
|
||||||
message = f'Index must be all timestamp like column. Valid formats are: pandas Timestamp, datetime, string in format {DATETIME_FORMAT_WITH_TZ}.'
|
message = f'Index must be all timestamp like column. Valid formats are: pandas Timestamp, datetime, string in format {DATETIME_FORMAT_WITH_TZ}.'
|
||||||
|
|
||||||
@@ -488,7 +490,7 @@ class MLFlowRepository(SientiaMonitoring):
|
|||||||
Returns:
|
Returns:
|
||||||
dict: Model configuration.
|
dict: Model configuration.
|
||||||
"""
|
"""
|
||||||
self.logger.debug(f'Model {model_name} is still valid, using cached version')
|
self.debug(f'Model {model_name} is still valid, using cached version')
|
||||||
|
|
||||||
return cache['target']
|
return cache['target']
|
||||||
|
|
||||||
@@ -503,7 +505,7 @@ class MLFlowRepository(SientiaMonitoring):
|
|||||||
Returns:
|
Returns:
|
||||||
None
|
None
|
||||||
"""
|
"""
|
||||||
self.logger.debug(f'Model {model_name} is outdated, downloading a new one')
|
self.debug(f'Model {model_name} is outdated, downloading a new one')
|
||||||
|
|
||||||
del self.model_cache[model_key]['target']
|
del self.model_cache[model_key]['target']
|
||||||
del self.model_cache[model_key]
|
del self.model_cache[model_key]
|
||||||
@@ -554,7 +556,7 @@ class MLFlowRepository(SientiaMonitoring):
|
|||||||
# Model is outdated, delete old model files
|
# Model is outdated, delete old model files
|
||||||
self.handle_outdated_model(model_name=model_name, model_key=model_key)
|
self.handle_outdated_model(model_name=model_name, model_key=model_key)
|
||||||
else:
|
else:
|
||||||
self.logger.debug(
|
self.debug(
|
||||||
f'Model {model_name} is not in {model_type} cache, downloading a new one'
|
f'Model {model_name} is not in {model_type} cache, downloading a new one'
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -631,7 +633,7 @@ class MLFlowRepository(SientiaMonitoring):
|
|||||||
prediction = model.predict(data)
|
prediction = model.predict(data)
|
||||||
|
|
||||||
if retention == 0:
|
if retention == 0:
|
||||||
self.logger.info(f'Deleting model {model_name}:{operation} from memory')
|
self.info(f'Deleting model {model_name}:{operation} from memory')
|
||||||
del model
|
del model
|
||||||
|
|
||||||
force_memory_release(self.logger)
|
force_memory_release(self.logger)
|
||||||
@@ -675,8 +677,8 @@ class MLFlowRepository(SientiaMonitoring):
|
|||||||
`data_model`, including optional artifact paths.
|
`data_model`, including optional artifact paths.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
self.logger.custom_info(f'Starting model experiment creation for {model_name}', metadata)
|
self.info(f'Starting model experiment creation for {model_name}', metadata)
|
||||||
self.logger.custom_debug(
|
self.debug(
|
||||||
f'Model configuration - transform_flavor: {transform_flavor}, predict_flavor: {predict_flavor}, target_name: {target_name}',
|
f'Model configuration - transform_flavor: {transform_flavor}, predict_flavor: {predict_flavor}, target_name: {target_name}',
|
||||||
metadata,
|
metadata,
|
||||||
)
|
)
|
||||||
@@ -684,10 +686,8 @@ class MLFlowRepository(SientiaMonitoring):
|
|||||||
# data.to_csv(
|
# data.to_csv(
|
||||||
# f"tmp/retrain_data_{model_name}.csv", index=True)
|
# f"tmp/retrain_data_{model_name}.csv", index=True)
|
||||||
|
|
||||||
self.logger.custom_info(
|
self.info(f'Retrieved latest production run ID: {latest_production_id}', metadata)
|
||||||
f'Retrieved latest production run ID: {latest_production_id}', metadata
|
self.info(f'Loading transformation model for {model_name}', metadata)
|
||||||
)
|
|
||||||
self.logger.custom_info(f'Loading transformation model for {model_name}', metadata)
|
|
||||||
|
|
||||||
load_transform_wrapper = transform_flavor == 'pyfunc'
|
load_transform_wrapper = transform_flavor == 'pyfunc'
|
||||||
|
|
||||||
@@ -699,7 +699,7 @@ class MLFlowRepository(SientiaMonitoring):
|
|||||||
load_wrapper=load_transform_wrapper,
|
load_wrapper=load_transform_wrapper,
|
||||||
)
|
)
|
||||||
|
|
||||||
self.logger.custom_info(f'Loading prediction model for {model_name}', metadata)
|
self.info(f'Loading prediction model for {model_name}', metadata)
|
||||||
|
|
||||||
load_predict_wrapper = predict_flavor == 'pyfunc'
|
load_predict_wrapper = predict_flavor == 'pyfunc'
|
||||||
|
|
||||||
@@ -728,24 +728,22 @@ class MLFlowRepository(SientiaMonitoring):
|
|||||||
|
|
||||||
treated_data = treated_data.drop_duplicates(subset=['timestamp'], keep='first')
|
treated_data = treated_data.drop_duplicates(subset=['timestamp'], keep='first')
|
||||||
|
|
||||||
self.logger.custom_debug(f'Treated data index: {treated_data.index}', metadata)
|
self.debug(f'Treated data index: {treated_data.index}', metadata)
|
||||||
|
|
||||||
# treated_data.to_csv(
|
# treated_data.to_csv(
|
||||||
# f"tmp/retrain_treated_data_{model_name}.csv", index=True)
|
# f"tmp/retrain_treated_data_{model_name}.csv", index=True)
|
||||||
|
|
||||||
self.logger.custom_debug(f'Transformed data shape: {treated_data.shape}', metadata)
|
self.debug(f'Transformed data shape: {treated_data.shape}', metadata)
|
||||||
|
|
||||||
if target_name is None:
|
if target_name is None:
|
||||||
target_name = data_model.target_variable
|
target_name = data_model.target_variable
|
||||||
self.logger.custom_debug(
|
self.debug(f'Using target variable from data model: {target_name}', metadata)
|
||||||
f'Using target variable from data model: {target_name}', metadata
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
self.logger.custom_debug(f'Using provided target variable: {target_name}', metadata)
|
self.debug(f'Using provided target variable: {target_name}', metadata)
|
||||||
|
|
||||||
# Check if treated_data contains target variable
|
# Check if treated_data contains target variable
|
||||||
if target_name not in treated_data.columns:
|
if target_name not in treated_data.columns:
|
||||||
self.logger.custom_debug(
|
self.debug(
|
||||||
f'Target variable {target_name} not found in treated data, aligning data with treated data indexes',
|
f'Target variable {target_name} not found in treated data, aligning data with treated data indexes',
|
||||||
metadata,
|
metadata,
|
||||||
)
|
)
|
||||||
@@ -757,9 +755,7 @@ class MLFlowRepository(SientiaMonitoring):
|
|||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
# Uses target variable from treated data
|
# Uses target variable from treated data
|
||||||
self.logger.custom_debug(
|
self.debug(f'Target variable {target_name} found in treated data, using it', metadata)
|
||||||
f'Target variable {target_name} found in treated data, using it', metadata
|
|
||||||
)
|
|
||||||
retrain_dataset = treated_data
|
retrain_dataset = treated_data
|
||||||
|
|
||||||
# retrain_dataset.to_csv(
|
# retrain_dataset.to_csv(
|
||||||
@@ -767,9 +763,7 @@ class MLFlowRepository(SientiaMonitoring):
|
|||||||
|
|
||||||
prediction_model.fit(retrain_dataset)
|
prediction_model.fit(retrain_dataset)
|
||||||
|
|
||||||
self.logger.custom_info(
|
self.info(f'Model experiment creation completed successfully for {model_name}', metadata)
|
||||||
f'Model experiment creation completed successfully for {model_name}', metadata
|
|
||||||
)
|
|
||||||
|
|
||||||
retrain_data = {
|
retrain_data = {
|
||||||
'prediction_model': {
|
'prediction_model': {
|
||||||
@@ -791,7 +785,7 @@ class MLFlowRepository(SientiaMonitoring):
|
|||||||
"""
|
"""
|
||||||
model = model_data['model']
|
model = model_data['model']
|
||||||
|
|
||||||
self.logger.custom_debug(f'Logging {model_type} model to {model_type}', metadata)
|
self.debug(f'Logging {model_type} model to {model_type}', metadata)
|
||||||
|
|
||||||
core_labels = self.get_core_labels(metadata, operation_type='log_model')
|
core_labels = self.get_core_labels(metadata, operation_type='log_model')
|
||||||
start_time = time.time()
|
start_time = time.time()
|
||||||
@@ -802,11 +796,11 @@ class MLFlowRepository(SientiaMonitoring):
|
|||||||
elif flavor == 'pyfunc':
|
elif flavor == 'pyfunc':
|
||||||
code_path = [path.join(model_data['artifact_path'], 'code', 'utils')]
|
code_path = [path.join(model_data['artifact_path'], 'code', 'utils')]
|
||||||
|
|
||||||
self.logger.custom_debug(f'Code path: {code_path}', metadata)
|
self.debug(f'Code path: {code_path}', metadata)
|
||||||
|
|
||||||
model.store_model(artifact_path=model_type, code_path=code_path, to_disk=False)
|
model.store_model(artifact_path=model_type, code_path=code_path, to_disk=False)
|
||||||
|
|
||||||
self.logger.custom_debug('Model uploaded successfully', metadata)
|
self.debug('Model uploaded successfully', metadata)
|
||||||
elif flavor == 'pytorch':
|
elif flavor == 'pytorch':
|
||||||
mlflow.pytorch.log_model(model, model_type)
|
mlflow.pytorch.log_model(model, model_type)
|
||||||
else:
|
else:
|
||||||
@@ -858,7 +852,7 @@ class MLFlowRepository(SientiaMonitoring):
|
|||||||
|
|
||||||
model_temp_path = path.join(ARTIFACTS_PATH, model_name)
|
model_temp_path = path.join(ARTIFACTS_PATH, model_name)
|
||||||
|
|
||||||
self.logger.custom_info(f'Starting model retraining process for {model_name}', metadata)
|
self.info(f'Starting model retraining process for {model_name}', metadata)
|
||||||
|
|
||||||
original_params = self.get_model_params(latest_production_id)
|
original_params = self.get_model_params(latest_production_id)
|
||||||
retrain_params = {
|
retrain_params = {
|
||||||
@@ -875,7 +869,7 @@ class MLFlowRepository(SientiaMonitoring):
|
|||||||
|
|
||||||
current_run_name = self.get_next_run_name(experiment_name)
|
current_run_name = self.get_next_run_name(experiment_name)
|
||||||
|
|
||||||
self.logger.custom_debug(f'Attributes: {retrain_params}', metadata)
|
self.debug(f'Attributes: {retrain_params}', metadata)
|
||||||
|
|
||||||
data_path = f'{model_temp_path}/retrain_data.csv'
|
data_path = f'{model_temp_path}/retrain_data.csv'
|
||||||
|
|
||||||
@@ -883,7 +877,7 @@ class MLFlowRepository(SientiaMonitoring):
|
|||||||
|
|
||||||
data.to_csv(data_path, index=True)
|
data.to_csv(data_path, index=True)
|
||||||
|
|
||||||
self.logger.custom_info(
|
self.info(
|
||||||
f'Starting model upload for {experiment_name} with run name {current_run_name}',
|
f'Starting model upload for {experiment_name} with run name {current_run_name}',
|
||||||
metadata,
|
metadata,
|
||||||
)
|
)
|
||||||
@@ -897,17 +891,17 @@ class MLFlowRepository(SientiaMonitoring):
|
|||||||
description=experiment_description,
|
description=experiment_description,
|
||||||
) as _run:
|
) as _run:
|
||||||
run_id = _run.info.run_id
|
run_id = _run.info.run_id
|
||||||
self.logger.custom_info('Logging data model', metadata)
|
self.info('Logging data model', metadata)
|
||||||
# dynamic parameters, including model itself
|
# dynamic parameters, including model itself
|
||||||
await self.log_model(data_model, transform_flavor, 'data_model', metadata)
|
await self.log_model(data_model, transform_flavor, 'data_model', metadata)
|
||||||
|
|
||||||
# dynamic parameters, including model itself
|
# dynamic parameters, including model itself
|
||||||
self.logger.custom_info('Logging prediction model', metadata)
|
self.info('Logging prediction model', metadata)
|
||||||
await self.log_model(prediction_model, predict_flavor, 'prediction_model', metadata)
|
await self.log_model(prediction_model, predict_flavor, 'prediction_model', metadata)
|
||||||
|
|
||||||
self.logger.custom_info(f'Model logged successfully for {model_name}', metadata)
|
self.info(f'Model logged successfully for {model_name}', metadata)
|
||||||
|
|
||||||
self.logger.custom_info(f'Logging remaining parameters for {model_name}', metadata)
|
self.info(f'Logging remaining parameters for {model_name}', metadata)
|
||||||
|
|
||||||
# update transfomation model
|
# update transfomation model
|
||||||
# fixed parameters
|
# fixed parameters
|
||||||
@@ -923,15 +917,15 @@ class MLFlowRepository(SientiaMonitoring):
|
|||||||
await self.observe_lag(start_time, metrics.MODEL_WRITE_LAG, core_labels)
|
await self.observe_lag(start_time, metrics.MODEL_WRITE_LAG, core_labels)
|
||||||
await self.emit_metric(metric_object=metrics.MODEL_WRITE_COUNT, tags=core_labels)
|
await self.emit_metric(metric_object=metrics.MODEL_WRITE_COUNT, tags=core_labels)
|
||||||
|
|
||||||
self.logger.custom_info('Deleting model from filesystem', metadata)
|
self.info('Deleting model from filesystem', metadata)
|
||||||
if path.exists(model_temp_path):
|
if path.exists(model_temp_path):
|
||||||
rmtree(model_temp_path)
|
rmtree(model_temp_path)
|
||||||
|
|
||||||
self.logger.custom_info('Deleting prediction model from memory', metadata)
|
self.info('Deleting prediction model from memory', metadata)
|
||||||
del prediction_model['model']
|
del prediction_model['model']
|
||||||
del prediction_model
|
del prediction_model
|
||||||
|
|
||||||
self.logger.custom_info('Deleting data model from memory', metadata)
|
self.info('Deleting data model from memory', metadata)
|
||||||
del data_model['model']
|
del data_model['model']
|
||||||
del data_model
|
del data_model
|
||||||
|
|
||||||
@@ -971,7 +965,7 @@ class MLFlowRepository(SientiaMonitoring):
|
|||||||
4. Archives existing production versions
|
4. Archives existing production versions
|
||||||
"""
|
"""
|
||||||
|
|
||||||
self.logger.custom_info(
|
self.info(
|
||||||
f'Starting production model update for {model_name} with run ID: {run_id}', metadata
|
f'Starting production model update for {model_name} with run ID: {run_id}', metadata
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -1059,9 +1053,7 @@ class MLFlowRepository(SientiaMonitoring):
|
|||||||
and returned in the response structure rather than propagated.
|
and returned in the response structure rather than propagated.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
self.logger.custom_debug(
|
self.debug(f'Data received for model transformation: {data.head(5).to_csv()}', metadata)
|
||||||
f'Data received for model transformation: {data.head(5).to_csv()}', metadata
|
|
||||||
)
|
|
||||||
|
|
||||||
# data.to_csv(
|
# data.to_csv(
|
||||||
# f"tmp/data_{model_name}.csv", index=True)
|
# f"tmp/data_{model_name}.csv", index=True)
|
||||||
@@ -1079,7 +1071,7 @@ class MLFlowRepository(SientiaMonitoring):
|
|||||||
metadata=metadata,
|
metadata=metadata,
|
||||||
)
|
)
|
||||||
|
|
||||||
self.logger.custom_debug(
|
self.debug(
|
||||||
f'Data received from model transformation: {transformed_data.head(5).to_csv()}',
|
f'Data received from model transformation: {transformed_data.head(5).to_csv()}',
|
||||||
metadata,
|
metadata,
|
||||||
)
|
)
|
||||||
@@ -1147,9 +1139,7 @@ class MLFlowRepository(SientiaMonitoring):
|
|||||||
input_index = data.index
|
input_index = data.index
|
||||||
start_time = datetime.now()
|
start_time = datetime.now()
|
||||||
|
|
||||||
self.logger.custom_debug(
|
self.debug(f'Data received for model prediction: {data.head(5).to_csv()}', metadata)
|
||||||
f'Data received for model prediction: {data.head(5).to_csv()}', 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)
|
||||||
@@ -1166,7 +1156,7 @@ class MLFlowRepository(SientiaMonitoring):
|
|||||||
end_time = datetime.now()
|
end_time = datetime.now()
|
||||||
|
|
||||||
if isinstance(predict_data, pd.DataFrame):
|
if isinstance(predict_data, pd.DataFrame):
|
||||||
self.logger.custom_debug(
|
self.debug(
|
||||||
f'Data received from model prediction: {data.head(5).to_csv()}', metadata
|
f'Data received from model prediction: {data.head(5).to_csv()}', metadata
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -1235,22 +1225,22 @@ class MLFlowRepository(SientiaMonitoring):
|
|||||||
Exception: Any other exception during the retraining process
|
Exception: Any other exception during the retraining process
|
||||||
"""
|
"""
|
||||||
|
|
||||||
self.logger.custom_info(f'Starting model retraining workflow for {model_name}', metadata)
|
self.info(f'Starting model retraining workflow for {model_name}', metadata)
|
||||||
self.logger.custom_debug(f'Data received for model retraining: {data.to_csv()}', metadata)
|
self.debug(f'Data received for model retraining: {data.to_csv()}', metadata)
|
||||||
|
|
||||||
target_name = model_config.get('target', None)
|
target_name = model_config.get('target', None)
|
||||||
|
|
||||||
transform_flavor = model_config.get('transform_flavor', 'sklearn')
|
transform_flavor = model_config.get('transform_flavor', 'sklearn')
|
||||||
predict_flavor = model_config.get('predict_flavor', 'sklearn')
|
predict_flavor = model_config.get('predict_flavor', 'sklearn')
|
||||||
|
|
||||||
self.logger.custom_debug(
|
self.debug(
|
||||||
f'Model configuration - transform_flavor: {transform_flavor}, predict_flavor: {predict_flavor}, target_name: {target_name}',
|
f'Model configuration - transform_flavor: {transform_flavor}, predict_flavor: {predict_flavor}, target_name: {target_name}',
|
||||||
metadata,
|
metadata,
|
||||||
)
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
latest_production_id = self.get_model_run_id(model_name, stage='Production')
|
latest_production_id = self.get_model_run_id(model_name, stage='Production')
|
||||||
self.logger.custom_info('Creating model experiment environment', metadata)
|
self.info('Creating model experiment environment', metadata)
|
||||||
retrain_data = await self.fit_models(
|
retrain_data = await self.fit_models(
|
||||||
model_name=model_name,
|
model_name=model_name,
|
||||||
data=data,
|
data=data,
|
||||||
@@ -1260,11 +1250,9 @@ class MLFlowRepository(SientiaMonitoring):
|
|||||||
metadata=metadata,
|
metadata=metadata,
|
||||||
latest_production_id=latest_production_id,
|
latest_production_id=latest_production_id,
|
||||||
)
|
)
|
||||||
self.logger.custom_info(
|
self.info(f'Model experiment created successfully: {retrain_data}', metadata)
|
||||||
f'Model experiment created successfully: {retrain_data}', metadata
|
|
||||||
)
|
|
||||||
|
|
||||||
self.logger.custom_info('Saving model retrain', metadata)
|
self.info('Saving model retrain', metadata)
|
||||||
experiment = await self.create_new_experiment(
|
experiment = await self.create_new_experiment(
|
||||||
model_name=model_name,
|
model_name=model_name,
|
||||||
data=data,
|
data=data,
|
||||||
@@ -1274,7 +1262,7 @@ class MLFlowRepository(SientiaMonitoring):
|
|||||||
metadata=metadata,
|
metadata=metadata,
|
||||||
latest_production_id=latest_production_id,
|
latest_production_id=latest_production_id,
|
||||||
)
|
)
|
||||||
self.logger.custom_info(
|
self.info(
|
||||||
f'Model retraining completed successfully for experiment: {experiment}', metadata
|
f'Model retraining completed successfully for experiment: {experiment}', metadata
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -1285,7 +1273,7 @@ class MLFlowRepository(SientiaMonitoring):
|
|||||||
}
|
}
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
error_msg = f'Error retraining model {model_name}: {e}'
|
error_msg = f'Error retraining model {model_name}: {e}'
|
||||||
self.logger.custom_info(error_msg, metadata)
|
self.info(error_msg, metadata)
|
||||||
return {
|
return {
|
||||||
'success': False,
|
'success': False,
|
||||||
'experiment': None,
|
'experiment': None,
|
||||||
|
|||||||
@@ -143,7 +143,9 @@ class OpcRepository(SientiaMonitoring):
|
|||||||
|
|
||||||
if self.cert_path:
|
if self.cert_path:
|
||||||
await self.set_security()
|
await self.set_security()
|
||||||
self.logger.custom_info(f'Starting connection to OPC server {self.id}:{self.server_name}...', self.metadata)
|
self.logger.custom_info(
|
||||||
|
f'Starting connection to OPC server {self.id}:{self.server_name}...', self.metadata
|
||||||
|
)
|
||||||
return await self.try_connect()
|
return await self.try_connect()
|
||||||
|
|
||||||
async def try_connect(self) -> tuple[bool, dict[str, Any]]:
|
async def try_connect(self) -> tuple[bool, dict[str, Any]]:
|
||||||
|
|||||||
@@ -255,9 +255,7 @@ async def test_retrain_model_success_data_success_retrain(mock_to_datetime, mlfl
|
|||||||
timestamp = raw_data.__getitem__.return_value.max.return_value
|
timestamp = raw_data.__getitem__.return_value.max.return_value
|
||||||
|
|
||||||
raw_data.sort_values.assert_not_called()
|
raw_data.sort_values.assert_not_called()
|
||||||
raw_data.drop_duplicates.assert_called_once_with(
|
raw_data.drop_duplicates.assert_called_once_with(subset=['variable', 'timestamp'], keep='first')
|
||||||
subset=['variable', 'timestamp'], keep='first'
|
|
||||||
)
|
|
||||||
raw_data = raw_data.drop_duplicates.return_value
|
raw_data = raw_data.drop_duplicates.return_value
|
||||||
|
|
||||||
raw_data.drop.assert_has_calls(
|
raw_data.drop.assert_has_calls(
|
||||||
|
|||||||
@@ -61,6 +61,7 @@ async def test_init_opc(mock_send_notification, mock_opc_repository):
|
|||||||
mock_notification_handler = MagicMock()
|
mock_notification_handler = MagicMock()
|
||||||
servers = {
|
servers = {
|
||||||
'server1': {
|
'server1': {
|
||||||
|
'server_name': 'server1',
|
||||||
'id': 'server1',
|
'id': 'server1',
|
||||||
'url': 'http://localhost:8080',
|
'url': 'http://localhost:8080',
|
||||||
'server_uri': 'opc.tcp://localhost:4840',
|
'server_uri': 'opc.tcp://localhost:4840',
|
||||||
@@ -70,6 +71,7 @@ async def test_init_opc(mock_send_notification, mock_opc_repository):
|
|||||||
'reconnection_interval': 60,
|
'reconnection_interval': 60,
|
||||||
},
|
},
|
||||||
'server2': {
|
'server2': {
|
||||||
|
'server_name': 'server2',
|
||||||
'id': 'server2',
|
'id': 'server2',
|
||||||
'url': 'http://localhost:8080',
|
'url': 'http://localhost:8080',
|
||||||
'server_uri': 'opc.tcp://localhost:4840',
|
'server_uri': 'opc.tcp://localhost:4840',
|
||||||
@@ -79,6 +81,7 @@ async def test_init_opc(mock_send_notification, mock_opc_repository):
|
|||||||
'reconnection_interval': 60,
|
'reconnection_interval': 60,
|
||||||
},
|
},
|
||||||
'server3': {
|
'server3': {
|
||||||
|
'server_name': 'server3',
|
||||||
'id': 'server3',
|
'id': 'server3',
|
||||||
'url': 'http://localhost:8080',
|
'url': 'http://localhost:8080',
|
||||||
'server_uri': 'opc.tcp://localhost:4840',
|
'server_uri': 'opc.tcp://localhost:4840',
|
||||||
@@ -106,6 +109,7 @@ async def test_init_opc(mock_send_notification, mock_opc_repository):
|
|||||||
[
|
[
|
||||||
call(
|
call(
|
||||||
opc_id='server1',
|
opc_id='server1',
|
||||||
|
server_name='server1',
|
||||||
url='http://localhost:8080',
|
url='http://localhost:8080',
|
||||||
logger=mock_logger,
|
logger=mock_logger,
|
||||||
server_uri='opc.tcp://localhost:4840',
|
server_uri='opc.tcp://localhost:4840',
|
||||||
@@ -122,6 +126,7 @@ async def test_init_opc(mock_send_notification, mock_opc_repository):
|
|||||||
[
|
[
|
||||||
call(
|
call(
|
||||||
opc_id='server2',
|
opc_id='server2',
|
||||||
|
server_name='server2',
|
||||||
url='http://localhost:8080',
|
url='http://localhost:8080',
|
||||||
logger=mock_logger,
|
logger=mock_logger,
|
||||||
server_uri='opc.tcp://localhost:4840',
|
server_uri='opc.tcp://localhost:4840',
|
||||||
@@ -163,6 +168,7 @@ async def opc(mock_opc_repository):
|
|||||||
servers = {
|
servers = {
|
||||||
'server1': {
|
'server1': {
|
||||||
'id': 'server1',
|
'id': 'server1',
|
||||||
|
'server_name': 'server1',
|
||||||
'url': 'http://localhost:8080',
|
'url': 'http://localhost:8080',
|
||||||
'server_uri': 'opc.tcp://localhost:4840',
|
'server_uri': 'opc.tcp://localhost:4840',
|
||||||
'cert_path': '',
|
'cert_path': '',
|
||||||
|
|||||||
@@ -95,7 +95,6 @@ async def test_create_bucket_error(minio_repository):
|
|||||||
with raises(ValueError):
|
with raises(ValueError):
|
||||||
await minio_repository.create_bucket({})
|
await minio_repository.create_bucket({})
|
||||||
|
|
||||||
|
|
||||||
minio_repository.s3_client.create_bucket.assert_called_once_with(Bucket='test')
|
minio_repository.s3_client.create_bucket.assert_called_once_with(Bucket='test')
|
||||||
minio_repository.emit_metric.assert_called_once_with(
|
minio_repository.emit_metric.assert_called_once_with(
|
||||||
metric_object=metrics.MINIO_WRITE_ERROR_COUNT, tags=ANY
|
metric_object=metrics.MINIO_WRITE_ERROR_COUNT, tags=ANY
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ def mock_logger():
|
|||||||
def opc_repository(mock_logger):
|
def opc_repository(mock_logger):
|
||||||
repository = OpcRepository(
|
repository = OpcRepository(
|
||||||
opc_id='test_repo',
|
opc_id='test_repo',
|
||||||
|
server_name='test_server',
|
||||||
url='opc.tcp://localhost:4840',
|
url='opc.tcp://localhost:4840',
|
||||||
logger=mock_logger,
|
logger=mock_logger,
|
||||||
notification_handler=Mock(),
|
notification_handler=Mock(),
|
||||||
@@ -55,6 +56,7 @@ metadata = {
|
|||||||
|
|
||||||
def test_init(opc_repository):
|
def test_init(opc_repository):
|
||||||
assert opc_repository.id == 'test_repo'
|
assert opc_repository.id == 'test_repo'
|
||||||
|
assert opc_repository.server_name == 'test_server'
|
||||||
assert opc_repository.url == 'opc.tcp://localhost:4840'
|
assert opc_repository.url == 'opc.tcp://localhost:4840'
|
||||||
assert opc_repository.server_uri == 'urn:test:server'
|
assert opc_repository.server_uri == 'urn:test:server'
|
||||||
assert opc_repository.cert_path == '/path/to/cert.pem'
|
assert opc_repository.cert_path == '/path/to/cert.pem'
|
||||||
@@ -139,11 +141,13 @@ async def test_try_connect_success(opc_repository):
|
|||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
async def test_try_connect_fail(opc_repository):
|
async def test_try_connect_fail(opc_repository):
|
||||||
opc_repository.last_reconnection_time = None
|
opc_repository.last_reconnection_time = None
|
||||||
|
opc_repository.disconnect = AsyncMock()
|
||||||
opc_repository.client = MagicMock()
|
opc_repository.client = MagicMock()
|
||||||
opc_repository.client.connect.side_effect = Exception('Test error')
|
opc_repository.client.connect.side_effect = Exception('Test error')
|
||||||
|
|
||||||
is_connected, error_data = await opc_repository.try_connect()
|
is_connected, error_data = await opc_repository.try_connect()
|
||||||
|
|
||||||
|
opc_repository.disconnect.assert_called_once()
|
||||||
opc_repository.client.connect.assert_called_once()
|
opc_repository.client.connect.assert_called_once()
|
||||||
assert is_connected is False
|
assert is_connected is False
|
||||||
assert error_data['notification_id'] == f'OPC_CONNECTION_ERROR_{opc_repository.id}'
|
assert error_data['notification_id'] == f'OPC_CONNECTION_ERROR_{opc_repository.id}'
|
||||||
|
|||||||
Reference in New Issue
Block a user