From 2c9a1cb3dd941b3f2f608a0633f620478bce0c68 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 29 May 2019 15:42:14 +0300 Subject: add latest requests to status page --- crates/ra_lsp_server/src/main_loop.rs | 38 +++++++++++++++++++------- crates/ra_lsp_server/src/main_loop/handlers.rs | 12 ++++++-- crates/ra_lsp_server/src/server_world.rs | 29 ++++++++++++++++++++ 3 files changed, 67 insertions(+), 12 deletions(-) (limited to 'crates') diff --git a/crates/ra_lsp_server/src/main_loop.rs b/crates/ra_lsp_server/src/main_loop.rs index c3580ab67..e65bb0972 100644 --- a/crates/ra_lsp_server/src/main_loop.rs +++ b/crates/ra_lsp_server/src/main_loop.rs @@ -20,7 +20,7 @@ use crate::{ main_loop::subscriptions::Subscriptions, project_model::workspace_loader, req, - server_world::{ServerWorld, ServerWorldState}, + server_world::{ServerWorld, ServerWorldState, CompletedRequest}, Result, InitializationOptions, }; @@ -45,6 +45,17 @@ enum Task { Notify(RawNotification), } +struct PendingRequest { + received: Instant, + method: String, +} + +impl From<(u64, PendingRequest)> for CompletedRequest { + fn from((id, pending): (u64, PendingRequest)) -> CompletedRequest { + CompletedRequest { id, method: pending.method, duration: pending.received.elapsed() } + } +} + const THREADPOOL_SIZE: usize = 8; pub fn main_loop( @@ -97,7 +108,9 @@ pub fn main_loop( ); log::info!("waiting for tasks to finish..."); - task_receiver.into_iter().for_each(|task| on_task(task, msg_sender, &mut pending_requests)); + task_receiver + .into_iter() + .for_each(|task| on_task(task, msg_sender, &mut pending_requests, &mut state)); log::info!("...tasks have finished"); log::info!("joining threadpool..."); drop(pool); @@ -159,7 +172,7 @@ fn main_loop_inner( task_sender: Sender, task_receiver: Receiver, state: &mut ServerWorldState, - pending_requests: &mut FxHashMap, + pending_requests: &mut FxHashMap, subs: &mut Subscriptions, ) -> Result<()> { // We try not to index more than THREADPOOL_SIZE - 3 libraries at the same @@ -195,7 +208,7 @@ fn main_loop_inner( let mut state_changed = false; match event { Event::Task(task) => { - on_task(task, msg_sender, pending_requests); + on_task(task, msg_sender, pending_requests, state); state.maybe_collect_garbage(); } Event::Vfs(task) => { @@ -292,12 +305,15 @@ fn main_loop_inner( fn on_task( task: Task, msg_sender: &Sender, - pending_requests: &mut FxHashMap, + pending_requests: &mut FxHashMap, + state: &mut ServerWorldState, ) { match task { Task::Respond(response) => { - if let Some(request_received) = pending_requests.remove(&response.id) { - log::info!("handled req#{} in {:?}", response.id, request_received.elapsed()); + if let Some(pending) = pending_requests.remove(&response.id) { + let completed = CompletedRequest::from((response.id, pending)); + log::info!("handled req#{} in {:?}", completed.id, completed.duration); + state.complete_request(completed); msg_sender.send(response.into()).unwrap(); } } @@ -309,12 +325,13 @@ fn on_task( fn on_request( world: &mut ServerWorldState, - pending_requests: &mut FxHashMap, + pending_requests: &mut FxHashMap, pool: &ThreadPool, sender: &Sender, request_received: Instant, req: RawRequest, ) -> Result> { + let method = req.method.clone(); let mut pool_dispatcher = PoolDispatcher { req: Some(req), res: None, pool, world, sender }; let req = pool_dispatcher .on::(handlers::handle_analyzer_status)? @@ -348,7 +365,8 @@ fn on_request( .finish(); match req { Ok(id) => { - let prev = pending_requests.insert(id, request_received); + let prev = + pending_requests.insert(id, PendingRequest { method, received: request_received }); assert!(prev.is_none(), "duplicate request: {}", id); Ok(None) } @@ -359,7 +377,7 @@ fn on_request( fn on_notification( msg_sender: &Sender, state: &mut ServerWorldState, - pending_requests: &mut FxHashMap, + pending_requests: &mut FxHashMap, subs: &mut Subscriptions, not: RawNotification, ) -> Result<()> { diff --git a/crates/ra_lsp_server/src/main_loop/handlers.rs b/crates/ra_lsp_server/src/main_loop/handlers.rs index e36db12b3..dc817f2d9 100644 --- a/crates/ra_lsp_server/src/main_loop/handlers.rs +++ b/crates/ra_lsp_server/src/main_loop/handlers.rs @@ -1,3 +1,5 @@ +use std::{io::Write as _, fmt::Write as _}; + use gen_lsp_server::ErrorCode; use lsp_types::{ CodeActionResponse, CodeLens, Command, Diagnostic, DiagnosticSeverity, CodeAction, @@ -16,7 +18,6 @@ use ra_prof::profile; use rustc_hash::FxHashMap; use serde::{Serialize, Deserialize}; use serde_json::to_value; -use std::io::Write; use url_serde::Ser; use crate::{ @@ -28,7 +29,14 @@ use crate::{ }; pub fn handle_analyzer_status(world: ServerWorld, _: ()) -> Result { - Ok(world.status()) + let mut buf = world.status(); + writeln!(buf, "\n\nrequests:").unwrap(); + let requests = world.latest_completed_requests.read(); + for (idx, r) in requests.iter().enumerate() { + let current = if idx == world.request_idx { "*" } else { " " }; + writeln!(buf, "{:4}{}{:<36}: {:?}", r.id, current, r.method, r.duration).unwrap(); + } + Ok(buf) } pub fn handle_syntax_tree(world: ServerWorld, params: req::SyntaxTreeParams) -> Result { diff --git a/crates/ra_lsp_server/src/server_world.rs b/crates/ra_lsp_server/src/server_world.rs index b2808b817..b63927a4f 100644 --- a/crates/ra_lsp_server/src/server_world.rs +++ b/crates/ra_lsp_server/src/server_world.rs @@ -1,6 +1,7 @@ use std::{ path::{Path, PathBuf}, sync::Arc, + time::Duration, }; use lsp_types::Url; @@ -28,12 +29,26 @@ pub struct ServerWorldState { pub workspaces: Arc>, pub analysis_host: AnalysisHost, pub vfs: Arc>, + // hand-rolling VecDeque here to print things in a nicer way + pub latest_completed_requests: Arc>, + pub request_idx: usize, } +const N_COMPLETED_REQUESTS: usize = 10; + pub struct ServerWorld { pub workspaces: Arc>, pub analysis: Analysis, pub vfs: Arc>, + pub latest_completed_requests: Arc>, + pub request_idx: usize, +} + +#[derive(Debug, Default)] +pub struct CompletedRequest { + pub id: u64, + pub method: String, + pub duration: Duration, } impl ServerWorldState { @@ -73,6 +88,8 @@ impl ServerWorldState { workspaces: Arc::new(workspaces), analysis_host, vfs: Arc::new(RwLock::new(vfs)), + latest_completed_requests: Default::default(), + request_idx: 0, } } @@ -137,6 +154,8 @@ impl ServerWorldState { workspaces: Arc::clone(&self.workspaces), analysis: self.analysis_host.analysis(), vfs: Arc::clone(&self.vfs), + latest_completed_requests: Arc::clone(&self.latest_completed_requests), + request_idx: self.request_idx.checked_sub(1).unwrap_or(N_COMPLETED_REQUESTS - 1), } } @@ -147,6 +166,16 @@ impl ServerWorldState { pub fn collect_garbage(&mut self) { self.analysis_host.collect_garbage() } + + pub fn complete_request(&mut self, request: CompletedRequest) { + // special case: don't track status request itself + if request.method == "rust-analyzer/analyzerStatus" { + return; + } + let idx = self.request_idx; + self.latest_completed_requests.write()[idx] = request; + self.request_idx = (idx + 1) % N_COMPLETED_REQUESTS; + } } impl ServerWorld { -- cgit v1.2.3