enhanced logging and external connection

This commit is contained in:
aglkm
2024-06-19 16:23:00 +03:00
parent 239683070b
commit 9f3446ddf2
7 changed files with 163 additions and 33 deletions

91
Cargo.lock generated
View File

@@ -41,6 +41,55 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "anstream"
version = "0.6.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b"
dependencies = [
"anstyle",
"anstyle-parse",
"anstyle-query",
"anstyle-wincon",
"colorchoice",
"is_terminal_polyfill",
"utf8parse",
]
[[package]]
name = "anstyle"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b"
[[package]]
name = "anstyle-parse"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4"
dependencies = [
"utf8parse",
]
[[package]]
name = "anstyle-query"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ad186efb764318d35165f1758e7dcef3b10628e26d41a44bc5550652e6804391"
dependencies = [
"windows-sys 0.52.0",
]
[[package]]
name = "anstyle-wincon"
version = "3.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19"
dependencies = [
"anstyle",
"windows-sys 0.52.0",
]
[[package]] [[package]]
name = "anyhow" name = "anyhow"
version = "1.0.86" version = "1.0.86"
@@ -234,6 +283,12 @@ dependencies = [
"phf_codegen", "phf_codegen",
] ]
[[package]]
name = "colorchoice"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422"
[[package]] [[package]]
name = "colored" name = "colored"
version = "2.1.0" version = "2.1.0"
@@ -482,6 +537,29 @@ dependencies = [
"cfg-if", "cfg-if",
] ]
[[package]]
name = "env_filter"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a009aa4810eb158359dda09d0c87378e4bbb89b5a801f016885a4707ba24f7ea"
dependencies = [
"log",
"regex",
]
[[package]]
name = "env_logger"
version = "0.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38b35839ba51819680ba087cd351788c9a3c476841207e0b8cee0b04722343b9"
dependencies = [
"anstream",
"anstyle",
"env_filter",
"humantime",
"log",
]
[[package]] [[package]]
name = "equivalent" name = "equivalent"
version = "1.0.1" version = "1.0.1"
@@ -743,6 +821,7 @@ dependencies = [
"colored", "colored",
"config", "config",
"either", "either",
"env_logger",
"fs_extra", "fs_extra",
"futures", "futures",
"humantime", "humantime",
@@ -982,6 +1061,12 @@ dependencies = [
"windows-sys 0.52.0", "windows-sys 0.52.0",
] ]
[[package]]
name = "is_terminal_polyfill"
version = "1.70.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800"
[[package]] [[package]]
name = "itoa" name = "itoa"
version = "1.0.11" version = "1.0.11"
@@ -2540,6 +2625,12 @@ dependencies = [
"percent-encoding", "percent-encoding",
] ]
[[package]]
name = "utf8parse"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
[[package]] [[package]]
name = "valuable" name = "valuable"
version = "0.1.0" version = "0.1.0"

View File

@@ -20,6 +20,7 @@ lazy_static = "1.4.0"
shellexpand = "3.1.0" shellexpand = "3.1.0"
either = "1.11.0" either = "1.11.0"
anyhow = "1.0.86" anyhow = "1.0.86"
env_logger = "0.11.3"
[dependencies.reqwest] [dependencies.reqwest]
version = "0.11.23" version = "0.11.23"

View File

@@ -7,13 +7,13 @@ port = "3413"
# Node protocol. Either HTTP or HTTPS. # Node protocol. Either HTTP or HTTPS.
proto = "http" proto = "http"
# API username. # API username. Comment out if user is not required.
user = "grin" user = "grin"
# API secret path. # API secret path. Comment out if secret is not required.
api_secret_path = "~/.grin/main/.api_secret" api_secret_path = "~/.grin/main/.api_secret"
# Foreign API secret path. # Foreign API secret path. Comment out if secret is not required.
foreign_api_secret_path = "~/.grin/main/.foreign_api_secret" foreign_api_secret_path = "~/.grin/main/.foreign_api_secret"
# Path to Grin directory. # Path to Grin directory.
@@ -26,6 +26,21 @@ coingecko_api = "enabled"
public_api = "enabled" public_api = "enabled"
# Grinnode config
# ip = "grinnode.live"
# port = "3413"
# proto = "https"
# coingecko_api = "enabled"
# public_api = "enabled"
# Grincoin config
# ip = "grincoin.org"
# proto = "https"
# coingecko_api = "enabled"
# public_api = "enabled"
# Testnet config # Testnet config
# ip = "127.0.0.1" # ip = "127.0.0.1"
# port = "13413" # port = "13413"

View File

