33import json
44import requests
55from concurrent .futures import ThreadPoolExecutor
6- import logging
7- from abc import ABC , abstractmethod
86from databricks .sql .telemetry .models .event import (
97 TelemetryEvent ,
108 DriverConnectionParameters ,
119 DriverSystemConfiguration ,
12- DriverErrorInfo ,
13- DriverVolumeOperation ,
14- SqlExecutionEvent ,
1510 HostDetails ,
1611)
1712from databricks .sql .telemetry .models .frontend_logs import (
2722import locale
2823
2924
30- class BaseTelemetryClient (ABC ):
31- """Abstract base class for telemetry clients."""
32-
33- @abstractmethod
34- def export_event (self , event ):
35- pass
36-
37- @abstractmethod
38- def flush (self ):
39- pass
40-
41- @abstractmethod
42- def close (self ):
43- pass
44-
45- @abstractmethod
46- def export_initial_telemetry_log (self , http_path , port , socket_timeout ):
47- pass
48-
49-
50- class TelemetryClient (BaseTelemetryClient ):
25+ class TelemetryClient :
5126 def __init__ (
5227 self ,
5328 host ,
@@ -71,14 +46,14 @@ def __init__(
7146 self .DriverConnectionParameters = None
7247
7348 def export_event (self , event ):
74- # Add an event to the batch queue and flush if batch is full
49+ """ Add an event to the batch queue and flush if batch is full"""
7550 with self .lock :
7651 self .events_batch .append (event )
7752 if len (self .events_batch ) >= self .batch_size :
7853 self .flush ()
7954
8055 def flush (self ):
81- # Flush the current batch of events to the server
56+ """ Flush the current batch of events to the server"""
8257 with self .lock :
8358 events_to_flush = self .events_batch .copy ()
8459 self .events_batch = []
@@ -87,7 +62,7 @@ def flush(self):
8762 self .executor .submit (self ._send_telemetry , events_to_flush )
8863
8964 def _send_telemetry (self , events ):
90- # Send telemetry events to the server
65+ """ Send telemetry events to the server"""
9166 request = {
9267 "uploadTime" : int (time .time () * 1000 ),
9368 "items" : [],
@@ -102,12 +77,36 @@ def _send_telemetry(self, events):
10277 if self .is_authenticated and self .auth_provider :
10378 self .auth_provider .add_headers (headers )
10479
80+ # print("\n=== Request Details ===", flush=True)
81+ # print(f"URL: {url}", flush=True)
82+ # print("\nHeaders:", flush=True)
83+ # for key, value in headers.items():
84+ # print(f" {key}: {value}", flush=True)
85+
86+ # print("\nRequest Body:", flush=True)
87+ # print(json.dumps(request, indent=2), flush=True)
88+ # sys.stdout.flush()
89+
10590 response = requests .post (
10691 url , data = json .dumps (request ), headers = headers , timeout = 10
10792 )
10893
94+ # print("\n=== Response Details ===", flush=True)
95+ # print(f"Status Code: {response.status_code}", flush=True)
96+ # print("\nResponse Headers:", flush=True)
97+ # for key, value in response.headers.items():
98+ # print(f" {key}: {value}", flush=True)
99+
100+ # print("\nResponse Body:", flush=True)
101+ # try:
102+ # response_json = response.json()
103+ # print(json.dumps(response_json, indent=2), flush=True)
104+ # except json.JSONDecodeError:
105+ # print(response.text, flush=True)
106+ # sys.stdout.flush()
107+
109108 def close (self ):
110- # Flush remaining events and shut down executor
109+ """ Flush remaining events and shut down executor"""
111110 self .flush ()
112111 self .executor .shutdown (wait = True )
113112
@@ -162,23 +161,20 @@ def export_volume_latency_log(self, latency_ms, volume_operation):
162161 pass
163162
164163
165- class NoopTelemetryClient (BaseTelemetryClient ):
166- """A no-operation telemetry client that implements the same interface but does nothing"""
167-
168- def export_event (self , event ):
169- pass
170-
171- def flush (self ):
172- pass
164+ class TelemetryManager :
165+ """A singleton manager class that handles telemetry operations for SQL connections.
173166
174- def close (self ):
175- pass
176-
177- def export_initial_telemetry_log (self , http_path , port , socket_timeout ):
178- pass
167+ This class maintains a map of connection_uuid to TelemetryClient instances. The initialize()
168+ method is only called from the connection class when telemetry is enabled for that connection.
169+ All telemetry operations (initial logs, failure logs, latency logs) first check if the
170+ connection_uuid exists in the map. If it doesn't exist (meaning telemetry was not enabled
171+ for that connection), the operation is skipped. If it exists, the operation is delegated
172+ to the corresponding TelemetryClient instance.
179173
174+ This design ensures that telemetry operations are only performed for connections where
175+ telemetry was explicitly enabled during initialization.
176+ """
180177
181- class TelemetryManager :
182178 _instance = None
183179 _DRIVER_SYSTEM_CONFIGURATION = None
184180
0 commit comments