@@ -142,4 +142,114 @@ describe('Telemetry E2E Test (Local Only)', () => {
142142 fetchStub . restore ( ) ;
143143 }
144144 } ) ;
145+
146+ it ( 'should send error telemetry for invalid query' , async function ( ) {
147+ this . timeout ( 30000 ) ;
148+
149+ // Check for required environment variables
150+ const host = process . env . DATABRICKS_SERVER_HOSTNAME ;
151+ const path = process . env . DATABRICKS_HTTP_PATH ;
152+ const token = process . env . DATABRICKS_TOKEN ;
153+
154+ if ( ! host || ! path || ! token ) {
155+ console . log ( '\n❌ Skipping test: Missing environment variables' ) ;
156+ this . skip ( ) ;
157+ return ;
158+ }
159+
160+ console . log ( '\n' + '=' . repeat ( 60 ) ) ;
161+ console . log ( 'TELEMETRY ERROR SCENARIO TEST' ) ;
162+ console . log ( '=' . repeat ( 60 ) ) ;
163+
164+ // Stub fetch to capture telemetry payloads
165+ const originalFetch = nodeFetch . default ;
166+ fetchStub = sinon . stub ( nodeFetch , 'default' ) . callsFake ( async ( url : any , options ?: any ) => {
167+ // Capture and log telemetry requests
168+ if ( typeof url === 'string' && ( url . includes ( '/telemetry-ext' ) || url . includes ( '/telemetry-unauth' ) ) ) {
169+ const body = options ?. body ? JSON . parse ( options . body ) : null ;
170+
171+ console . log ( '\n' + '=' . repeat ( 60 ) ) ;
172+ console . log ( '📊 TELEMETRY REQUEST CAPTURED' ) ;
173+ console . log ( '=' . repeat ( 60 ) ) ;
174+ console . log ( 'URL:' , url ) ;
175+
176+ if ( body && body . protoLogs ) {
177+ console . log ( `\nProtoLogs count: ${ body . protoLogs . length } ` ) ;
178+ body . protoLogs . forEach ( ( log : string , index : number ) => {
179+ const parsed = JSON . parse ( log ) ;
180+ console . log ( `\n--- ProtoLog ${ index + 1 } ---` ) ;
181+ console . log ( JSON . stringify ( parsed , null , 2 ) ) ;
182+ } ) ;
183+ }
184+ console . log ( '=' . repeat ( 60 ) + '\n' ) ;
185+ }
186+
187+ // Call original fetch
188+ return originalFetch ( url , options ) ;
189+ } ) ;
190+
191+ const client = new DBSQLClient ( {
192+ logger : new DebugLogger ( ) ,
193+ } ) ;
194+
195+ console . log ( '\n📡 Connecting with telemetry enabled...\n' ) ;
196+
197+ const connection = await client . connect ( {
198+ host,
199+ path,
200+ token,
201+ telemetryEnabled : true ,
202+ telemetryBatchSize : 1 , // Flush immediately for testing
203+ } ) ;
204+
205+ console . log ( '\n' + '=' . repeat ( 60 ) ) ;
206+ console . log ( 'EXECUTING INVALID QUERY (should fail)' ) ;
207+ console . log ( '=' . repeat ( 60 ) + '\n' ) ;
208+
209+ const session = await connection . openSession ( ) ;
210+
211+ try {
212+ // Execute an invalid query that will fail
213+ const queryOperation = await session . executeStatement ( 'SELECT * FROM nonexistent_table_12345' , {
214+ runAsync : false ,
215+ } ) ;
216+
217+ await queryOperation . fetchAll ( ) ;
218+ console . log ( '\n❌ Query should have failed but did not' ) ;
219+ } catch ( error : any ) {
220+ console . log ( '\n✅ Query failed as expected:' , error . message ) ;
221+ }
222+
223+ console . log ( '\n📝 Waiting for error telemetry flush...\n' ) ;
224+
225+ // Wait for telemetry to flush
226+ await new Promise < void > ( ( resolve ) => {
227+ setTimeout ( resolve , 3000 ) ;
228+ } ) ;
229+
230+ console . log ( '\n' + '=' . repeat ( 60 ) ) ;
231+ console . log ( 'CLEANING UP' ) ;
232+ console . log ( '=' . repeat ( 60 ) + '\n' ) ;
233+
234+ await session . close ( ) ;
235+ await connection . close ( ) ;
236+
237+ // Wait for final flush
238+ await new Promise < void > ( ( resolve ) => {
239+ setTimeout ( resolve , 2000 ) ;
240+ } ) ;
241+
242+ console . log ( '\n' + '=' . repeat ( 60 ) ) ;
243+ console . log ( 'TEST COMPLETE' ) ;
244+ console . log ( '=' . repeat ( 60 ) ) ;
245+ console . log ( '\nCheck the logs above for error telemetry payload' ) ;
246+ console . log ( 'Should see error_info with:' ) ;
247+ console . log ( ' - error_name' ) ;
248+ console . log ( ' - stack_trace\n' ) ;
249+
250+ // Restore fetch stub
251+ if ( fetchStub ) {
252+ fetchStub . restore ( ) ;
253+ }
254+ } ) ;
145255} ) ;
0 commit comments