@@ -22,15 +22,14 @@ Grin is the very first, simple and fair MimbleWimble blockchain implementation.
cd grin-explorer cd grin-explorer
cargo build --release cargo build --release
``` ```
4. Run executable: `./target/release/grin-explorer` 4. Run executable: `RUST_LOG=rocket=warn,grin_explorer ./target/release/grin-explorer`
You will see the following output: You will see the following output:
``` ```
[ INFO ] Starting up Explorer. [2024-06-19T13:12:34Z INFO grin_explorer] starting up.
[ INFO ] Starting up Rocket engine. [2024-06-19T13:12:34Z WARN rocket::launch] 🚀 Rocket has launched from http://127.0.0.1:8000
🚀 Rocket has launched from http://127.0.0.1:8000 [2024-06-19T13:12:34Z INFO grin_explorer] ready.
[ OK ] Explorer Ready.
``` ```
5. Open explorer in your browser: http://127.0.0.1:8000 5. Open explorer in your browser: http://127.0.0.1:8000

View File

@@ -1,6 +1,5 @@
[default] [default]
address = "127.0.0.1" address = "127.0.0.1"
log_level = "critical"
# Uncomment and change default port number (8000) if another instance of the explorer is needed to run. # Uncomment and change default port number (8000) if another instance of the explorer is needed to run.
# E.g. Mainnet (8000) and Testnet (8001) instances. # E.g. Mainnet (8000) and Testnet (8001) instances.

View File

@@ -5,7 +5,6 @@ use rocket::fs::FileServer;
use rocket::State; use rocket::State;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use std::time::Duration; use std::time::Duration;
use colored::Colorize;
use rocket::tokio; use rocket::tokio;
use rocket::response::Redirect; use rocket::response::Redirect;
use either::Either; use either::Either;
@@ -396,7 +395,11 @@ fn last_block_age(blocks: &State<Arc<Mutex<Vec<Block>>>>) -> String {
fn disk_usage(dashboard: &State<Arc<Mutex<Dashboard>>>) -> String { fn disk_usage(dashboard: &State<Arc<Mutex<Dashboard>>>) -> String {
let data = dashboard.lock().unwrap(); let data = dashboard.lock().unwrap();
format!("{} GB", data.disk_usage) if data.disk_usage.is_empty() == false {
return format!("{} GB", data.disk_usage);
} else {
return format!("<i class=\"bi bi-x-lg\"></i>");
}
} }
@@ -602,7 +605,9 @@ fn block_list_index(dashboard: &State<Arc<Mutex<Dashboard>>>) -> String {
// Main // Main
#[rocket::main] #[rocket::main]
async fn main() { async fn main() {
println!("{} Starting up Explorer.", "[ INFO ]".cyan()); env_logger::init();
info!("starting up.");
let dash = Arc::new(Mutex::new(Dashboard::new())); let dash = Arc::new(Mutex::new(Dashboard::new()));
let dash_clone = dash.clone(); let dash_clone = dash.clone();
@@ -622,12 +627,12 @@ async fn main() {
Ok(_v) => { Ok(_v) => {
if ready == false { if ready == false {
ready = true; ready = true;
println!("{} Explorer Ready.", "[ OK ]".green()); info!("ready.");
} }
}, },
Err(e) => { Err(e) => {
ready = false; ready = false;
println!("{} {}.", "[ ERROR ]".red(), e); error!("{}", e);
}, },
} }
@@ -635,8 +640,6 @@ async fn main() {
} }
}); });
println!("{} Starting up Rocket engine.", "[ INFO ]".cyan());
// Starting Rocket engine. // Starting Rocket engine.
let _ = rocket::build() let _ = rocket::build()
.manage(dash) .manage(dash)

View File

