Skip to content

Commit 80ac99e

Browse files
committed
fix log filtering
1 parent 96bb28c commit 80ac99e

5 files changed

Lines changed: 143 additions & 12 deletions

File tree

ingestion/src/metadata/ingestion/source/database/databricks/connection.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
Source connection handler
1414
"""
1515

16-
import logging
1716
from copy import deepcopy
1817
from functools import partial
1918
from typing import Optional
@@ -44,6 +43,9 @@
4443
)
4544
from metadata.ingestion.ometa.ometa_api import OpenMetadata
4645
from metadata.ingestion.source.database.databricks.auth import get_auth_config
46+
from metadata.ingestion.source.database.databricks.log_filters import (
47+
suppress_user_agent_entry_deprecation_log,
48+
)
4749
from metadata.ingestion.source.database.databricks.queries import (
4850
DATABRICKS_GET_CATALOGS,
4951
DATABRICKS_SQL_STATEMENT_TEST,
@@ -60,9 +62,7 @@
6062

6163
logger = ingestion_logger()
6264

63-
# Suppress noisy deprecation warning from databricks-sqlalchemy using
64-
# the deprecated '_user_agent_entry' parameter internally
65-
logging.getLogger("databricks.sql.session").setLevel(logging.ERROR)
65+
suppress_user_agent_entry_deprecation_log()
6666

6767

6868
class DatabricksEngineWrapper:
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# Copyright 2025 Collate
2+
# Licensed under the Collate Community License, Version 1.0 (the "License");
3+
# you may not use this file except in compliance with the License.
4+
# You may obtain a copy of the License at
5+
# https://github.com/open-metadata/OpenMetadata/blob/main/ingestion/LICENSE
6+
# Unless required by applicable law or agreed to in writing, software
7+
# distributed under the License is distributed on an "AS IS" BASIS,
8+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9+
# See the License for the specific language governing permissions and
10+
# limitations under the License.
11+
12+
"""
13+
Logging filters for Databricks SQL connector noise.
14+
"""
15+
16+
import logging
17+
18+
_DATABRICKS_SESSION_LOGGER = "databricks.sql.session"
19+
_DEPRECATED_PARAM_FRAGMENT = "_user_agent_entry"
20+
_FILTER_INSTALLED_FLAG = "_om_user_agent_entry_filter_installed"
21+
22+
23+
class _UserAgentEntryDeprecationFilter(logging.Filter):
24+
def filter(self, record: logging.LogRecord) -> bool:
25+
try:
26+
message = record.getMessage()
27+
except Exception:
28+
return True
29+
return _DEPRECATED_PARAM_FRAGMENT not in message
30+
31+
32+
def suppress_user_agent_entry_deprecation_log() -> None:
33+
"""
34+
Drop the `_user_agent_entry` deprecation log emitted by databricks-sqlalchemy
35+
without changing the level of the `databricks.sql.session` logger, so
36+
user-configured logging is preserved and other records flow through normally.
37+
Idempotent: safe to call from multiple connector modules at import time.
38+
"""
39+
target_logger = logging.getLogger(_DATABRICKS_SESSION_LOGGER)
40+
if getattr(target_logger, _FILTER_INSTALLED_FLAG, False):
41+
return
42+
target_logger.addFilter(_UserAgentEntryDeprecationFilter())
43+
setattr(target_logger, _FILTER_INSTALLED_FLAG, True)

ingestion/src/metadata/ingestion/source/database/unitycatalog/connection.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
Source connection handler
1414
"""
1515

