glass/browser/session/
diagnostic.rs1use super::*;
7
8impl BrowserSession {
9 pub async fn diagnostics(&self, duration: Duration) -> BrowserResult<DiagnosticReport> {
11 if duration.is_zero() || duration > MAX_DIAGNOSTIC_DURATION {
12 return Err("diagnostic duration must be between 1 ms and 30 seconds".into());
13 }
14 self.cdp
15 .with_current_route(async {
16 let (target_id, frame_id) = self.route_identity().await?;
17 let route_session_id = self.cdp.current_session_id();
18 let mut events = self.cdp.subscribe_events_with_params();
19 let mut guard = DiagnosticDomainGuard::acquire(
20 self.cdp.clone(),
21 Arc::clone(&self.network_wait_leases),
22 Arc::clone(&self.diagnostic_leases),
23 )
24 .await?;
25 let started = tokio::time::Instant::now();
26 let deadline = started + duration;
27 let mut console = Vec::new();
28 let mut network = Vec::new();
29 let mut request_indexes = HashMap::new();
30 let mut dropped_events = 0_u64;
31 loop {
32 tokio::select! {
33 _ = tokio::time::sleep_until(deadline) => break,
34 event = events.recv() => match event {
35 Ok(event) if event.session_id == route_session_id => collect_diagnostic_event(
36 &event,
37 &mut console,
38 &mut network,
39 &mut request_indexes,
40 &mut dropped_events,
41 ),
42 Ok(_) => {}
43 Err(tokio::sync::broadcast::error::RecvError::Lagged(count)) => {
44 dropped_events = dropped_events.saturating_add(count);
45 }
46 Err(tokio::sync::broadcast::error::RecvError::Closed) => break,
47 }
48 }
49 }
50 guard.disable().await?;
51 Ok(DiagnosticReport {
52 target_id,
53 frame_id,
54 duration_ms: started.elapsed().as_millis() as u64,
55 console,
56 network,
57 dropped_events,
58 })
59 })
60 .await
61 }
62}