SIENTIAPDE-1325
Refactor monitoring and metrics integration across various components - Removed coverage options from `pyproject.toml`. - Updated prediction metrics in `README.md` to replace `pipeline_name` with `workflow_name`. - Upgraded `sientia-dataops-library` dependency version in `requirements-light.txt` and `requirements.txt`. - Enhanced metrics handling in `laborious` activities, including `Activities`, `Gates`, `MLFlow`, and `OPC`, to utilize a new `MetricsController`. - Refactored metric emission methods to improve clarity and consistency across the codebase. - Updated tests to reflect changes in metrics handling and ensure proper functionality.
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
from unittest.mock import ANY, MagicMock, patch
|
||||
from unittest.mock import ANY, AsyncMock, MagicMock, patch
|
||||
|
||||
from pytest import mark
|
||||
|
||||
@@ -13,7 +13,10 @@ from laborious.activities.storage import Storage
|
||||
@patch('laborious.activities.activities.MLFlow.__init__')
|
||||
@patch('laborious.activities.activities.OPC.__init__')
|
||||
@patch('laborious.activities.activities.Gates.__init__')
|
||||
def test___init__(mock_gates_init, mock_opc_init, mock_mlflow_init, mock_storage_init):
|
||||
@patch('laborious.activities.activities.MetricsController')
|
||||
def test___init__(
|
||||
mock_metrics_controller, mock_gates_init, mock_opc_init, mock_mlflow_init, mock_storage_init
|
||||
):
|
||||
postgres_config = {
|
||||
'host': 'localhost',
|
||||
'port': 5432,
|
||||
@@ -70,6 +73,7 @@ def test___init__(mock_gates_init, mock_opc_init, mock_mlflow_init, mock_storage
|
||||
minio_config=minio_config,
|
||||
logger=logger,
|
||||
notification_handler=notification_handler,
|
||||
metrics_controller=mock_metrics_controller.return_value,
|
||||
)
|
||||
|
||||
mock_mlflow_init.assert_called_once_with(
|
||||
@@ -81,22 +85,32 @@ def test___init__(mock_gates_init, mock_opc_init, mock_mlflow_init, mock_storage
|
||||
minio_config=minio_config,
|
||||
logger=logger,
|
||||
notification_handler=notification_handler,
|
||||
metrics_controller=mock_metrics_controller.return_value,
|
||||
)
|
||||
|
||||
mock_opc_init.assert_called_once_with(
|
||||
ANY, opc_servers=opc_config, logger=logger, notification_handler=notification_handler
|
||||
ANY,
|
||||
opc_servers=opc_config,
|
||||
logger=logger,
|
||||
notification_handler=notification_handler,
|
||||
metrics_controller=mock_metrics_controller.return_value,
|
||||
)
|
||||
|
||||
mock_gates_init.assert_called_once_with(
|
||||
ANY, logger=logger, notification_handler=notification_handler
|
||||
ANY,
|
||||
logger=logger,
|
||||
notification_handler=notification_handler,
|
||||
metrics_controller=mock_metrics_controller.return_value,
|
||||
)
|
||||
|
||||
|
||||
@mark.asyncio
|
||||
@patch('laborious.activities.activities.Storage', return_value=MagicMock())
|
||||
@patch('laborious.activities.activities.MLFlow', return_value=MagicMock())
|
||||
@patch('laborious.activities.activities.OPC', return_value=MagicMock())
|
||||
async def test_shutdown(mock_opc_init, _mock_mlflow_init, mock_storage_init):
|
||||
@patch('laborious.activities.activities.Storage')
|
||||
@patch('laborious.activities.activities.MLFlow')
|
||||
@patch('laborious.activities.activities.OPC')
|
||||
@patch('laborious.activities.activities.Gates')
|
||||
async def test_shutdown(mock_gates_init, mock_opc_init, mock_mlflow_init, mock_storage_init):
|
||||
mock_opc_init.close = AsyncMock()
|
||||
postgres_config = {
|
||||
'host': 'localhost',
|
||||
'port': 5432,
|
||||
@@ -136,5 +150,7 @@ async def test_shutdown(mock_opc_init, _mock_mlflow_init, mock_storage_init):
|
||||
)
|
||||
|
||||
await activities.shutdown()
|
||||
mock_opc_init.shutdown.assert_called_once()
|
||||
mock_opc_init.close.assert_called_once()
|
||||
mock_storage_init.close.assert_called_once()
|
||||
mock_mlflow_init.close.assert_called_once()
|
||||
mock_gates_init.close.assert_called_once()
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from unittest.mock import ANY, MagicMock, call, patch
|
||||
from unittest.mock import ANY, AsyncMock, MagicMock, call, patch
|
||||
|
||||
from pytest import fixture, mark
|
||||
from sientia_do.notifications.models import NotificationLevel
|
||||
@@ -11,6 +11,7 @@ def gates_activity():
|
||||
gates = Gates(
|
||||
logger=MagicMock(),
|
||||
notification_handler=MagicMock(),
|
||||
metrics_controller=AsyncMock(),
|
||||
)
|
||||
gates.error = MagicMock()
|
||||
gates.debug = MagicMock()
|
||||
@@ -18,6 +19,8 @@ def gates_activity():
|
||||
gates.warning = MagicMock()
|
||||
gates.critical = MagicMock()
|
||||
gates.send_notification = MagicMock()
|
||||
gates.send_notification_async = AsyncMock()
|
||||
gates.emit_metric = AsyncMock()
|
||||
return gates
|
||||
|
||||
|
||||
@@ -71,7 +74,7 @@ async def test_input_gate_filter_exception(mock_input_filter_functions, gates_ac
|
||||
|
||||
# Assert
|
||||
assert result == (None, 0, '')
|
||||
gates_activity.send_notification.assert_called_once_with(
|
||||
gates_activity.send_notification_async.assert_called_once_with(
|
||||
metadata=metadata['metadata'],
|
||||
notification_id='INTPUT_GATE_ERROR__EMPTY_DATA',
|
||||
message="Error in filter EMPTY_DATA:{'policy': 'STOP', 'config': {}}: \n Test error",
|
||||
@@ -176,7 +179,7 @@ async def test_mlflow_response_gate_filter_exception(
|
||||
|
||||
# Assert
|
||||
assert result == (None, 0, '')
|
||||
gates_activity.send_notification.assert_called_once_with(
|
||||
gates_activity.send_notification_async.assert_called_once_with(
|
||||
metadata=metadata['metadata'],
|
||||
notification_id='MLFLOW_GATE_RESPONSE_FILTER__INVALID_FILTER',
|
||||
message="Error in filter INVALID_FILTER:{'POLICY': 'STOP'}: \n Test error",
|
||||
@@ -225,7 +228,7 @@ async def test_mlflow_response_gate_with_filter(gates_activity):
|
||||
# Assert
|
||||
assert result == ('STOP', -1, 'API error occurred')
|
||||
gates_activity.debug.assert_called()
|
||||
gates_activity.send_notification.assert_called()
|
||||
gates_activity.send_notification_async.assert_called()
|
||||
|
||||
|
||||
@mark.asyncio
|
||||
@@ -298,7 +301,7 @@ async def test_mlflow_content_gate_filter_exception(
|
||||
# Assert
|
||||
assert result == (None, 0, '')
|
||||
gates_activity.debug.assert_called()
|
||||
gates_activity.send_notification.assert_called_once_with(
|
||||
gates_activity.send_notification_async.assert_called_once_with(
|
||||
metadata=metadata['metadata'],
|
||||
notification_id='MLFLOW_GATE_CONTENT_FILTER__API_ERROR',
|
||||
message="Error in filter API_ERROR:{'POLICY': 'STOP'}: \n Test error",
|
||||
@@ -344,7 +347,7 @@ async def test_mlflow_content_gate_with_filter(gates_activity):
|
||||
# Assert
|
||||
assert result == ('STOP', -1, 'Transformed data not passed the content filter')
|
||||
gates_activity.debug.assert_called()
|
||||
gates_activity.send_notification.assert_called()
|
||||
gates_activity.send_notification_async.assert_called()
|
||||
|
||||
|
||||
@mark.asyncio
|
||||
@@ -639,57 +642,103 @@ async def test_write_metrics(mock_metrics, gates_activity):
|
||||
'opc_metrics': {'server1': {'tag1': 0.1, 'tag2': 0.2}},
|
||||
}
|
||||
await gates_activity.write_metrics(input_data)
|
||||
mock_metrics.PREDICTIONS_WRITTEN_COUNT.labels.assert_called_once_with(
|
||||
pod_id=gates_activity.pod_id,
|
||||
model_name=metadata['metadata']['model_name'],
|
||||
pipeline_name=metadata['metadata']['workflow_name'],
|
||||
)
|
||||
mock_metrics.PREDICTIONS_WRITTEN_COUNT.labels.return_value.inc.assert_called_once_with()
|
||||
|
||||
mock_metrics.PREDICTION_CONFIDENCE_MONITOR.labels.assert_called_once_with(
|
||||
pod_id=gates_activity.pod_id,
|
||||
model_name=metadata['metadata']['model_name'],
|
||||
pipeline_name=metadata['metadata']['workflow_name'],
|
||||
)
|
||||
mock_metrics.PREDICTION_CONFIDENCE_MONITOR.labels.return_value.set.assert_called_once_with(0.9)
|
||||
|
||||
mock_metrics.PREDICTION_RESPONSE_TIME_MONITOR.labels.assert_called_once_with(
|
||||
pod_id=gates_activity.pod_id,
|
||||
model_name=metadata['metadata']['model_name'],
|
||||
pipeline_name=metadata['metadata']['workflow_name'],
|
||||
)
|
||||
mock_metrics.PREDICTION_RESPONSE_TIME_MONITOR.labels.return_value.observe.assert_called_once_with(
|
||||
0.1
|
||||
)
|
||||
|
||||
mock_metrics.PREDICTION_OPC_WRITING_COUNT.labels.assert_has_calls(
|
||||
gates_activity.emit_metric.assert_has_calls(
|
||||
[
|
||||
call(
|
||||
pod_id=gates_activity.pod_id,
|
||||
model_name=metadata['metadata']['model_name'],
|
||||
pipeline_name=metadata['metadata']['workflow_name'],
|
||||
opc_server_id='server1',
|
||||
tag='tag1',
|
||||
)
|
||||
metric_object=mock_metrics.PREDICTIONS_WRITTEN_COUNT,
|
||||
tags={
|
||||
'pod_id': gates_activity.pod_id,
|
||||
'model_name': metadata['metadata']['model_name'],
|
||||
'workflow_name': metadata['metadata']['workflow_name'],
|
||||
},
|
||||
),
|
||||
]
|
||||
)
|
||||
mock_metrics.PREDICTION_OPC_WRITING_RESPONSE_TIME_MONITOR.labels.assert_has_calls(
|
||||
gates_activity.emit_metric.assert_has_calls(
|
||||
[
|
||||
call(
|
||||
pod_id=gates_activity.pod_id,
|
||||
model_name=metadata['metadata']['model_name'],
|
||||
pipeline_name=metadata['metadata']['workflow_name'],
|
||||
opc_server_id='server1',
|
||||
tag='tag1',
|
||||
)
|
||||
metric_object=mock_metrics.PREDICTION_CONFIDENCE_MONITOR,
|
||||
method='set',
|
||||
tags={
|
||||
'pod_id': gates_activity.pod_id,
|
||||
'model_name': metadata['metadata']['model_name'],
|
||||
'workflow_name': metadata['metadata']['workflow_name'],
|
||||
},
|
||||
value=0.9,
|
||||
),
|
||||
]
|
||||
)
|
||||
|
||||
assert mock_metrics.PREDICTION_OPC_WRITING_COUNT.labels.return_value.inc.call_count == 2
|
||||
mock_metrics.PREDICTION_OPC_WRITING_RESPONSE_TIME_MONITOR.labels.return_value.observe.assert_has_calls(
|
||||
gates_activity.emit_metric.assert_has_calls(
|
||||
[
|
||||
call(0.1),
|
||||
call(0.2),
|
||||
],
|
||||
any_order=True,
|
||||
call(
|
||||
metric_object=mock_metrics.PREDICTION_RESPONSE_TIME_MONITOR,
|
||||
method='observe',
|
||||
tags={
|
||||
'pod_id': gates_activity.pod_id,
|
||||
'model_name': metadata['metadata']['model_name'],
|
||||
'workflow_name': metadata['metadata']['workflow_name'],
|
||||
},
|
||||
value=0.1,
|
||||
),
|
||||
]
|
||||
)
|
||||
gates_activity.emit_metric.assert_has_calls(
|
||||
[
|
||||
call(
|
||||
metric_object=mock_metrics.PREDICTION_OPC_WRITING_COUNT,
|
||||
tags={
|
||||
'pod_id': gates_activity.pod_id,
|
||||
'model_name': metadata['metadata']['model_name'],
|
||||
'workflow_name': metadata['metadata']['workflow_name'],
|
||||
'opc_server_id': 'server1',
|
||||
'tag': 'tag1',
|
||||
},
|
||||
),
|
||||
]
|
||||
)
|
||||
gates_activity.emit_metric.assert_has_calls(
|
||||
[
|
||||
call(
|
||||
metric_object=mock_metrics.PREDICTION_OPC_WRITING_RESPONSE_TIME_MONITOR,
|
||||
method='observe',
|
||||
tags={
|
||||
'pod_id': gates_activity.pod_id,
|
||||
'model_name': metadata['metadata']['model_name'],
|
||||
'workflow_name': metadata['metadata']['workflow_name'],
|
||||
'opc_server_id': 'server1',
|
||||
'tag': 'tag1',
|
||||
},
|
||||
value=0.1,
|
||||
),
|
||||
]
|
||||
)
|
||||
gates_activity.emit_metric.assert_has_calls(
|
||||
[
|
||||
call(
|
||||
metric_object=mock_metrics.PREDICTION_OPC_WRITING_COUNT,
|
||||
tags={
|
||||
'pod_id': gates_activity.pod_id,
|
||||
'model_name': metadata['metadata']['model_name'],
|
||||
'workflow_name': metadata['metadata']['workflow_name'],
|
||||
'opc_server_id': 'server1',
|
||||
'tag': 'tag2',
|
||||
},
|
||||
),
|
||||
]
|
||||
)
|
||||
gates_activity.emit_metric.assert_has_calls(
|
||||
[
|
||||
call(
|
||||
metric_object=mock_metrics.PREDICTION_OPC_WRITING_RESPONSE_TIME_MONITOR,
|
||||
method='observe',
|
||||
tags={
|
||||
'pod_id': gates_activity.pod_id,
|
||||
'model_name': metadata['metadata']['model_name'],
|
||||
'workflow_name': metadata['metadata']['workflow_name'],
|
||||
'opc_server_id': 'server1',
|
||||
'tag': 'tag2',
|
||||
},
|
||||
value=0.2,
|
||||
),
|
||||
]
|
||||
)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from unittest.mock import ANY, MagicMock, call, patch
|
||||
from unittest.mock import ANY, AsyncMock, MagicMock, call, patch
|
||||
|
||||
import numpy as np
|
||||
from pytest import fixture, mark, raises
|
||||
@@ -25,6 +25,7 @@ def test___init__(mock_minio_repository, mock_mlflow_repository):
|
||||
},
|
||||
logger=MagicMock(),
|
||||
notification_handler=MagicMock(),
|
||||
metrics_controller=AsyncMock(),
|
||||
)
|
||||
|
||||
assert mlflow.mlflow_host == 'http://localhost'
|
||||
@@ -32,7 +33,9 @@ def test___init__(mock_minio_repository, mock_mlflow_repository):
|
||||
assert mlflow.mlflow_username == 'admin'
|
||||
assert mlflow.mlflow_password == 'admin'
|
||||
|
||||
mock_mlflow_repository.assert_called_once_with('http://localhost:5000', 'admin', 'admin', ANY)
|
||||
mock_mlflow_repository.assert_called_once_with(
|
||||
'http://localhost:5000', 'admin', 'admin', ANY, ANY, ANY
|
||||
)
|
||||
|
||||
mock_minio_repository.assert_called_once_with(
|
||||
logger=ANY,
|
||||
@@ -42,6 +45,7 @@ def test___init__(mock_minio_repository, mock_mlflow_repository):
|
||||
minio_secret_key='minio123',
|
||||
minio_region_name='us-east-1',
|
||||
minio_default_bucket='test',
|
||||
metrics_controller=ANY,
|
||||
)
|
||||
|
||||
|
||||
@@ -63,9 +67,15 @@ def mlflow(mock_minio_repository, mock_mlflow_repository):
|
||||
},
|
||||
logger=MagicMock(),
|
||||
notification_handler=MagicMock(),
|
||||
metrics_controller=AsyncMock(),
|
||||
)
|
||||
|
||||
mlflow.model_monitoring_repository = AsyncMock()
|
||||
mlflow.minio_repository = AsyncMock()
|
||||
|
||||
mlflow.send_notification = MagicMock()
|
||||
mlflow.emit_metric = AsyncMock()
|
||||
mlflow.send_notification_async = AsyncMock()
|
||||
|
||||
return mlflow
|
||||
|
||||
@@ -225,6 +235,8 @@ async def test_retrain_model_success_data_success_retrain(mock_to_datetime, mlfl
|
||||
'message': 'Model retrained successfully.',
|
||||
}
|
||||
|
||||
mlflow.minio_repository.get_parquet_as_dataframe.return_value = MagicMock()
|
||||
|
||||
response = await mlflow.retrain_model(
|
||||
{
|
||||
**metadata,
|
||||
@@ -301,6 +313,8 @@ async def test_retrain_model_success_data_fail_retrain(mock_to_datetime, mlflow)
|
||||
'message': 'Model retrained failed.',
|
||||
}
|
||||
|
||||
mlflow.minio_repository.get_parquet_as_dataframe.return_value = MagicMock()
|
||||
|
||||
response = await mlflow.retrain_model(
|
||||
{
|
||||
**metadata,
|
||||
@@ -360,7 +374,7 @@ async def test_retrain_model_success_data_fail_retrain(mock_to_datetime, mlflow)
|
||||
metadata=metadata['metadata'],
|
||||
)
|
||||
|
||||
mlflow.send_notification.assert_called_once_with(
|
||||
mlflow.send_notification_async.assert_called_once_with(
|
||||
metadata=metadata['metadata'],
|
||||
notification_id='RETRAIN_MODEL_ERROR',
|
||||
message='Error retraining model test_model: Model retrained failed.',
|
||||
@@ -464,7 +478,7 @@ async def test_update_production_model_error(mlflow):
|
||||
await mlflow.update_production_model(input_data)
|
||||
except Exception as e:
|
||||
assert str(e) == 'Error updating production model'
|
||||
mlflow.send_notification.assert_called_once_with(
|
||||
mlflow.send_notification_async.assert_called_once_with(
|
||||
metadata=metadata['metadata'],
|
||||
notification_id='UPDATE_PRODUCTION_MODEL_ERROR',
|
||||
message='Error updating production model test_model: Error updating production model',
|
||||
|
||||
@@ -18,8 +18,13 @@ metadata = {
|
||||
|
||||
|
||||
def test__init__():
|
||||
servers = {'server1': 'config'}
|
||||
opc = OPC(opc_servers=servers, logger=MagicMock(), notification_handler=MagicMock())
|
||||
servers = {'server1': {'id': 'server1'}}
|
||||
opc = OPC(
|
||||
opc_servers=servers,
|
||||
logger=MagicMock(),
|
||||
notification_handler=MagicMock(),
|
||||
metrics_controller=AsyncMock(),
|
||||
)
|
||||
|
||||
assert opc.opc_servers == servers
|
||||
assert opc.opc_repository == {}
|
||||
@@ -27,9 +32,10 @@ def test__init__():
|
||||
|
||||
@mark.asyncio
|
||||
@patch('laborious.activities.opc.OpcRepository')
|
||||
@patch('laborious.activities.opc.OPC.send_notification')
|
||||
@patch('laborious.activities.opc.OPC.send_notification_async')
|
||||
async def test_init_opc(mock_send_notification, mock_opc_repository):
|
||||
mock_logger = MagicMock()
|
||||
mock_metrics_controller = AsyncMock()
|
||||
server1 = MagicMock(
|
||||
connect=AsyncMock(return_value=(True, {})), write_data=AsyncMock(return_value=(True, {}))
|
||||
)
|
||||
@@ -83,7 +89,10 @@ async def test_init_opc(mock_send_notification, mock_opc_repository):
|
||||
},
|
||||
}
|
||||
opc = OPC(
|
||||
opc_servers=servers, logger=mock_logger, notification_handler=mock_notification_handler
|
||||
opc_servers=servers,
|
||||
logger=mock_logger,
|
||||
notification_handler=mock_notification_handler,
|
||||
metrics_controller=mock_metrics_controller,
|
||||
)
|
||||
await opc.init_opc()
|
||||
|
||||
@@ -105,6 +114,7 @@ async def test_init_opc(mock_send_notification, mock_opc_repository):
|
||||
server_cert_path='',
|
||||
notification_handler=mock_notification_handler,
|
||||
reconnection_interval=60,
|
||||
metrics_controller=mock_metrics_controller,
|
||||
),
|
||||
]
|
||||
)
|
||||
@@ -120,6 +130,7 @@ async def test_init_opc(mock_send_notification, mock_opc_repository):
|
||||
server_cert_path='',
|
||||
notification_handler=mock_notification_handler,
|
||||
reconnection_interval=60,
|
||||
metrics_controller=mock_metrics_controller,
|
||||
)
|
||||
]
|
||||
)
|
||||
@@ -163,9 +174,16 @@ async def opc(mock_opc_repository):
|
||||
|
||||
mock_opc_repository.return_value.write_data = AsyncMock(return_value=(True, {}))
|
||||
mock_opc_repository.return_value.connect = AsyncMock(return_value=(True, {}))
|
||||
opc = OPC(opc_servers=servers, logger=MagicMock(), notification_handler=MagicMock())
|
||||
opc = OPC(
|
||||
opc_servers=servers,
|
||||
logger=MagicMock(),
|
||||
notification_handler=MagicMock(),
|
||||
metrics_controller=AsyncMock(),
|
||||
)
|
||||
await opc.init_opc()
|
||||
opc.send_notification = MagicMock()
|
||||
opc.send_notification_async = AsyncMock()
|
||||
opc.emit_metric = AsyncMock()
|
||||
return opc
|
||||
|
||||
|
||||
@@ -219,7 +237,7 @@ async def test_write_data_failed(opc):
|
||||
)
|
||||
assert result is None
|
||||
|
||||
opc.send_notification.assert_called_once_with(
|
||||
opc.send_notification_async.assert_called_once_with(
|
||||
metadata=metadata,
|
||||
notification_id='OPC_WRITE_DATA_ERROR_server1',
|
||||
message='Failed to write data to OPC server: Test error',
|
||||
@@ -244,7 +262,7 @@ async def test_write_data_exception(opc):
|
||||
)
|
||||
|
||||
except Exception:
|
||||
opc.send_notification.assert_called_once_with(
|
||||
opc.send_notification_async.assert_called_once_with(
|
||||
metadata=metadata,
|
||||
notification_id='WRITE_OPC_PREDICTION_ERROR',
|
||||
message='Error writing data to OPC server: Test error',
|
||||
@@ -411,7 +429,7 @@ async def test_write_opc_data_empty_config(opc):
|
||||
|
||||
@mark.asyncio
|
||||
async def test_write_opc_data_no_validate_server(opc):
|
||||
opc.validate_server = MagicMock(return_value=False)
|
||||
opc.validate_server = AsyncMock(return_value=False)
|
||||
input_data = {
|
||||
**metadata,
|
||||
'data': {'prediction': [0.75], 'prediction_confidence': [0.95]},
|
||||
@@ -445,13 +463,14 @@ def test_process_confidence(opc, data, success, expected):
|
||||
assert result['prediction_confidence'][0] == expected
|
||||
|
||||
|
||||
def test_validate_server(opc):
|
||||
assert opc.validate_server('server1', metadata) is True
|
||||
assert opc.validate_server('server2', metadata) is False
|
||||
@mark.asyncio
|
||||
async def test_validate_server(opc):
|
||||
assert await opc.validate_server('server1', metadata) is True
|
||||
assert await opc.validate_server('server2', metadata) is False
|
||||
|
||||
|
||||
@mark.asyncio
|
||||
async def test_shutdown(opc):
|
||||
async def test_close(opc):
|
||||
opc.opc_repository['server1'].disconnect = AsyncMock(return_value=True)
|
||||
await opc.shutdown()
|
||||
await opc.close()
|
||||
opc.opc_repository['server1'].disconnect.assert_called_once()
|
||||
|
||||
@@ -37,6 +37,7 @@ def storage(mock_minio_repository):
|
||||
},
|
||||
logger=MagicMock(),
|
||||
notification_handler=MagicMock(),
|
||||
metrics_controller=AsyncMock(),
|
||||
)
|
||||
|
||||
|
||||
@@ -44,6 +45,7 @@ def storage(mock_minio_repository):
|
||||
def test___init___not_hasattr(mock_minio_repository):
|
||||
logger = MagicMock()
|
||||
notification_handler = MagicMock()
|
||||
metrics_controller = AsyncMock()
|
||||
storage = Storage(
|
||||
host='localhost',
|
||||
port=5432,
|
||||
@@ -61,6 +63,7 @@ def test___init___not_hasattr(mock_minio_repository):
|
||||
},
|
||||
logger=logger,
|
||||
notification_handler=notification_handler,
|
||||
metrics_controller=metrics_controller,
|
||||
)
|
||||
assert isinstance(storage, Postgres)
|
||||
|
||||
@@ -72,6 +75,7 @@ def test___init___not_hasattr(mock_minio_repository):
|
||||
minio_secret_key='minio123',
|
||||
minio_region_name='us-east-1',
|
||||
minio_default_bucket='test',
|
||||
metrics_controller=metrics_controller,
|
||||
)
|
||||
|
||||
|
||||
@@ -80,7 +84,7 @@ def test___init___none_minio_repository(mock_minio_repository, storage):
|
||||
storage.minio_repository = None
|
||||
logger = MagicMock()
|
||||
notification_handler = MagicMock()
|
||||
|
||||
metrics_controller = AsyncMock()
|
||||
storage.__init__(
|
||||
host='localhost',
|
||||
port=5432,
|
||||
@@ -98,6 +102,7 @@ def test___init___none_minio_repository(mock_minio_repository, storage):
|
||||
},
|
||||
logger=logger,
|
||||
notification_handler=notification_handler,
|
||||
metrics_controller=metrics_controller,
|
||||
)
|
||||
|
||||
mock_minio_repository.assert_called_once_with(
|
||||
@@ -108,6 +113,7 @@ def test___init___none_minio_repository(mock_minio_repository, storage):
|
||||
minio_secret_key='minio123',
|
||||
minio_region_name='us-east-1',
|
||||
minio_default_bucket='test',
|
||||
metrics_controller=metrics_controller,
|
||||
)
|
||||
|
||||
|
||||
@@ -130,6 +136,7 @@ def test___init___done_repository(mock_minio_repository, storage):
|
||||
},
|
||||
logger=MagicMock(),
|
||||
notification_handler=MagicMock(),
|
||||
metrics_controller=AsyncMock(),
|
||||
)
|
||||
mock_minio_repository.assert_not_called()
|
||||
assert storage.minio_repository is not None
|
||||
@@ -162,6 +169,7 @@ async def test_query_to_minio_success(now, dataframe, storage):
|
||||
data = [{'a': 1}, {'a': 2}, {'a': 3}]
|
||||
storage.load_custom_query = AsyncMock(return_value=data)
|
||||
now.return_value = datetime.datetime(2024, 1, 1, 0, 0, 0)
|
||||
storage.minio_repository.store_dataframe_as_parquet = AsyncMock()
|
||||
storage.minio_repository.minio_bucket = 'test'
|
||||
|
||||
result = await storage.query_to_minio({'object_prefix': 'test', **metadata})
|
||||
@@ -183,11 +191,14 @@ async def test_query_to_minio_success(now, dataframe, storage):
|
||||
@mark.asyncio
|
||||
async def test_query_to_minio_error(storage):
|
||||
storage.send_notification = MagicMock()
|
||||
storage.send_notification_async = AsyncMock()
|
||||
storage.minio_repository.store_dataframe_as_parquet = AsyncMock()
|
||||
|
||||
storage.load_custom_query = AsyncMock(side_effect=Exception('test'))
|
||||
result = await storage.query_to_minio({**metadata, 'object_prefix': 'test'})
|
||||
assert result['success'] is False
|
||||
assert result['message'] == 'test'
|
||||
storage.send_notification.assert_called_once_with(
|
||||
storage.send_notification_async.assert_called_once_with(
|
||||
metadata=metadata['metadata'],
|
||||
notification_id='ERROR_STORING_QUERY_TO_MINIO',
|
||||
message='Error storing query to MinIO: test',
|
||||
|
||||
Reference in New Issue
Block a user