Skip to content

Commit d2ae1e8

Browse files
authored
Prepare for a release with telemetry on by default (#717)
* Prepare for a release with telemetry on by default Signed-off-by: samikshya-chand_data <samikshya.chand@databricks.com> * Make edits Signed-off-by: samikshya-chand_data <samikshya.chand@databricks.com> * Update version Signed-off-by: samikshya-chand_data <samikshya.chand@databricks.com> * Fix CHANGELOG formatting to match previous style Signed-off-by: samikshya-chand_data <samikshya.chand@databricks.com> * Fix telemetry e2e tests for default-enabled behavior - Update test expectations to reflect telemetry being enabled by default - Add feature flags cache cleanup in teardown to prevent state leakage between tests - This ensures each test runs with fresh feature flag state * Add wait after connection close for async telemetry submission * Remove debug logging from telemetry tests * Mark telemetry e2e tests as serial - must not run in parallel Root cause: Telemetry tests share host-level client across pytest-xdist workers, causing test isolation issues with patches. Tests pass serially but fail with -n auto. Solution: Add @pytest.mark.serial marker. CI needs to run these separately without -n auto. * Split test execution to run serial tests separately Telemetry e2e tests must run serially due to shared host-level telemetry client across pytest-xdist workers. Running with -n auto causes test isolation issues where futures aren't properly captured. Changes: - Run parallel tests with -m 'not serial' -n auto - Run serial tests with -m 'serial' without parallelization - Use --cov-append for serial tests to combine coverage - Mark telemetry e2e tests with @pytest.mark.serial - Update test expectations for default telemetry behavior - Add feature flags cache cleanup in test teardown * Mark telemetry e2e tests as serial - must not run in parallel The concurrent telemetry e2e test globally patches telemetry methods to capture events. When run in parallel with other tests via pytest-xdist, it captures telemetry events from other concurrent tests, causing assertion failures (expected 60 events, got 88). All telemetry e2e tests must run serially to avoid cross-test interference with the shared host-level telemetry client. --------- Signed-off-by: samikshya-chand_data <samikshya.chand@databricks.com>
1 parent ebe4b07 commit d2ae1e8

File tree

9 files changed

+48
-11
lines changed

9 files changed

+48
-11
lines changed

.github/workflows/code-coverage.yml

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,17 +61,32 @@ jobs:
6161
- name: Install library
6262
run: poetry install --no-interaction --all-extras
6363
#----------------------------------------------
64-
# run all tests with coverage
64+
# run parallel tests with coverage
6565
#----------------------------------------------
66-
- name: Run all tests with coverage
66+
- name: Run parallel tests with coverage
6767
continue-on-error: false
6868
run: |
6969
poetry run pytest tests/unit tests/e2e \
70+
-m "not serial" \
7071
-n auto \
7172
--cov=src \
7273
--cov-report=xml \
7374
--cov-report=term \
7475
-v
76+
77+
#----------------------------------------------
78+
# run serial tests with coverage
79+
#----------------------------------------------
80+
- name: Run serial tests with coverage
81+
continue-on-error: false
82+
run: |
83+
poetry run pytest tests/e2e \
84+
-m "serial" \
85+
--cov=src \
86+
--cov-append \
87+
--cov-report=xml \
88+
--cov-report=term \
89+
-v
7590
7691
#----------------------------------------------
7792
# check for coverage override

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
# Release History
22

3+
# 4.2.2 (2025-12-01)
4+
- Change default use_hybrid_disposition to False (databricks/databricks-sql-python#714 by @samikshya-db)
5+
- Circuit breaker changes using pybreaker (databricks/databricks-sql-python#705 by @nikhilsuri-db)
6+
- perf: Optimize telemetry latency logging to reduce overhead (databricks/databricks-sql-python#715 by @samikshya-db)
7+
- basic e2e test for force telemetry verification (databricks/databricks-sql-python#708 by @nikhilsuri-db)
8+
- Telemetry is ON by default to track connection stats. (Note : This strictly excludes PII, query text, and results) (databricks/databricks-sql-python#717 by @samikshya-db)
9+
310
# 4.2.1 (2025-11-20)
411
- Ignore transactions by default (databricks/databricks-sql-python#711 by @jayantsing-db)
512

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ You are welcome to file an issue here for general use cases. You can also contac
1313

1414
## Requirements
1515

16-
Python 3.8 or above is required.
16+
Python 3.9 or above is required.
1717

1818
## Documentation
1919

pyproject.toml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "databricks-sql-connector"
3-
version = "4.2.1"
3+
version = "4.2.2"
44
description = "Databricks SQL Connector for Python"
55
authors = ["Databricks <databricks-sql-connector-maintainers@databricks.com>"]
66
license = "Apache-2.0"
@@ -62,7 +62,10 @@ exclude = ['ttypes\.py$', 'TCLIService\.py$']
6262
exclude = '/(\.eggs|\.git|\.hg|\.mypy_cache|\.nox|\.tox|\.venv|\.svn|_build|buck-out|build|dist|thrift_api)/'
6363

6464
[tool.pytest.ini_options]
65-
markers = {"reviewed" = "Test case has been reviewed by Databricks"}
65+
markers = [
66+
"reviewed: Test case has been reviewed by Databricks",
67+
"serial: Tests that must run serially (not parallelized)"
68+
]
6669
minversion = "6.0"
6770
log_cli = "false"
6871
log_cli_level = "INFO"

src/databricks/sql/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ def __repr__(self):
7171
DATE = DBAPITypeObject("date")
7272
ROWID = DBAPITypeObject()
7373

74-
__version__ = "4.2.1"
74+
__version__ = "4.2.2"
7575
USER_AGENT_NAME = "PyDatabricksSqlConnector"
7676

7777
# These two functions are pyhive legacy

src/databricks/sql/auth/common.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ def __init__(
5151
pool_connections: Optional[int] = None,
5252
pool_maxsize: Optional[int] = None,
5353
user_agent: Optional[str] = None,
54-
telemetry_circuit_breaker_enabled: Optional[bool] = None,
54+
telemetry_circuit_breaker_enabled: Optional[bool] = True,
5555
):
5656
self.hostname = hostname
5757
self.access_token = access_token

src/databricks/sql/client.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,7 @@ def read(self) -> Optional[OAuthToken]:
328328
self.ignore_transactions = ignore_transactions
329329

330330
self.force_enable_telemetry = kwargs.get("force_enable_telemetry", False)
331-
self.enable_telemetry = kwargs.get("enable_telemetry", False)
331+
self.enable_telemetry = kwargs.get("enable_telemetry", True)
332332
self.telemetry_enabled = TelemetryHelper.is_telemetry_enabled(self)
333333

334334
TelemetryClientFactory.initialize_telemetry_client(

tests/e2e/test_concurrent_telemetry.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ def run_in_threads(target, num_threads, pass_index=False):
2626
t.join()
2727

2828

29+
@pytest.mark.serial
2930
class TestE2ETelemetry(PySQLPytestTestCase):
3031
@pytest.fixture(autouse=True)
3132
def telemetry_setup_teardown(self):

tests/e2e/test_telemetry_e2e.py

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,9 @@ def connection(self, extra_params=()):
4343
conn.close()
4444

4545

46+
@pytest.mark.serial
4647
class TestTelemetryE2E(TelemetryTestBase):
47-
"""E2E tests for telemetry scenarios"""
48+
"""E2E tests for telemetry scenarios - must run serially due to shared host-level telemetry client"""
4849

4950
@pytest.fixture(autouse=True)
5051
def telemetry_setup_teardown(self):
@@ -58,6 +59,14 @@ def telemetry_setup_teardown(self):
5859
TelemetryClientFactory._stop_flush_thread()
5960
TelemetryClientFactory._initialized = False
6061

62+
# Clear feature flags cache to prevent state leakage between tests
63+
from databricks.sql.common.feature_flag import FeatureFlagsContextFactory
64+
with FeatureFlagsContextFactory._lock:
65+
FeatureFlagsContextFactory._context_map.clear()
66+
if FeatureFlagsContextFactory._executor:
67+
FeatureFlagsContextFactory._executor.shutdown(wait=False)
68+
FeatureFlagsContextFactory._executor = None
69+
6170
@pytest.fixture
6271
def telemetry_interceptors(self):
6372
"""Setup reusable telemetry interceptors as a fixture"""
@@ -142,7 +151,7 @@ def verify_events(self, captured_events, captured_futures, expected_count):
142151
else:
143152
assert len(captured_events) == expected_count, \
144153
f"Expected {expected_count} events, got {len(captured_events)}"
145-
154+
146155
time.sleep(2)
147156
done, _ = wait(captured_futures, timeout=10)
148157
assert len(done) == expected_count, \
@@ -163,7 +172,7 @@ def verify_events(self, captured_events, captured_futures, expected_count):
163172
(True, False, 2, "enable_on_force_off"),
164173
(False, True, 2, "enable_off_force_on"),
165174
(False, False, 0, "both_off"),
166-
(None, None, 0, "default_behavior"),
175+
(None, None, 2, "default_behavior"),
167176
])
168177
def test_telemetry_flags(self, telemetry_interceptors, enable_telemetry,
169178
force_enable, expected_count, test_id):
@@ -185,6 +194,8 @@ def test_telemetry_flags(self, telemetry_interceptors, enable_telemetry,
185194
cursor.execute("SELECT 1")
186195
cursor.fetchone()
187196

197+
# Give time for async telemetry submission after connection closes
198+
time.sleep(0.5)
188199
self.verify_events(captured_events, captured_futures, expected_count)
189200

190201
# Assert statement execution on latency event (if events exist)

0 commit comments

Comments
 (0)