Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,14 @@ license = "MIT"
version = "25.4.1"
edition = "2021"

[lib]
name = "chdig"
path = "src/lib.rs"

[[bin]]
name = "chdig"
path = "src/main.rs"

[features]
default = ["tls"]
tls = ["clickhouse-rs/tls-rustls"]
Expand Down
78 changes: 78 additions & 0 deletions src/chdig.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
use anyhow::Result;
use backtrace::Backtrace;
use flexi_logger::{LogSpecification, Logger};
use std::panic::{self, PanicHookInfo};
use std::sync::Arc;

use crate::{
interpreter::{options, ClickHouse, Context, ContextArc},
view::Navigation,
};

fn panic_hook(info: &PanicHookInfo<'_>) {
let location = info.location().unwrap();

let msg = match info.payload().downcast_ref::<&'static str>() {
Some(s) => *s,
None => match info.payload().downcast_ref::<String>() {
Some(s) => &s[..],
None => "Box<Any>",
},
};

// NOTE: we need to add \r since the terminal is in raw mode.
// (another option is to restore the terminal state with termios)
let stacktrace: String = format!("{:?}", Backtrace::new()).replace('\n', "\n\r");

print!(
"\n\rthread '<unnamed>' panicked at '{}', {}\n\r{}",
msg, location, stacktrace
);
}

pub async fn chdig_main() -> Result<()> {
let options = options::parse()?;

// Initialize it before any backends (otherwise backend will prepare terminal for TUI app, and
// panic hook will clear the screen).
let clickhouse = Arc::new(ClickHouse::new(options.clickhouse.clone()).await?);

panic::set_hook(Box::new(|info| {
panic_hook(info);
}));

#[cfg(not(target_family = "windows"))]
let backend = cursive::backends::termion::Backend::init()?;
#[cfg(target_family = "windows")]
let backend = cursive::backends::crossterm::Backend::init()?;

let buffered_backend = Box::new(cursive_buffered_backend::BufferedBackend::new(backend));
let mut siv = cursive::CursiveRunner::new(cursive::Cursive::new(), buffered_backend);

// Override with RUST_LOG
//
// NOTE: hyper also has trace_span() which will not be overwritten
//
// FIXME: should be initialize before options, but options prints completion that should be
// done before terminal switched to raw mode.
let logger = Logger::try_with_env_or_str(
"trace,cursive=info,clickhouse_rs=info,skim=info,tuikit=info,hyper=info,rustls=info",
)?
.log_to_writer(cursive_flexi_logger_view::cursive_flexi_logger(&siv))
.format(flexi_logger::colored_with_thread)
.start()?;

// FIXME: should be initialized before cursive, otherwise on error it clears the terminal.
let context: ContextArc = Context::new(options, clickhouse, siv.cb_sink().clone()).await?;

siv.chdig(context.clone());

log::info!("chdig started");
siv.run();

// Suppress error from the cursive_flexi_logger_view - "cursive callback sink is closed!"
// Note, cursive_flexi_logger_view does not implements shutdown() so it will not help.
logger.set_new_spec(LogSpecification::parse("none").unwrap());

return Ok(());
}
6 changes: 3 additions & 3 deletions src/interpreter/background_runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ use std::time::Duration;
/// It is OK to suppress unused warning for this code, since it join the thread in drop()
/// correctly, example:
///
/// ```rust
/// pub struct Context {
/// ``rust
/// pub struct SomeView {
/// #[allow(unused)]
/// bg_runner: BackgroundRunner,
/// }
/// ```
/// ``
///
pub struct BackgroundRunner {
interval: Duration,
Expand Down
2 changes: 1 addition & 1 deletion src/interpreter/context.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::actions::ActionDescription;
use crate::interpreter::{options::ChDigOptions, ClickHouse, Worker};
use anyhow::Result;
use chdig::ActionDescription;
use chrono::Duration;
use cursive::{event::Event, event::EventResult, views::Dialog, views::OnEventView, Cursive, View};
use std::sync::{atomic, Arc, Condvar, Mutex};
Expand Down
2 changes: 1 addition & 1 deletion src/interpreter/worker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ use crate::{
common::Stopwatch,
interpreter::clickhouse::{Columns, TraceType},
interpreter::{flamegraph, ContextArc},
utils::{highlight_sql, open_graph_in_browser},
view::{self, Navigation},
};
use anyhow::{anyhow, Result};
use chdig::{highlight_sql, open_graph_in_browser};
use chrono::{DateTime, Local};
// FIXME: "leaky abstractions"
use clickhouse_rs::errors::Error as ClickHouseError;
Expand Down
15 changes: 5 additions & 10 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,8 @@
mod actions;
mod common;
mod interpreter;
mod utils;
mod view;

// utils
pub use utils::edit_query;
#[cfg(not(target_family = "windows"))]
pub use utils::fuzzy_actions;
pub use utils::get_query;
pub use utils::highlight_sql;
pub use utils::open_graph_in_browser;

// actions
pub use actions::ActionDescription;
mod chdig;
pub use chdig::chdig_main;
80 changes: 2 additions & 78 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,83 +1,7 @@
use anyhow::Result;
use backtrace::Backtrace;
use flexi_logger::{LogSpecification, Logger};
use std::panic::{self, PanicHookInfo};
use std::sync::Arc;

mod common;
mod interpreter;
mod view;

use crate::{
interpreter::{options, ClickHouse, Context, ContextArc},
view::Navigation,
};

fn panic_hook(info: &PanicHookInfo<'_>) {
let location = info.location().unwrap();

let msg = match info.payload().downcast_ref::<&'static str>() {
Some(s) => *s,
None => match info.payload().downcast_ref::<String>() {
Some(s) => &s[..],
None => "Box<Any>",
},
};

// NOTE: we need to add \r since the terminal is in raw mode.
// (another option is to restore the terminal state with termios)
let stacktrace: String = format!("{:?}", Backtrace::new()).replace('\n', "\n\r");

print!(
"\n\rthread '<unnamed>' panicked at '{}', {}\n\r{}",
msg, location, stacktrace
);
}
use chdig::chdig_main;