16-
import logging
1716
from copy import deepcopy
1817
from functools import partial
1918
from typing import Optional
@@ -50,6 +49,9 @@
5049
from metadata.ingestion.connections.test_connections import test_connection_steps
5150
from metadata.ingestion.ometa.ometa_api import OpenMetadata
5251
from metadata.ingestion.source.database.databricks.auth import get_auth_config
52+
from metadata.ingestion.source.database.databricks.log_filters import (
53+
suppress_user_agent_entry_deprecation_log,
54+
)
5355
from metadata.ingestion.source.database.unitycatalog.models import DatabricksTable
5456
from metadata.ingestion.source.database.unitycatalog.queries import (
5557
UNITY_CATALOG_GET_ALL_SCHEMA_TAGS,
@@ -65,9 +67,7 @@
6567

6668
logger = ingestion_logger()
6769

68-
# Suppress noisy deprecation warning from databricks-sqlalchemy using
69-
# the deprecated '_user_agent_entry' parameter internally
70-
logging.getLogger("databricks.sql.session").setLevel(logging.ERROR)
70+
suppress_user_agent_entry_deprecation_log()
7171

7272

7373
def get_connection_url(connection: UnityCatalogConnection) -> str:

ingestion/src/metadata/ingestion/source/pipeline/databrickspipeline/connection.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
Source connection handler
1414
"""
1515

16-
import logging
1716
from typing import Optional
1817

1918
from metadata.generated.schema.entity.automations.workflow import (
@@ -33,11 +32,12 @@
3332
from metadata.ingestion.connections.test_connections import test_connection_steps
3433
from metadata.ingestion.ometa.ometa_api import OpenMetadata
3534
from metadata.ingestion.source.database.databricks.client import DatabricksClient
35+
from metadata.ingestion.source.database.databricks.log_filters import (
36+
suppress_user_agent_entry_deprecation_log,
37+
)
3638
from metadata.utils.constants import THREE_MIN
3739

38-
# Suppress noisy deprecation warning from databricks-sqlalchemy using
39-
# the deprecated '_user_agent_entry' parameter internally
40-
logging.getLogger("databricks.sql.session").setLevel(logging.ERROR)
40+
suppress_user_agent_entry_deprecation_log()
4141

4242

4343
def get_connection_url(connection: DatabricksPipelineConnection) -> str:
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
# Copyright 2025 Collate
2+
# Licensed under the Collate Community License, Version 1.0 (the "License");
3+
# you may not use this file except in compliance with the License.
4+
# You may obtain a copy of the License at
5+
# https://github.com/open-metadata/OpenMetadata/blob/main/ingestion/LICENSE
6+
# Unless required by applicable law or agreed to in writing, software
7+
# distributed under the License is distributed on an "AS IS" BASIS,
8+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9+
# See the License for the specific language governing permissions and
10+
# limitations under the License.
11+
12+
"""
13+
Tests for the databricks.sql.session log filter helper.
14+
"""
15+
16+
import logging
17+
18+
import pytest
19+
20+
from metadata.ingestion.source.database.databricks import log_filters
21+
from metadata.ingestion.source.database.databricks.log_filters import (
22+
suppress_user_agent_entry_deprecation_log,
23+
)
24+
25+
DATABRICKS_SESSION_LOGGER = "databricks.sql.session"
26+
27+
28+
@pytest.fixture
29+
def clean_logger():
30+
target = logging.getLogger(DATABRICKS_SESSION_LOGGER)
31+
original_filters = list(target.filters)
32+
original_level = target.level
33+
had_flag = hasattr(target, log_filters._FILTER_INSTALLED_FLAG)
34+
flag_value = getattr(target, log_filters._FILTER_INSTALLED_FLAG, None)
35+
36+
target.filters = []
37+
if had_flag:
38+
delattr(target, log_filters._FILTER_INSTALLED_FLAG)
39+
40+
yield target
41+
42+
target.filters = original_filters
43+
target.setLevel(original_level)
44+
if had_flag:
45+
setattr(target, log_filters._FILTER_INSTALLED_FLAG, flag_value)
46+
elif hasattr(target, log_filters._FILTER_INSTALLED_FLAG):
47+
delattr(target, log_filters._FILTER_INSTALLED_FLAG)
48+
49+
50+
def _emit(logger: logging.Logger, message: str) -> logging.LogRecord:
51+
record = logger.makeRecord(logger.name, logging.WARNING, __file__, 0, message, None, None)
52+
return record
53+
54+
55+
def test_filters_user_agent_entry_message(clean_logger):
56+
suppress_user_agent_entry_deprecation_log()
57+
58+
record = _emit(
59+
clean_logger,
60+
"Parameter '_user_agent_entry' is deprecated, use 'user_agent_entry' instead",
61+
)
62+
63+
assert clean_logger.filters, "Expected the suppression filter to be installed"
64+
assert all(f.filter(record) is False for f in clean_logger.filters)
65+
66+
67+
def test_unrelated_warning_passes_through(clean_logger):
68+
suppress_user_agent_entry_deprecation_log()
69+
70+
record = _emit(clean_logger, "Connection retry: attempt 2 of 3")
71+
72+
assert all(f.filter(record) is True for f in clean_logger.filters)
73+
74+
75+
def test_logger_level_is_not_modified(clean_logger):
76+
clean_logger.setLevel(logging.DEBUG)
77+
78+
suppress_user_agent_entry_deprecation_log()
79+
80+
assert clean_logger.level == logging.DEBUG
81+
82+
83+
def test_helper_is_idempotent(clean_logger):
84+
suppress_user_agent_entry_deprecation_log()
85+
suppress_user_agent_entry_deprecation_log()
86+
suppress_user_agent_entry_deprecation_log()
87+
88+
assert len(clean_logger.filters) == 1

0 commit comments

Comments
 (0)