Improve SDK and SWQOS logging: alignment, errors, duration format
- Rename wait_transaction_confirmed to wait_tx_confirmed (params, lib, docs, examples)
- SDK timing: use [SDK][provider] style with fixed-width labels; add newline before block
- Move print_sdk_timing_block to common::sdk_log; unify SWQOS_LABEL_WIDTH
- SWQOS submitted/failed: aligned [Provider] labels via log_swqos_submitted/submission_failed
- Extract short error message from JSON (message/data) or quoted string; prefix with 'error: '
- Format elapsed as 'X.XXXX ms' or 'X.XXXX µs' (4 decimals, space before unit); use comma before error
- Add SwqosType::as_str() for zero-allocation log labels; only parse JSON when input starts with '{'
Made-with: Cursor
This commit is contained in:
@@ -3,10 +3,59 @@
|
||||
//! Controlled by `TradeConfig::log_enabled`, set in `TradingClient::new`.
|
||||
//! All SDK logs (timing, SWQOS submit/confirm, WSOL, blacklist, etc.) should check this before output.
|
||||
|
||||
use std::fmt;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::time::Duration;
|
||||
|
||||
/// Format duration for log: "97.9396 ms" or "13.936 µs", 4 decimal places, space before unit.
|
||||
fn format_elapsed(d: Duration) -> String {
|
||||
let secs = d.as_secs_f64();
|
||||
if secs < 0.001 {
|
||||
format!("{:.4} µs", secs * 1_000_000.0)
|
||||
} else {
|
||||
format!("{:.4} ms", secs * 1000.0)
|
||||
}
|
||||
}
|
||||
|
||||
/// Extract a short error message for SWQOS submission failed log.
|
||||
/// Tries JSON "message"/"data" and quoted string; on any parse failure returns original (no panic).
|
||||
fn extract_swqos_error_message(s: &str) -> String {
|
||||
let s = s.trim();
|
||||
if s.is_empty() {
|
||||
return String::new();
|
||||
}
|
||||
// Plain double-quoted string (no inner JSON): unquote
|
||||
if s.starts_with('"') && s.ends_with('"') && s.len() >= 2 {
|
||||
let inner = &s[1..s.len() - 1];
|
||||
if !inner.contains('{') {
|
||||
return inner.replace("\\\"", "\"");
|
||||
}
|
||||
}
|
||||
// Try parse as JSON only when input looks like JSON (avoid parsing long non-JSON strings)
|
||||
if s.starts_with('{') {
|
||||
if let Ok(v) = serde_json::from_str::<serde_json::Value>(s) {
|
||||
let obj = v
|
||||
.get("error")
|
||||
.and_then(|e| e.as_object())
|
||||
.or_else(|| v.as_object());
|
||||
if let Some(o) = obj {
|
||||
if let Some(m) = o.get("message").and_then(|x| x.as_str()) {
|
||||
return m.to_string();
|
||||
}
|
||||
if let Some(d) = o.get("data").and_then(|x| x.as_str()) {
|
||||
return d.to_string();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
s.to_string()
|
||||
}
|
||||
|
||||
static SDK_LOG_ENABLED: AtomicBool = AtomicBool::new(true);
|
||||
|
||||
/// Width of [provider] label so SWQOS submit/confirm lines align (longest: Speedlanding).
|
||||
pub const SWQOS_LABEL_WIDTH: usize = 12;
|
||||
|
||||
/// Whether SDK logging is enabled (set from TradeConfig.log_enabled in TradingClient::new).
|
||||
#[inline(always)]
|
||||
pub fn sdk_log_enabled() -> bool {
|
||||
@@ -17,3 +66,103 @@ pub fn sdk_log_enabled() -> bool {
|
||||
pub fn set_sdk_log_enabled(enabled: bool) {
|
||||
SDK_LOG_ENABLED.store(enabled, Ordering::Relaxed);
|
||||
}
|
||||
|
||||
/// Aligned log: ` [Soyas ] Buy submitted: 13.936 µs`. Call only when sdk_log_enabled().
|
||||
#[inline]
|
||||
pub fn log_swqos_submitted(
|
||||
provider: &str,
|
||||
trade_type: impl fmt::Display,
|
||||
elapsed: Duration,
|
||||
) {
|
||||
println!(
|
||||
" [{:width$}] {} submitted: {}",
|
||||
provider,
|
||||
trade_type,
|
||||
format_elapsed(elapsed),
|
||||
width = SWQOS_LABEL_WIDTH
|
||||
);
|
||||
}
|
||||
|
||||
/// Prints one SDK timing block (build_instructions, before_submit, per-channel submit_done).
|
||||
/// When confirm_us is Some, prints confirmed + total; when None, prints "confirmed: -, total: submit_ms".
|
||||
/// Call only when sdk_log_enabled().
|
||||
pub fn print_sdk_timing_block(
|
||||
dir: &str,
|
||||
start_us: Option<i64>,
|
||||
build_end_us: Option<i64>,
|
||||
before_submit_us: Option<i64>,
|
||||
submit_timings: &[(crate::swqos::SwqosType, i64)],
|
||||
confirm_us: Option<i64>,
|
||||
) {
|
||||
println!();
|
||||
let start_us = match start_us {
|
||||
Some(u) => u,
|
||||
None => return,
|
||||
};
|
||||
if let Some(end_us) = build_end_us {
|
||||
println!(
|
||||
" [SDK][{:width$}] {} build_instructions: {:.4} ms",
|
||||
"-",
|
||||
dir,
|
||||
(end_us - start_us) as f64 / 1000.0,
|
||||
width = SWQOS_LABEL_WIDTH
|
||||
);
|
||||
}
|
||||
if let Some(end_us) = before_submit_us {
|
||||
println!(
|
||||
" [SDK][{:width$}] {} before_submit: {:.4} ms",
|
||||
"-",
|
||||
dir,
|
||||
(end_us - start_us) as f64 / 1000.0,
|
||||
width = SWQOS_LABEL_WIDTH
|
||||
);
|
||||
}
|
||||
if let Some(confirm_done_us) = confirm_us {
|
||||
let total_ms = (confirm_done_us - start_us) as f64 / 1000.0;
|
||||
for (swqos_type, submit_done_us) in submit_timings {
|
||||
let submit_ms = (*submit_done_us - start_us).max(0) as f64 / 1000.0;
|
||||
let confirmed_ms = (confirm_done_us - *submit_done_us).max(0) as f64 / 1000.0;
|
||||
println!(
|
||||
" [SDK][{:width$}] {} submit_done: {:.4} ms, confirmed: {:.4} ms, total: {:.4} ms",
|
||||
swqos_type.as_str(),
|
||||
dir,
|
||||
submit_ms,
|
||||
confirmed_ms,
|
||||
total_ms,
|
||||
width = SWQOS_LABEL_WIDTH
|
||||
);
|
||||
}
|
||||
} else {
|
||||
for (swqos_type, submit_done_us) in submit_timings {
|
||||
let submit_ms = (*submit_done_us - start_us).max(0) as f64 / 1000.0;
|
||||
println!(
|
||||
" [SDK][{:width$}] {} submit_done: {:.4} ms, confirmed: -, total: {:.4} ms",
|
||||
swqos_type.as_str(),
|
||||
dir,
|
||||
submit_ms,
|
||||
submit_ms,
|
||||
width = SWQOS_LABEL_WIDTH
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Aligned log: ` [Stellium ] Buy submission failed after 97.9396 ms: ...`. Call only when sdk_log_enabled().
|
||||
/// Error is normalized: JSON "message"/"data" or quoted string is shown; raw JSON is not.
|
||||
#[inline]
|
||||
pub fn log_swqos_submission_failed(
|
||||
provider: &str,
|
||||
trade_type: impl fmt::Display,
|
||||
elapsed: Duration,
|
||||
err: impl fmt::Display,
|
||||
) {
|
||||
let msg = extract_swqos_error_message(&format!("{}", err));
|
||||
eprintln!(
|
||||
" [{:width$}] {} submission failed after {}, error: {}",
|
||||
provider,
|
||||
trade_type,
|
||||
format_elapsed(elapsed),
|
||||
msg,
|
||||
width = SWQOS_LABEL_WIDTH
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user