repl: Log Jupyter kernel process stderr and stdout (#15391)

Kyle Kelley created

Super simple piping of logs from the Jupyter kernels to the Zed logs.

Release Notes:

- Added logging of stderr from Jupyter kernels to the Zed logs

Change summary

crates/repl/src/kernels.rs |  4 ++--
crates/repl/src/session.rs | 31 ++++++++++++++++++++++++++++++-
2 files changed, 32 insertions(+), 3 deletions(-)

Detailed changes

crates/repl/src/kernels.rs 🔗

@@ -222,8 +222,8 @@ impl RunningKernel {
 
             let process = cmd
                 .current_dir(&working_directory)
-                // .stdout(Stdio::null())
-                // .stderr(Stdio::null())
+                .stdout(std::process::Stdio::piped())
+                .stderr(std::process::Stdio::piped())
                 .kill_on_drop(true)
                 .spawn()
                 .context("failed to start the kernel process")?;

crates/repl/src/session.rs 🔗

@@ -14,7 +14,8 @@ use editor::{
     scroll::Autoscroll,
     Anchor, AnchorRangeExt as _, Editor, MultiBuffer, ToPoint,
 };
-use futures::{FutureExt as _, StreamExt as _};
+use futures::io::BufReader;
+use futures::{AsyncBufReadExt as _, FutureExt as _, StreamExt as _};
 use gpui::{
     div, prelude::*, EntityId, EventEmitter, Model, Render, Subscription, Task, View, ViewContext,
     WeakView,
@@ -242,6 +243,34 @@ impl Session {
                         this.update(&mut cx, |session, cx| {
                             // At this point we can create a new kind of kernel that has the process and our long running background tasks
 
+                            let stderr = kernel.process.stderr.take();
+
+                            cx.spawn(|_session, mut _cx| async move {
+                                if let None = stderr {
+                                    return;
+                                }
+                                let reader = BufReader::new(stderr.unwrap());
+                                let mut lines = reader.lines();
+                                while let Some(Ok(line)) = lines.next().await {
+                                    log::error!("kernel: {}", line);
+                                }
+                            })
+                            .detach();
+
+                            let stdout = kernel.process.stderr.take();
+
+                            cx.spawn(|_session, mut _cx| async move {
+                                if let None = stdout {
+                                    return;
+                                }
+                                let reader = BufReader::new(stdout.unwrap());
+                                let mut lines = reader.lines();
+                                while let Some(Ok(line)) = lines.next().await {
+                                    log::info!("kernel: {}", line);
+                                }
+                            })
+                            .detach();
+
                             let status = kernel.process.status();
                             session.kernel(Kernel::RunningKernel(kernel), cx);