Skip to content

Commit 0a2553a

Browse files
authored
chore(core): add debug mode for tui (#31115)
<!-- Please make sure you have read the submission guidelines before posting an PR --> <!-- https://github.com/nrwl/nx/blob/master/CONTRIBUTING.md#-submitting-a-pr --> <!-- Please make sure that your commit message follows our format --> <!-- Example: `fix(nx): must begin with lowercase` --> <!-- If this is a particularly complex change or feature addition, you can request a dedicated Nx release for this pull request branch. Mention someone from the Nx team or the `@nrwl/nx-pipelines-reviewers` and they will confirm if the PR warrants its own release for testing purposes, and generate it for you if appropriate. --> ## Current Behavior <!-- This is the behavior we have today --> Debugging the TUI is a chore ## Expected Behavior <!-- This is the behavior we should expect with the changes in this PR --> Debugging the TUI is a little better.. ## Related Issue(s) <!-- Please link the issue being fixed so it gets closed when this is merged. --> Fixes #
1 parent cdba055 commit 0a2553a

File tree

12 files changed

+169
-18
lines changed

12 files changed

+169
-18
lines changed

Cargo.lock

Lines changed: 48 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/nx/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ tracing-subscriber = { version = "0.3.17", features = ["env-filter"] }
5454
tokio = { version = "1.32.0", features = ['sync','macros','io-util','rt','time'] }
5555
tokio-util = "0.7.9"
5656
tracing-appender = "0.2"
57+
tui-logger = { version = "0.17.2", features = ["tracing-support"] }
5758
tui-term = { git = "https://github.com/JamesHenry/tui-term", rev = "88e3b61425c97220c528ef76c188df10032a75dd" }
5859
walkdir = '2.3.3'
5960
xxhash-rust = { version = '0.8.5', features = ['xxh3', 'xxh64'] }

packages/nx/src/native/index.d.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,10 @@ export interface InputsInput {
237237

238238
export const IS_WASM: boolean
239239

240+
export declare export declare function logError(message: string): void
241+
242+
export declare export declare function logInfo(message: string): void
243+
240244
/** Stripped version of the NxJson interface for use in rust */
241245
export interface NxJson {
242246
namedInputs?: Record<string, Array<JsInputs>>
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
use crate::native::logger::enable_logger;
2+
use tracing::{error, info};
3+
4+
#[napi]
5+
pub fn log_info(message: String) {
6+
enable_logger();
7+
info!(message);
8+
}
9+
10+
#[napi]
11+
pub fn log_error(message: String) {
12+
enable_logger();
13+
error!(message);
14+
}

packages/nx/src/native/logger/mod.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
pub mod console;
2+
13
use colored::Colorize;
24
use std::env;
35
use std::fs::create_dir_all;
@@ -8,6 +10,7 @@ use tracing_subscriber::fmt::{format, FmtContext, FormatEvent, FormatFields, For
810
use tracing_subscriber::prelude::*;
911
use tracing_subscriber::registry::LookupSpan;
1012
use tracing_subscriber::{EnvFilter, Layer};
13+
use tui_logger::TuiTracingSubscriberLayer;
1114

1215
struct NxLogFormatter;
1316
impl<S, N> FormatEvent<S, N> for NxLogFormatter
@@ -103,7 +106,9 @@ pub(crate) fn enable_logger() {
103106
.unwrap_or_else(|_| EnvFilter::new("ERROR")),
104107
);
105108

106-
let registry = tracing_subscriber::registry().with(stdout_layer);
109+
let registry = tracing_subscriber::registry()
110+
.with(stdout_layer)
111+
.with(TuiTracingSubscriberLayer);
107112

108113
if env::var("NX_NATIVE_FILE_LOGGING").is_err() {
109114
// File logging is not enabled

packages/nx/src/native/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
pub mod cache;
22
pub mod glob;
33
pub mod hasher;
4-
mod logger;
4+
pub mod logger;
55
mod machine_id;
66
pub mod metadata;
77
pub mod plugins;

packages/nx/src/native/native-bindings.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,8 @@ module.exports.getTransformableOutputs = nativeBinding.getTransformableOutputs
388388
module.exports.hashArray = nativeBinding.hashArray
389389
module.exports.hashFile = nativeBinding.hashFile
390390
module.exports.IS_WASM = nativeBinding.IS_WASM
391+
module.exports.logError = nativeBinding.logError
392+
module.exports.logInfo = nativeBinding.logInfo
391393
module.exports.parseTaskStatus = nativeBinding.parseTaskStatus
392394
module.exports.remove = nativeBinding.remove
393395
module.exports.restoreTerminal = nativeBinding.restoreTerminal

packages/nx/src/native/tui/action.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,5 @@ pub enum Action {
3434
StartCommand(Option<u32>),
3535
StartTasks(Vec<Task>),
3636
EndTasks(Vec<TaskResult>),
37+
ToggleDebugMode,
3738
}

packages/nx/src/native/tui/app.rs

Lines changed: 65 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use crossterm::event::{KeyCode, KeyEvent, KeyModifiers, MouseEventKind};
33
use hashbrown::HashSet;
44
use napi::bindgen_prelude::External;
55
use napi::threadsafe_function::{ErrorStrategy, ThreadsafeFunction};
6-
use ratatui::layout::{Alignment, Rect, Size};
6+
use ratatui::layout::{Alignment, Position, Rect, Size};
77
use ratatui::style::Modifier;
88
use ratatui::style::Style;
99
use ratatui::text::{Line, Span};
@@ -14,6 +14,7 @@ use std::sync::{Arc, Mutex, RwLock};
1414
use tokio::sync::mpsc;
1515
use tokio::sync::mpsc::UnboundedSender;
1616
use tracing::{debug, trace};
17+
use tui_logger::{TuiLoggerSmartWidget, TuiLoggerWidget, TuiWidgetEvent, TuiWidgetState};
1718
use vt100_ctt::Parser;
1819

1920
use crate::native::tui::tui::Tui;
@@ -66,6 +67,8 @@ pub struct App {
6667
selection_manager: Arc<Mutex<TaskSelectionManager>>,
6768
pinned_tasks: Vec<String>,
6869
tasks: Vec<Task>,
70+
debug_mode: bool,
71+
debug_state: TuiWidgetState,
6972
}
7073

7174
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
@@ -131,6 +134,8 @@ impl App {
131134
pty_instances: HashMap::new(),
132135
selection_manager,
133136
tasks,
137+
debug_mode: false,
138+
debug_state: TuiWidgetState::default(),
134139
})
135140
}
136141

@@ -292,7 +297,7 @@ impl App {
292297
tui::Event::Render => action_tx.send(Action::Render)?,
293298
tui::Event::Resize(x, y) => action_tx.send(Action::Resize(x, y))?,
294299
tui::Event::Key(key) => {
295-
debug!("Handling Key Event: {:?}", key);
300+
trace!("Handling Key Event: {:?}", key);
296301

297302
// Record that the user has interacted with the app
298303
self.user_has_interacted = true;
@@ -324,6 +329,16 @@ impl App {
324329
};
325330
}
326331

332+
if matches!(key.code, KeyCode::F(12)) {
333+
self.dispatch_action(Action::ToggleDebugMode);
334+
return Ok(false);
335+
}
336+
337+
if self.debug_mode {
338+
self.handle_debug_event(key);
339+
return Ok(false);
340+
}
341+
327342
// Only handle '?' key if we're not in interactive mode and the countdown popup is not open
328343
if matches!(key.code, KeyCode::Char('?'))
329344
&& !self.is_interactive_mode()
@@ -729,7 +744,7 @@ impl App {
729744
action_tx: &UnboundedSender<Action>,
730745
) {
731746
if action != Action::Tick && action != Action::Render {
732-
debug!("{action:?}");
747+
trace!("{action:?}");
733748
}
734749
match &action {
735750
// Quit immediately
@@ -749,6 +764,10 @@ impl App {
749764
// Ensure the pty instances get resized appropriately (debounced)
750765
let _ = self.debounce_pty_resize();
751766
}
767+
Action::ToggleDebugMode => {
768+
self.debug_mode = !self.debug_mode;
769+
debug!("Debug mode: {}", self.debug_mode);
770+
}
752771
Action::Render => {
753772
tui.draw(|f| {
754773
let area = f.area();
@@ -764,6 +783,12 @@ impl App {
764783
let frame_area = self.frame_area.unwrap();
765784
let layout_areas = self.layout_areas.as_mut().unwrap();
766785

786+
if self.debug_mode {
787+
let debug_widget = TuiLoggerSmartWidget::default().state(&self.debug_state);
788+
f.render_widget(debug_widget, frame_area);
789+
return;
790+
}
791+
767792
// TODO: move this to the layout manager?
768793
// Check for minimum viable viewport size at the app level
769794
if frame_area.height < 10 || frame_area.width < 40 {
@@ -1444,4 +1469,41 @@ impl App {
14441469
self.focus = focus;
14451470
self.dispatch_action(Action::UpdateFocus(focus));
14461471
}
1472+
1473+
fn handle_debug_event(&mut self, key: KeyEvent) {
1474+
// https://docs.rs/tui-logger/latest/tui_logger/#smart-widget-key-commands
1475+
// | KEY | ACTION
1476+
// |----------|-----------------------------------------------------------|
1477+
// | h | Toggles target selector widget hidden/visible
1478+
// | f | Toggle focus on the selected target only
1479+
// | UP | Select previous target in target selector widget
1480+
// | DOWN | Select next target in target selector widget
1481+
// | LEFT | Reduce SHOWN (!) log messages by one level
1482+
// | RIGHT | Increase SHOWN (!) log messages by one level
1483+
// | - | Reduce CAPTURED (!) log messages by one level
1484+
// | + | Increase CAPTURED (!) log messages by one level
1485+
// | PAGEUP | Enter Page Mode and scroll approx. half page up in log history.
1486+
// | PAGEDOWN | Only in page mode: scroll 10 events down in log history.
1487+
// | ESCAPE | Exit page mode and go back to scrolling mode
1488+
// | SPACE | Toggles hiding of targets, which have logfilter set to off
1489+
let debug_widget_event = match key.code {
1490+
KeyCode::Char(' ') => Some(TuiWidgetEvent::SpaceKey),
1491+
KeyCode::Esc => Some(TuiWidgetEvent::EscapeKey),
1492+
KeyCode::PageUp => Some(TuiWidgetEvent::PrevPageKey),
1493+
KeyCode::PageDown => Some(TuiWidgetEvent::NextPageKey),
1494+
KeyCode::Up => Some(TuiWidgetEvent::UpKey),
1495+
KeyCode::Down => Some(TuiWidgetEvent::DownKey),
1496+
KeyCode::Left => Some(TuiWidgetEvent::LeftKey),
1497+
KeyCode::Right => Some(TuiWidgetEvent::RightKey),
1498+
KeyCode::Char('+') => Some(TuiWidgetEvent::PlusKey),
1499+
KeyCode::Char('-') => Some(TuiWidgetEvent::MinusKey),
1500+
KeyCode::Char('h') => Some(TuiWidgetEvent::HideKey),
1501+
KeyCode::Char('f') => Some(TuiWidgetEvent::FocusKey),
1502+
_ => None,
1503+
};
1504+
1505+
if let Some(event) = debug_widget_event {
1506+
self.debug_state.transition(event);
1507+
}
1508+
}
14471509
}

packages/nx/src/native/tui/lifecycle.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,7 @@ impl AppLifeCycle {
162162
done_callback: ThreadsafeFunction<(), ErrorStrategy::Fatal>,
163163
) -> napi::Result<()> {
164164
enable_logger();
165+
tui_logger::init_logger(tui_logger::LevelFilter::Debug).unwrap();
165166
debug!("Initializing Terminal UI");
166167

167168
let app_mutex = self.app.clone();

0 commit comments

Comments
 (0)