16
16
pub mod config;
17
17
pub mod router;
18
18
19
- use chromiumoxide:: { browser:: Browser , cdp:: browser_protocol:: page:: PrintToPdfParams , Page } ;
19
+ use chromiumoxide:: {
20
+ browser:: Browser ,
21
+ cdp:: browser_protocol:: page:: { CaptureScreenshotParamsBuilder , PrintToPdfParams } ,
22
+ Page ,
23
+ } ;
20
24
use config:: { get_chrome_launch_options, CONFIG } ;
21
25
use futures:: StreamExt ;
22
26
use lettre:: {
@@ -165,9 +169,13 @@ pub async fn generate_report(
165
169
}
166
170
Err ( e) => {
167
171
let page_url = page. url ( ) . await ;
172
+ // Take a screenshot before killing the browser to help debug login issues
173
+ take_screenshot ( & page, org_id, dashboard_id) . await ?;
174
+ log:: info!( "killing browser" ) ;
168
175
browser. close ( ) . await ?;
169
176
browser. wait ( ) . await ?;
170
177
handle. await ?;
178
+ browser. kill ( ) . await ;
171
179
let err_msg = format ! (
172
180
"Error finding email input box: current url: {:#?} error: {e}" ,
173
181
page_url
@@ -189,9 +197,12 @@ pub async fn generate_report(
189
197
}
190
198
Err ( e) => {
191
199
let page_url = page. url ( ) . await ;
200
+ take_screenshot ( & page, org_id, dashboard_id) . await ?;
201
+ log:: info!( "killing browser" ) ;
192
202
browser. close ( ) . await ?;
193
203
browser. wait ( ) . await ?;
194
204
handle. await ?;
205
+ browser. kill ( ) . await ;
195
206
let err_msg = format ! (
196
207
"Error finding password input box: current url: {:#?} error: {e}" ,
197
208
page_url
@@ -285,9 +296,13 @@ pub async fn generate_report(
285
296
. await
286
297
{
287
298
let page_url = page. url ( ) . await ;
299
+ // Take a screenshot before killing the browser to help debug issues
300
+ take_screenshot ( & page, org_id, dashboard_id) . await ?;
301
+ log:: info!( "killing browser" ) ;
288
302
browser. close ( ) . await ?;
289
303
browser. wait ( ) . await ?;
290
304
handle. await ?;
305
+ browser. kill ( ) . await ;
291
306
log:: error!(
292
307
"Error navigating to organization {org_id}: current uri: {:#?} error: {e}" ,
293
308
page_url
@@ -302,9 +317,12 @@ pub async fn generate_report(
302
317
303
318
if let Err ( e) = page. goto ( & dashb_url) . await {
304
319
let page_url = page. url ( ) . await ;
320
+ take_screenshot ( & page, org_id, dashboard_id) . await ?;
321
+ log:: info!( "killing browser" ) ;
305
322
browser. close ( ) . await ?;
306
323
browser. wait ( ) . await ?;
307
324
handle. await ?;
325
+ browser. kill ( ) . await ;
308
326
log:: error!(
309
327
"Error navigating to dashboard url {dashb_url}: current uri: {:#?} error: {e}" ,
310
328
page_url
@@ -335,19 +353,27 @@ pub async fn generate_report(
335
353
336
354
if let Err ( e) = page. find_element ( "main" ) . await {
337
355
let page_url = page. url ( ) . await ;
356
+ take_screenshot ( & page, org_id, dashboard_id) . await ?;
357
+ // Take a screenshot before killing the browser to help debug login issues
358
+ log:: info!( "killing browser" ) ;
338
359
browser. close ( ) . await ?;
339
360
browser. wait ( ) . await ?;
340
361
handle. await ?;
362
+ browser. kill ( ) . await ;
341
363
return Err ( anyhow:: anyhow!(
342
364
"[REPORT] main html element not rendered yet for dashboard {dashboard_id}; most likely login failed: current url: {:#?} error: {e}" ,
343
365
page_url
344
366
) ) ;
345
367
}
346
368
if let Err ( e) = page. find_element ( "div.displayDiv" ) . await {
347
369
let page_url = page. url ( ) . await ;
370
+ // Take a screenshot before killing the browser to help debug login issues
371
+ take_screenshot ( & page, org_id, dashboard_id) . await ?;
372
+ log:: info!( "killing browser" ) ;
348
373
browser. close ( ) . await ?;
349
374
browser. wait ( ) . await ?;
350
375
handle. await ?;
376
+ browser. kill ( ) . await ;
351
377
return Err ( anyhow:: anyhow!(
352
378
"[REPORT] div.displayDiv element not rendered yet for dashboard {dashboard_id}: current url: {:#?} error: {e}" ,
353
379
page_url
@@ -373,6 +399,7 @@ pub async fn generate_report(
373
399
browser. close ( ) . await ?;
374
400
browser. wait ( ) . await ?;
375
401
handle. await ?;
402
+ browser. kill ( ) . await ;
376
403
log:: debug!( "done with headless browser" ) ;
377
404
Ok ( ( pdf_data, email_dashb_url) )
378
405
}
@@ -430,6 +457,22 @@ async fn send_email(
430
457
}
431
458
}
432
459
460
+ async fn take_screenshot (
461
+ page : & Page ,
462
+ org_id : & str ,
463
+ dashboard_name : & str ,
464
+ ) -> Result < ( ) , anyhow:: Error > {
465
+ let timestamp = chrono:: Utc :: now ( ) . timestamp ( ) ;
466
+ let screenshot_params = CaptureScreenshotParamsBuilder :: default ( ) ;
467
+ let screenshot = page. screenshot ( screenshot_params. build ( ) ) . await ?;
468
+ tokio:: fs:: write (
469
+ format ! ( "screenshot_{}_{}_{}.png" , org_id, dashboard_name, timestamp) ,
470
+ & screenshot,
471
+ )
472
+ . await ?;
473
+ Ok ( ( ) )
474
+ }
475
+
433
476
pub async fn wait_for_panel_data_load ( page : & Page ) -> Result < Duration , anyhow:: Error > {
434
477
let start = std:: time:: Instant :: now ( ) ;
435
478
let timeout = std:: time:: Duration :: from_secs ( CONFIG . chrome . chrome_sleep_secs . into ( ) ) ;
@@ -456,6 +499,12 @@ pub async fn wait_for_panel_data_load(page: &Page) -> Result<Duration, anyhow::E
456
499
fn sanitize_filename ( filename : & str ) -> String {
457
500
filename
458
501
. chars ( )
459
- . map ( |c| if c. is_ascii_alphanumeric ( ) || c == '-' || c == '_' || c == ' ' { c } else { '_' } )
502
+ . map ( |c| {
503
+ if c. is_ascii_alphanumeric ( ) || c == '-' || c == '_' || c == ' ' {
504
+ c
505
+ } else {
506
+ '_'
507
+ }
508
+ } )
460
509
. collect ( )
461
- }
510
+ }
0 commit comments