diff --git a/sdk/python/feast/infra/offline_stores/contrib/trino_offline_store/tests/test_trino_monitoring.py b/sdk/python/feast/infra/offline_stores/contrib/trino_offline_store/tests/test_trino_monitoring.py index dfa0c936965..893f6d365e4 100644 --- a/sdk/python/feast/infra/offline_stores/contrib/trino_offline_store/tests/test_trino_monitoring.py +++ b/sdk/python/feast/infra/offline_stores/contrib/trino_offline_store/tests/test_trino_monitoring.py @@ -768,6 +768,48 @@ def test_query_monitoring_metrics_raises_on_connection_error(repo_config): ) +def test_query_monitoring_metrics_missing_schema_is_empty(repo_config): + mock_client = MagicMock() + mock_client.execute_query.side_effect = TrinoQueryError( + {"errorName": "SCHEMA_NOT_FOUND", "message": "Schema does not exist"} + ) + + with patch( + "feast.infra.offline_stores.contrib.trino_offline_store.trino._get_trino_client", + return_value=mock_client, + ): + res = TrinoOfflineStore.query_monitoring_metrics( + config=repo_config, + project="test_project", + metric_type="feature", + ) + assert res == [] + + +@pytest.mark.parametrize( + "error_name", ["ACCESS_DENIED", "SYNTAX_ERROR", "GENERIC_INTERNAL_ERROR"] +) +def test_query_monitoring_metrics_raises_on_other_query_errors(repo_config, error_name): + # Only a missing table or schema means "no metrics yet". Anything else must not + # reach the monitoring UI as an empty result. + mock_client = MagicMock() + mock_client.execute_query.side_effect = TrinoQueryError( + {"errorName": error_name, "message": "query failed"} + ) + + with patch( + "feast.infra.offline_stores.contrib.trino_offline_store.trino._get_trino_client", + return_value=mock_client, + ): + with pytest.raises(TrinoQueryError) as exc_info: + TrinoOfflineStore.query_monitoring_metrics( + config=repo_config, + project="test_project", + metric_type="feature", + ) + assert exc_info.value.error_name == error_name + + def test_clear_monitoring_baseline_falls_back_on_query_error(repo_config): mock_client = MagicMock() executed_queries = [] diff --git a/sdk/python/feast/infra/offline_stores/contrib/trino_offline_store/trino.py b/sdk/python/feast/infra/offline_stores/contrib/trino_offline_store/trino.py index e55359496e6..16c7d059221 100644 --- a/sdk/python/feast/infra/offline_stores/contrib/trino_offline_store/trino.py +++ b/sdk/python/feast/infra/offline_stores/contrib/trino_offline_store/trino.py @@ -719,12 +719,20 @@ def query_monitoring_metrics( df = df.sort_values(order_col_name) return [normalize_monitoring_row(row.to_dict()) for _, row in df.iterrows()] except TrinoQueryError as e: + if e.error_name in ("TABLE_NOT_FOUND", "SCHEMA_NOT_FOUND"): + # The monitoring table has not been created yet: no metrics so far. + logger.debug( + "Monitoring metrics table %s does not exist yet: %s", + full_table_name, + e, + ) + return [] logger.debug( "Failed to query monitoring metrics from %s: %s", full_table_name, e, ) - return [] + raise @staticmethod def clear_monitoring_baseline(