@@ -43,11 +43,17 @@ lazy_static! {
} }
} }
cfg.api_secret = fs::read_to_string(format!("{}", if cfg.api_secret_path.is_empty() == false {
shellexpand::tilde(&cfg.api_secret_path))).unwrap(); cfg.api_secret = fs::read_to_string(format!("{}", shellexpand::tilde(&cfg.api_secret_path))).unwrap();
cfg.foreign_api_secret = fs::read_to_string(format!("{}", }
shellexpand::tilde(&cfg.foreign_api_secret_path))).unwrap();
cfg.grin_dir = format!("{}", shellexpand::tilde(&cfg.grin_dir)); if cfg.foreign_api_secret_path.is_empty() == false {
cfg.foreign_api_secret = fs::read_to_string(format!("{}", shellexpand::tilde(&cfg.foreign_api_secret_path))).unwrap();
}
if cfg.grin_dir.is_empty() == false {
cfg.grin_dir = format!("{}", shellexpand::tilde(&cfg.grin_dir));
}
cfg cfg
}; };
@@ -59,13 +65,16 @@ pub async fn call(method: &str, params: &str, id: &str, rpc_type: &str) -> Resul
let rpc_url; let rpc_url;
let secret; let secret;
if rpc_type == "owner" { if CONFIG.port.is_empty() == false {
rpc_url = format!("{}://{}:{}/v2/owner", CONFIG.proto, CONFIG.ip, CONFIG.port); rpc_url = format!("{}://{}:{}/v2/{}", CONFIG.proto, CONFIG.ip, CONFIG.port, rpc_type);
secret = CONFIG.api_secret.clone(); } else {
rpc_url = format!("{}://{}/v2/{}", CONFIG.proto, CONFIG.ip, rpc_type);
} }
else {
rpc_url = format!("{}://{}:{}/v2/foreign", CONFIG.proto, CONFIG.ip, CONFIG.port); if rpc_type == "owner" {
secret = CONFIG.foreign_api_secret.clone(); secret = CONFIG.api_secret.clone();
} else {
secret = CONFIG.foreign_api_secret.clone();
} }
let client = reqwest::Client::new(); let client = reqwest::Client::new();
@@ -76,6 +85,11 @@ pub async fn call(method: &str, params: &str, id: &str, rpc_type: &str) -> Resul
.send() .send()
.await?; .await?;
match result.error_for_status_ref() {
Ok(_res) => (),
Err(err) => { error!("rpc failed, status code: {:?}", err.status().unwrap()); },
}
let val: Value = serde_json::from_str(&result.text().await.unwrap())?; let val: Value = serde_json::from_str(&result.text().await.unwrap())?;
Ok(val) Ok(val)
@@ -173,7 +187,7 @@ pub async fn get_market(dashboard: Arc<Mutex<Dashboard>>) -> Result<(), Error> {
if CONFIG.coingecko_api == "enabled" && val != Value::Null { if CONFIG.coingecko_api == "enabled" && val != Value::Null {
// Check if CoingGecko API returned error // Check if CoingGecko API returned error
if let Some(status) = val.get("status") { if let Some(status) = val.get("status") {
println!("{} {}.", "[ WARNING ]".yellow(), status["error_message"].as_str().unwrap().to_string()); warn!("{}", status["error_message"].as_str().unwrap().to_string());
} else { } else {
data.price_usd = format!("{:.3}", val["grin"]["usd"].to_string().parse::<f64>().unwrap()); data.price_usd = format!("{:.3}", val["grin"]["usd"].to_string().parse::<f64>().unwrap());
data.price_btc = format!("{:.8}", val["grin"]["btc"].to_string().parse::<f64>().unwrap()); data.price_btc = format!("{:.8}", val["grin"]["btc"].to_string().parse::<f64>().unwrap());
@@ -205,7 +219,13 @@ pub fn get_disk_usage(dashboard: Arc<Mutex<Dashboard>>) -> Result<(), Error> {
match get_size(chain_dir.clone()) { match get_size(chain_dir.clone()) {
Ok(chain_size) => data.disk_usage = format!("{:.2}", (chain_size as f64) / 1000.0 / 1000.0 / 1000.0), Ok(chain_size) => data.disk_usage = format!("{:.2}", (chain_size as f64) / 1000.0 / 1000.0 / 1000.0),
Err(e) => println!("{} {}: \"{}\".", "[ ERROR ]".red(), e, chain_dir), Err(e) => {
if CONFIG.ip == "127.0.0.1" || CONFIG.ip == "0.0.0.0" {
error!("{}: \"{}\"", e, chain_dir);
} else {
// Ignore error for external node connection
}
},
} }
Ok(()) Ok(())
@@ -237,7 +257,7 @@ pub async fn get_mining_stats(dashboard: Arc<Mutex<Dashboard>>) -> Result<(), an
// https://forum.grin.mw/t/difference-c31-and-c32-c33/7018/7 // https://forum.grin.mw/t/difference-c31-and-c32-c33/7018/7
let hashrate = (net_diff as f64) * 42.0 / 60.0 / 16384.0; let hashrate = (net_diff as f64) * 42.0 / 60.0 / 16384.0;
// KG/s // kG/s
if hashrate > 1000.0 { if hashrate > 1000.0 {
data.hashrate = format!("{:.2} kG/s", hashrate / 1000.0); data.hashrate = format!("{:.2} kG/s", hashrate / 1000.0);
// G/s // G/s
@@ -255,10 +275,12 @@ pub async fn get_mining_stats(dashboard: Arc<Mutex<Dashboard>>) -> Result<(), an
// Assuming $0.07 per kW/h // Assuming $0.07 per kW/h
data.production_cost = format!("{:.3}", 120.0 / 1000.0 * 0.07 * (1.0 / coins_per_hour)); data.production_cost = format!("{:.3}", 120.0 / 1000.0 * 0.07 * (1.0 / coins_per_hour));
data.reward_ratio = format!("{:.2}", data.price_usd.parse::<f64>().unwrap() if data.price_usd.is_empty() == false {
data.reward_ratio = format!("{:.2}", data.price_usd.parse::<f64>().unwrap()
/ data.production_cost.parse::<f64>().unwrap()); / data.production_cost.parse::<f64>().unwrap());
data.breakeven_cost = format!("{:.2}", data.price_usd.parse::<f64>().unwrap() data.breakeven_cost = format!("{:.2}", data.price_usd.parse::<f64>().unwrap()
/ (120.0 / 1000.0 * (1.0 / coins_per_hour))); / (120.0 / 1000.0 * (1.0 / coins_per_hour)));
}
} }
} }
} }