Skip to content

Commit c74b0e5

Browse files
committed
timeout 900, TelemetryResponse, BaseTelemetryClient in utils
Signed-off-by: Sai Shree Pradhan <saishree.pradhan@databricks.com>
1 parent 85bfe06 commit c74b0e5

File tree

3 files changed

+63
-38
lines changed

3 files changed

+63
-38
lines changed

src/databricks/sql/telemetry/telemetry_client.py

Lines changed: 32 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
import threading
22
import time
3-
import json
43
import requests
54
import logging
65
from concurrent.futures import ThreadPoolExecutor
7-
from typing import Dict, Optional, List
6+
from typing import Dict, Optional
87
from databricks.sql.telemetry.models.event import (
98
TelemetryEvent,
109
DriverSystemConfiguration,
@@ -30,7 +29,7 @@
3029
import platform
3130
import uuid
3231
import locale
33-
from abc import ABC, abstractmethod
32+
from databricks.sql.telemetry.utils import BaseTelemetryClient
3433

3534
logger = logging.getLogger(__name__)
3635

@@ -94,33 +93,6 @@ def get_auth_flow(auth_provider):
9493
return None
9594

9695

97-
class BaseTelemetryClient(ABC):
98-
"""
99-
Base class for telemetry clients.
100-
It is used to define the interface for telemetry clients.
101-
"""
102-
103-
@abstractmethod
104-
def export_initial_telemetry_log(self, driver_connection_params, user_agent):
105-
logger.debug("subclass must implement export_initial_telemetry_log")
106-
pass
107-
108-
@abstractmethod
109-
def export_failure_log(self, error_name, error_message):
110-
logger.debug("subclass must implement export_failure_log")
111-
pass
112-
113-
@abstractmethod
114-
def export_latency_log(self, latency_ms, sql_execution_event, sql_statement_id):
115-
logger.debug("subclass must implement export_latency_log")
116-
pass
117-
118-
@abstractmethod
119-
def close(self):
120-
logger.debug("subclass must implement close")
121-
pass
122-
123-
12496
class NoopTelemetryClient(BaseTelemetryClient):
12597
"""
12698
NoopTelemetryClient is a telemetry client that does not send any events to the server.
@@ -212,6 +184,8 @@ def _send_telemetry(self, events):
212184
protoLogs=[event.to_json() for event in events],
213185
)
214186

187+
sent_count = len(events)
188+
215189
path = (
216190
self.TELEMETRY_AUTHENTICATED_PATH
217191
if self._auth_provider
@@ -231,26 +205,47 @@ def _send_telemetry(self, events):
231205
url,
232206
data=request.to_json(),
233207
headers=headers,
234-
timeout=10,
208+
timeout=900,
235209
)
236-
future.add_done_callback(self._telemetry_request_callback)
210+
future.add_done_callback(self._telemetry_request_callback, sent_count)
237211
except Exception as e:
238212
logger.debug("Failed to submit telemetry request: %s", e)
239213

240-
def _telemetry_request_callback(self, future):
214+
def _telemetry_request_callback(self, future, sent_count: int):
241215
"""Callback function to handle telemetry request completion"""
242216
try:
243217
response = future.result()
244218

245-
if response.status_code == 200:
246-
logger.debug("Telemetry request completed successfully")
247-
else:
219+
if not response.ok:
248220
logger.debug(
249221
"Telemetry request failed with status code: %s, response: %s",
250222
response.status_code,
251223
response.text,
252224
)
253225

226+
telemetry_response = TelemetryResponse.from_json(**response.json())
227+
228+
logger.debug(
229+
"Pushed Telemetry logs with success count: %s, error count: %s",
230+
telemetry_response.numProtoSuccess,
231+
len(telemetry_response.errors),
232+
)
233+
234+
if telemetry_response.errors:
235+
logger.debug(
236+
"Telemetry push failed for some events with errors: %s",
237+
telemetry_response.errors,
238+
)
239+
240+
# Check for partial failures
241+
if sent_count != telemetry_response.numProtoSuccess:
242+
logger.debug(
243+
"Partial failure pushing telemetry. Sent: %s, Succeeded: %s, Errors: %s",
244+
sent_count,
245+
telemetry_response.numProtoSuccess,
246+
telemetry_response.errors,
247+
)
248+
254249
except Exception as e:
255250
logger.debug("Telemetry request failed with exception: %s", e)
256251

@@ -335,7 +330,7 @@ def _initialize(cls):
335330
cls._clients = {}
336331
cls._executor = ThreadPoolExecutor(
337332
max_workers=10
338-
) # Thread pool for async operations TODO: Decide on max workers
333+
) # Thread pool for async operations
339334
cls._install_exception_hook()
340335
cls._initialized = True
341336
logger.debug(

src/databricks/sql/telemetry/utils.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,37 @@
11
import json
22
from enum import Enum
33
from dataclasses import asdict, is_dataclass
4+
from abc import ABC, abstractmethod
5+
import logging
6+
7+
logger = logging.getLogger(__name__)
8+
9+
10+
class BaseTelemetryClient(ABC):
11+
"""
12+
Base class for telemetry clients.
13+
It is used to define the interface for telemetry clients.
14+
"""
15+
16+
@abstractmethod
17+
def export_initial_telemetry_log(self, driver_connection_params, user_agent):
18+
logger.debug("subclass must implement export_initial_telemetry_log")
19+
pass
20+
21+
@abstractmethod
22+
def export_failure_log(self, error_name, error_message):
23+
logger.debug("subclass must implement export_failure_log")
24+
pass
25+
26+
@abstractmethod
27+
def export_latency_log(self, latency_ms, sql_execution_event, sql_statement_id):
28+
logger.debug("subclass must implement export_latency_log")
29+
pass
30+
31+
@abstractmethod
32+
def close(self):
33+
logger.debug("subclass must implement close")
34+
pass
435

536

637
class JsonSerializableMixin:

tests/unit/test_telemetry.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,6 @@ def test_network_request_flow(self, mock_post, mock_telemetry_client):
9494
assert args[0] == requests.post
9595
assert args[1] == 'https://test-host.com/telemetry-ext'
9696
assert kwargs['headers']['Authorization'] == 'Bearer test-token'
97-
assert kwargs['timeout'] == 10
9897

9998
# Verify request body structure
10099
request_data = kwargs['data']

0 commit comments

Comments
 (0)