debugger: Improve logging of debug sessions (#32718)

This PR fixes a common issue where a debug session won't start up and
user's weren't able to get any logs from the debug session. We now do
these three things

1. We know store a history of debug sessions
2. We added a new option to only look at the initialization sequence 
3. We default to selecting a session in dap log view in stead of none

Release Notes:

- debugger: Add history to debug session logging

---------

Co-authored-by: Cole Miller <cole@zed.dev>
Co-authored-by: Remco Smits <djsmits12@gmail.com>
This commit is contained in:
Anthony Eid 2025-06-13 16:56:23 -04:00 committed by GitHub
parent 4425d58d72
commit 6650be8e0f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 347 additions and 165 deletions

View file

@ -218,7 +218,7 @@ impl DebugAdapterClient {
pub fn add_log_handler<F>(&self, f: F, kind: LogKind)
where
F: 'static + Send + FnMut(IoKind, &str),
F: 'static + Send + FnMut(IoKind, Option<&str>, &str),
{
self.transport_delegate.add_log_handler(f, kind);
}

View file

@ -25,7 +25,9 @@ use util::ConnectionResult;
use crate::{adapters::DebugAdapterBinary, debugger_settings::DebuggerSettings};
pub type IoHandler = Box<dyn Send + FnMut(IoKind, &str)>;
pub(crate) type IoMessage = str;
pub(crate) type Command = str;
pub type IoHandler = Box<dyn Send + FnMut(IoKind, Option<&Command>, &IoMessage)>;
#[derive(PartialEq, Eq, Clone, Copy)]
pub enum LogKind {
@ -296,7 +298,7 @@ impl TransportDelegate {
if let Some(log_handlers) = log_handlers.as_ref() {
for (kind, handler) in log_handlers.lock().iter_mut() {
if matches!(kind, LogKind::Adapter) {
handler(IoKind::StdOut, line.as_str());
handler(IoKind::StdOut, None, line.as_str());
}
}
}
@ -330,6 +332,12 @@ impl TransportDelegate {
}
}
let command = match &message {
Message::Request(request) => Some(request.command.as_str()),
Message::Response(response) => Some(response.command.as_str()),
_ => None,
};
let message = match serde_json::to_string(&message) {
Ok(message) => message,
Err(e) => break Err(e.into()),
@ -338,7 +346,7 @@ impl TransportDelegate {
if let Some(log_handlers) = log_handlers.as_ref() {
for (kind, log_handler) in log_handlers.lock().iter_mut() {
if matches!(kind, LogKind::Rpc) {
log_handler(IoKind::StdIn, &message);
log_handler(IoKind::StdIn, command, &message);
}
}
}
@ -423,7 +431,7 @@ impl TransportDelegate {
Ok(_) => {
for (kind, log_handler) in log_handlers.lock().iter_mut() {
if matches!(kind, LogKind::Adapter) {
log_handler(IoKind::StdErr, buffer.as_str());
log_handler(IoKind::StdErr, None, buffer.as_str());
}
}
@ -512,17 +520,24 @@ impl TransportDelegate {
Err(e) => return ConnectionResult::Result(Err(e)),
};
let message =
serde_json::from_str::<Message>(message_str).context("deserializing server message");
if let Some(log_handlers) = log_handlers {
let command = match &message {
Ok(Message::Request(request)) => Some(request.command.as_str()),
Ok(Message::Response(response)) => Some(response.command.as_str()),
_ => None,
};
for (kind, log_handler) in log_handlers.lock().iter_mut() {
if matches!(kind, LogKind::Rpc) {
log_handler(IoKind::StdOut, message_str);
log_handler(IoKind::StdOut, command, message_str);
}
}
}
ConnectionResult::Result(
serde_json::from_str::<Message>(message_str).context("deserializing server message"),
)
ConnectionResult::Result(message)
}
pub async fn shutdown(&self) -> Result<()> {
@ -558,7 +573,7 @@ impl TransportDelegate {
pub fn add_log_handler<F>(&self, f: F, kind: LogKind)
where
F: 'static + Send + FnMut(IoKind, &str),
F: 'static + Send + FnMut(IoKind, Option<&Command>, &IoMessage),
{
let mut log_handlers = self.log_handlers.lock();
log_handlers.push((kind, Box::new(f)));