Skip to content

Commit a5c698c

Browse files
committed
linting issue resolved
Signed-off-by: Nikhil Suri <nikhil.suri@databricks.com>
1 parent cca26eb commit a5c698c

File tree

6 files changed

+907
-2
lines changed

6 files changed

+907
-2
lines changed

BUG_FIX_SUMMARY.md

Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
# Bug Fix Summary: telemetry_client.py Line 547
2+
3+
## Issue Description
4+
**File**: `src/databricks/sql/telemetry/telemetry_client.py`
5+
**Line**: 547
6+
**Severity**: High (Runtime AttributeError)
7+
**Detected By**: Stricter MyPy configuration
8+
9+
## The Bug
10+
11+
### Before (Incorrect)
12+
```python:545:547:src/databricks/sql/telemetry/telemetry_client.py
13+
clients_to_close = list(cls._clients.values())
14+
for client in clients_to_close:
15+
client.close() #BUG: client is _TelemetryClientHolder, not TelemetryClient!
16+
```
17+
18+
### After (Correct)
19+
```python:545:547:src/databricks/sql/telemetry/telemetry_client.py
20+
clients_to_close = list(cls._clients.values())
21+
for holder in clients_to_close:
22+
holder.client.close() # ✅ FIXED: Access the client attribute
23+
```
24+
25+
## Root Cause Analysis
26+
27+
### Data Structure
28+
```python
29+
# Class definition (line 425-442)
30+
class _TelemetryClientHolder:
31+
"""Holds a telemetry client with reference counting."""
32+
33+
def __init__(self, client: BaseTelemetryClient):
34+
self.client = client # The actual TelemetryClient instance
35+
self.refcount = 1
36+
37+
def increment(self):
38+
self.refcount += 1
39+
40+
def decrement(self):
41+
self.refcount -= 1
42+
return self.refcount
43+
```
44+
45+
### The Issue
46+
1. `cls._clients` is a `Dict[str, _TelemetryClientHolder]`
47+
2. `cls._clients.values()` returns `_TelemetryClientHolder` objects
48+
3. `_TelemetryClientHolder` does NOT have a `close()` method
49+
4. Only `_TelemetryClientHolder.client` (the wrapped `BaseTelemetryClient`) has `close()`
50+
51+
### Runtime Error
52+
Without the fix, this code would crash with:
53+
```python
54+
AttributeError: '_TelemetryClientHolder' object has no attribute 'close'
55+
```
56+
57+
## How MyPy Caught This
58+
59+
### Current Configuration (pyproject.toml)
60+
```toml
61+
[tool.mypy]
62+
ignore_missing_imports = "true"
63+
exclude = ['ttypes\.py$', 'TCLIService\.py$']
64+
```
65+
**Result**: ✅ No errors reported (bug not caught!)
66+
67+
### Stricter Configuration
68+
```toml
69+
[tool.mypy]
70+
ignore_missing_imports = false
71+
check_untyped_defs = true
72+
disallow_any_generics = true
73+
show_error_codes = true
74+
# ... additional strict settings
75+
```
76+
77+
**Result**: ❌ Error caught!
78+
```
79+
src/databricks/sql/telemetry/telemetry_client.py:547:13: error:
80+
"_TelemetryClientHolder" has no attribute "close" [attr-defined]
81+
client.close()
82+
```
83+
84+
## Correct Pattern Used Elsewhere
85+
86+
### Example from Line 518-521 (Correct)
87+
```python:518:521:src/databricks/sql/telemetry/telemetry_client.py
88+
with cls._lock:
89+
clients_to_flush = list(cls._clients.values())
90+
91+
for holder in clients_to_flush: # ✅ Correct: named 'holder'
92+
holder.client._flush() # ✅ Correct: access .client attribute
93+
```
94+
95+
This shows the pattern was used correctly elsewhere in the same file, making the bug at line 547 inconsistent with the established pattern.
96+
97+
## Impact Assessment
98+
99+
### When Would This Bug Occur?
100+
The buggy code is in `_handle_unhandled_exception()`, which runs when:
101+
1. An unhandled Python exception occurs in the application
102+
2. The global exception hook intercepts it
103+
3. The code attempts to close all telemetry clients
104+
105+
### Severity
106+
- **High**: Would cause secondary crash when handling primary exception
107+
- **Masking**: Original exception might be obscured by the AttributeError
108+
- **User Experience**: Poor error reporting and telemetry loss
109+
- **Rare**: Only triggers on unhandled exceptions
110+
111+
## Testing
112+
113+
### Verification Test
114+
```bash
115+
# Run with strict mypy config
116+
./venv/bin/python -m mypy --config-file=mypy-strict.ini \
117+
src/databricks/sql/telemetry/telemetry_client.py
118+
119+
# Before fix: Shows error at line 547
120+
# After fix: No attribute error at line 547 ✅
121+
```
122+
123+
### Unit Test Recommendation
124+
```python
125+
def test_handle_unhandled_exception_closes_all_clients():
126+
"""Test that unhandled exception handler properly closes all clients."""
127+
# Setup: Create factory with multiple clients
128+
factory = TelemetryClientFactory
129+
factory._initialize()
130+
131+
# Create mock clients
132+
mock_client_1 = Mock(spec=TelemetryClient)
133+
mock_client_2 = Mock(spec=TelemetryClient)
134+
135+
holder_1 = _TelemetryClientHolder(mock_client_1)
136+
holder_2 = _TelemetryClientHolder(mock_client_2)
137+
138+
factory._clients = {
139+
"host1": holder_1,
140+
"host2": holder_2
141+
}
142+
143+
# Simulate unhandled exception
144+
try:
145+
raise ValueError("Test exception")
146+
except ValueError:
147+
exc_info = sys.exc_info()
148+
factory._handle_unhandled_exception(*exc_info)
149+
150+
# Verify both clients were closed
151+
mock_client_1.close.assert_called_once()
152+
mock_client_2.close.assert_called_once()
153+
```
154+
155+
## Recommendations
156+
157+
1. **Immediate**:
158+
- ✅ Fix applied to `telemetry_client.py:547`
159+
- Review other occurrences of `cls._clients.values()` usage
160+
161+
2. **Short-term**:
162+
- Adopt Phase 1 mypy configuration (see `MYPY_RECOMMENDATIONS.md`)
163+
- Add unit test for `_handle_unhandled_exception()`
164+
165+
3. **Long-term**:
166+
- Enable stricter mypy checks across codebase
167+
- Add CI/CD integration for mypy
168+
- Implement pre-commit hooks
169+
170+
## Related Files
171+
- `MYPY_RECOMMENDATIONS.md` - Comprehensive mypy improvement guide
172+
- `pyproject.toml.recommended` - Updated configuration with Phase 1 rules
173+
- `mypy-strict.ini` - Strict configuration used to detect this bug
174+
175+
## References
176+
- MyPy error code: `[attr-defined]`
177+
- Related pattern: Lines 518-521 (correct usage)
178+
- Class definition: Lines 425-442 (`_TelemetryClientHolder`)
179+
180+
---
181+
**Fixed by**: @nikhil.suri
182+
**Date**: 2025-12-30
183+
**Reviewer**: @P JOTHI PRAKASH
184+

0 commit comments

Comments
 (0)