23
23
from abc import ABC , abstractmethod
24
24
25
25
26
+ < << << << HEAD
26
27
class BaseTelemetryClient (ABC ):
27
28
@abstractmethod
28
29
def export_initial_telemetry_log (self , ** kwargs ):
@@ -52,13 +53,29 @@ class TelemetryClient(BaseTelemetryClient):
52
53
def __init__ (self , telemetry_enabled , batch_size , connection_uuid , ** kwargs ):
53
54
self .telemetry_enabled = telemetry_enabled
54
55
self .batch_size = batch_size
56
+ == == == =
57
+ class TelemetryClient :
58
+ def __init__ (
59
+ self ,
60
+ host ,
61
+ connection_uuid ,
62
+ batch_size ,
63
+ auth_provider = None ,
64
+ is_authenticated = False ,
65
+ user_agent = None ,
66
+ ):
67
+ self .host_url = host
68
+ > >> >> >> parent of 419 dac3 (shifted thread pool executor to telemetry manager )
55
69
self .connection_uuid = connection_uuid
56
- self .host_url = kwargs . get ( "host_url" , None )
57
- self .auth_provider = kwargs . get ( "auth_provider" , None )
58
- self .is_authenticated = kwargs . get ( "is_authenticated" , False )
59
- self .user_agent = kwargs . get ( " user_agent" , None )
70
+ self .auth_provider = auth_provider
71
+ self .is_authenticated = is_authenticated
72
+ self .batch_size = batch_size
73
+ self .user_agent = user_agent
60
74
self .events_batch = []
61
75
self .lock = threading .Lock ()
76
+ self .executor = ThreadPoolExecutor (
77
+ max_workers = 10 # TODO: Decide on max workers
78
+ ) # Thread pool for async operations
62
79
self .DriverConnectionParameters = None
63
80
64
81
def export_event (self , event ):
@@ -75,18 +92,67 @@ def flush(self):
75
92
self .events_batch = []
76
93
77
94
if events_to_flush :
95
+ < << << << HEAD
78
96
telemetry_client_factory ._send_telemetry (
79
97
events_to_flush ,
80
98
self .host_url ,
81
99
self .is_authenticated ,
82
100
self .auth_provider ,
83
101
)
102
+ == == == =
103
+ self .executor .submit (self ._send_telemetry , events_to_flush )
84
104
85
- def export_initial_telemetry_log (self , ** kwargs ):
86
- http_path = kwargs .get ("http_path" , None )
87
- port = kwargs .get ("port" , None )
88
- socket_timeout = kwargs .get ("socket_timeout" , None )
105
+ def _send_telemetry (self , events ):
106
+ """Send telemetry events to the server"""
107
+ request = {
108
+ "uploadTime" : int (time .time () * 1000 ),
109
+ "items" : [],
110
+ "protoLogs" : [event .to_json () for event in events ],
111
+ }
112
+
113
+ path = "/telemetry-ext" if self .is_authenticated else "/telemetry-unauth"
114
+ url = f"https://{ self .host_url } { path } "
115
+
116
+ headers = {"Accept" : "application/json" , "Content-Type" : "application/json" }
89
117
118
+ if self .is_authenticated and self .auth_provider :
119
+ self .auth_provider .add_headers (headers )
120
+
121
+ # print("\n=== Request Details ===", flush=True)
122
+ # print(f"URL: {url}", flush=True)
123
+ # print("\nHeaders:", flush=True)
124
+ # for key, value in headers.items():
125
+ # print(f" {key}: {value}", flush=True)
126
+
127
+ # print("\nRequest Body:", flush=True)
128
+ # print(json.dumps(request, indent=2), flush=True)
129
+ # sys.stdout.flush()
130
+
131
+ response = requests .post (
132
+ url , data = json .dumps (request ), headers = headers , timeout = 10
133
+ )
134
+
135
+ # print("\n=== Response Details ===", flush=True)
136
+ # print(f"Status Code: {response.status_code}", flush=True)
137
+ # print("\nResponse Headers:", flush=True)
138
+ # for key, value in response.headers.items():
139
+ # print(f" {key}: {value}", flush=True)
140
+
141
+ # print("\nResponse Body:", flush=True)
142
+ # try:
143
+ # response_json = response.json()
144
+ # print(json.dumps(response_json, indent=2), flush=True)
145
+ # except json.JSONDecodeError:
146
+ # print(response.text, flush=True)
147
+ # sys.stdout.flush()
148
+
149
+ def close (self ):
150
+ """Flush remaining events and shut down executor"""
151
+ self .flush ()
152
+ self .executor .shutdown (wait = True )
153
+ >> >> >> > parent of 419 dac3 (shifted thread pool executor to telemetry manager )
154
+
155
+ def export_initial_telemetry_log (self , http_path , port , socket_timeout ):
90
156
discovery_url = None
91
157
if hasattr (self .auth_provider , "oauth_manager" ) and hasattr (
92
158
self .auth_provider .oauth_manager , "idp_endpoint"
@@ -123,10 +189,26 @@ def export_initial_telemetry_log(self, **kwargs):
123
189
124
190
self .export_event (telemetry_frontend_log )
125
191
192
+ < << << << HEAD
126
193
def close (self ):
127
194
"""Flush remaining events before closing"""
128
195
self .flush ()
129
196
telemetry_client_factory .close (self .connection_uuid )
197
+ == == == =
198
+ def export_failure_log (self , errorName , errorMessage ):
199
+ pass
200
+
201
+ def export_sql_latency_log (
202
+ self , latency_ms , sql_execution_event , sql_statement_id = None
203
+ ):
204
+ """Export telemetry for sql execution"""
205
+ pass
206
+
207
+ def export_volume_latency_log (self , latency_ms , volume_operation ):
208
+ """Export telemetry for volume operation"""
209
+ pass
210
+
211
+ >> >> >> > parent of 419 dac3 (shifted thread pool executor to telemetry manager )
130
212
131
213
132
214
class TelemetryClientFactory :
@@ -145,6 +227,7 @@ def __init__(self):
145
227
return
146
228
147
229
self ._clients = {} # Map of connection_uuid -> TelemetryClient
230
+ < << << << HEAD
148
231
self .executor = ThreadPoolExecutor (
149
232
max_workers = 10
150
233
) # Thread pool for async operations TODO: Decide on max workers
@@ -186,6 +269,59 @@ def _send_telemetry(self, events, host_url, is_authenticated, auth_provider):
186
269
requests .post , url , data = json .dumps (request ), headers = headers , timeout = 10
187
270
)
188
271
272
+ == == == =
273
+ self ._initialized = True
274
+
275
+ def initialize (
276
+ self ,
277
+ host ,
278
+ connection_uuid ,
279
+ batch_size ,
280
+ auth_provider = None ,
281
+ is_authenticated = False ,
282
+ user_agent = None ,
283
+ ):
284
+ """Initialize a telemetry client for a specific connection"""
285
+ if connection_uuid not in self ._clients :
286
+ self ._clients [connection_uuid ] = TelemetryClient (
287
+ host = host ,
288
+ connection_uuid = connection_uuid ,
289
+ batch_size = batch_size ,
290
+ auth_provider = auth_provider ,
291
+ is_authenticated = is_authenticated ,
292
+ user_agent = user_agent ,
293
+ )
294
+
295
+ def export_failure_log (self , error_name , error_message , connection_uuid ):
296
+ """Export error logs for a specific connection or all connections if connection_uuid is None"""
297
+ pass
298
+
299
+ def export_initial_telemetry_log (
300
+ self , http_path , port , socket_timeout , connection_uuid
301
+ ):
302
+ """Export initial telemetry for a specific connection"""
303
+ if connection_uuid in self ._clients :
304
+ self ._clients [connection_uuid ].export_initial_telemetry_log (
305
+ http_path , port , socket_timeout
306
+ )
307
+
308
+ def export_sql_latency_log (
309
+ self ,
310
+ latency_ms ,
311
+ sql_execution_event ,
312
+ sql_statement_id = None ,
313
+ connection_uuid = None ,
314
+ ):
315
+ """Export latency logs for sql execution for a specific connection"""
316
+ pass
317
+
318
+ def export_volume_latency_log (
319
+ self , latency_ms , volume_operation , connection_uuid = None
320
+ ):
321
+ """Export latency logs for volume operation for a specific connection"""
322
+ pass
323
+
324
+ >> >> >> > parent of 419 dac3 (shifted thread pool executor to telemetry manager )
189
325
@classmethod
190
326
def getDriverSystemConfiguration (cls ) -> DriverSystemConfiguration :
191
327
if cls ._DRIVER_SYSTEM_CONFIGURATION is None :
@@ -207,6 +343,7 @@ def getDriverSystemConfiguration(cls) -> DriverSystemConfiguration:
207
343
return cls ._DRIVER_SYSTEM_CONFIGURATION
208
344
209
345
def close (self , connection_uuid ):
346
+ < << << << HEAD
210
347
del self ._clients [connection_uuid ]
211
348
212
349
# Shutdown executor if no more clients
@@ -216,3 +353,14 @@ def close(self, connection_uuid):
216
353
217
354
# Create a global instance
218
355
telemetry_client_factory = TelemetryClientFactory ()
356
+ == == == =
357
+ """Close telemetry client(s)"""
358
+ if connection_uuid :
359
+ if connection_uuid in self ._clients :
360
+ self ._clients [connection_uuid ].close ()
361
+ del self ._clients [connection_uuid ]
362
+
363
+
364
+ # Create a global instance
365
+ telemetry_client = TelemetryManager ()
366
+ > >> >> >> parent of 419 dac3 (shifted thread pool executor to telemetry manager )
0 commit comments