#[tokio::main(flavor = "current_thread")]
async fn main() -> Result<()> {
let options = options::parse()?;

// Initialize it before any backends (otherwise backend will prepare terminal for TUI app, and
// panic hook will clear the screen).
let clickhouse = Arc::new(ClickHouse::new(options.clickhouse.clone()).await?);

panic::set_hook(Box::new(|info| {
panic_hook(info);
}));

#[cfg(not(target_family = "windows"))]
let backend = cursive::backends::termion::Backend::init()?;
#[cfg(target_family = "windows")]
let backend = cursive::backends::crossterm::Backend::init()?;

let buffered_backend = Box::new(cursive_buffered_backend::BufferedBackend::new(backend));
let mut siv = cursive::CursiveRunner::new(cursive::Cursive::new(), buffered_backend);

// Override with RUST_LOG
//
// NOTE: hyper also has trace_span() which will not be overwritten
//
// FIXME: should be initialize before options, but options prints completion that should be
// done before terminal switched to raw mode.
let logger = Logger::try_with_env_or_str(
"trace,cursive=info,clickhouse_rs=info,skim=info,tuikit=info,hyper=info,rustls=info",
)?
.log_to_writer(cursive_flexi_logger_view::cursive_flexi_logger(&siv))
.format(flexi_logger::colored_with_thread)
.start()?;

// FIXME: should be initialized before cursive, otherwise on error it clears the terminal.
let context: ContextArc = Context::new(options, clickhouse, siv.cb_sink().clone()).await?;

siv.chdig(context.clone());

log::info!("chdig started");
siv.run();

// Suppress error from the cursive_flexi_logger_view - "cursive callback sink is closed!"
// Note, cursive_flexi_logger_view does not implements shutdown() so it will not help.
logger.set_new_spec(LogSpecification::parse("none").unwrap());

return Ok(());
return chdig_main().await;
}
2 changes: 1 addition & 1 deletion src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use tempfile::Builder;
use urlencoding::encode;

#[cfg(not(target_family = "windows"))]
use {crate::ActionDescription, skim::prelude::*};
use {crate::actions::ActionDescription, skim::prelude::*};

#[cfg(not(target_family = "windows"))]
impl SkimItem for ActionDescription {
Expand Down
4 changes: 2 additions & 2 deletions src/view/navigation.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#[cfg(not(target_family = "windows"))]
use crate::utils::fuzzy_actions;
use crate::{
interpreter::{
clickhouse::TraceType,
Expand All @@ -7,8 +9,6 @@ use crate::{
view::{self, TextLogView},
};
use anyhow::Result;
#[cfg(not(target_family = "windows"))]
use chdig::fuzzy_actions;
use cursive::{
event::{Event, EventResult, Key},
theme::{BaseColor, Color, ColorStyle, Effect, PaletteColor, Style, Theme},
Expand Down
14 changes: 8 additions & 6 deletions src/view/processes_view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,15 @@ use cursive::{
};
use size::{Base, SizeFormatter, Style};

use crate::interpreter::{
clickhouse::Columns, clickhouse::TraceType, options::ViewOptions, BackgroundRunner, ContextArc,
QueryProcess, WorkerEvent,
use crate::{
interpreter::{
clickhouse::Columns, clickhouse::TraceType, options::ViewOptions, BackgroundRunner,
ContextArc, QueryProcess, WorkerEvent,
},
utils::{edit_query, get_query},
view::{ExtTableView, ProcessView, QueryResultView, TableViewItem, TextLogView},
wrap_impl_no_move,
};
use crate::view::{ExtTableView, ProcessView, QueryResultView, TableViewItem, TextLogView};
use crate::wrap_impl_no_move;
use chdig::{edit_query, get_query};

// Analog of mapFromArrays() in ClickHouse
fn map_from_arrays<K, V>(keys: Vec<K>, values: Vec<V>) -> HashMap<K, V>
Expand Down
Loading