Merge relay debug view
Fix a few conflicts
This commit is contained in:
@@ -2,21 +2,21 @@ use crate::Error;
|
||||
use nostrdb::{Filter, Note};
|
||||
use serde_json::json;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct EventClientMessage<'a> {
|
||||
note: Note<'a>,
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct EventClientMessage {
|
||||
pub note_json: String,
|
||||
}
|
||||
|
||||
impl EventClientMessage<'_> {
|
||||
pub fn to_json(&self) -> Result<String, Error> {
|
||||
Ok(format!("[\"EVENT\", {}]", self.note.json()?))
|
||||
impl EventClientMessage {
|
||||
pub fn to_json(&self) -> String {
|
||||
format!("[\"EVENT\", {}]", self.note_json)
|
||||
}
|
||||
}
|
||||
|
||||
/// Messages sent by clients, received by relays
|
||||
#[derive(Debug)]
|
||||
pub enum ClientMessage<'a> {
|
||||
Event(EventClientMessage<'a>),
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum ClientMessage {
|
||||
Event(EventClientMessage),
|
||||
Req {
|
||||
sub_id: String,
|
||||
filters: Vec<Filter>,
|
||||
@@ -27,9 +27,11 @@ pub enum ClientMessage<'a> {
|
||||
Raw(String),
|
||||
}
|
||||
|
||||
impl<'a> ClientMessage<'a> {
|
||||
pub fn event(note: Note<'a>) -> Self {
|
||||
ClientMessage::Event(EventClientMessage { note })
|
||||
impl ClientMessage {
|
||||
pub fn event(note: Note) -> Result<Self, Error> {
|
||||
Ok(ClientMessage::Event(EventClientMessage {
|
||||
note_json: note.json()?,
|
||||
}))
|
||||
}
|
||||
|
||||
pub fn raw(raw: String) -> Self {
|
||||
@@ -46,7 +48,7 @@ impl<'a> ClientMessage<'a> {
|
||||
|
||||
pub fn to_json(&self) -> Result<String, Error> {
|
||||
Ok(match self {
|
||||
Self::Event(ecm) => ecm.to_json()?,
|
||||
Self::Event(ecm) => ecm.to_json(),
|
||||
Self::Raw(raw) => raw.clone(),
|
||||
Self::Req { sub_id, filters } => {
|
||||
if filters.is_empty() {
|
||||
|
||||
@@ -18,6 +18,7 @@ pub use profile::Profile;
|
||||
pub use pubkey::Pubkey;
|
||||
pub use relay::message::{RelayEvent, RelayMessage};
|
||||
pub use relay::pool::{PoolEvent, PoolRelay, RelayPool};
|
||||
pub use relay::subs_debug::{OwnedRelayEvent, RelayLogEvent, SubsDebug, TransferStats};
|
||||
pub use relay::{Relay, RelayStatus};
|
||||
|
||||
pub type Result<T> = std::result::Result<T, error::Error>;
|
||||
|
||||
@@ -8,6 +8,12 @@ pub struct CommandResult<'a> {
|
||||
message: &'a str,
|
||||
}
|
||||
|
||||
pub fn calculate_command_result_size(result: &CommandResult) -> usize {
|
||||
std::mem::size_of_val(result)
|
||||
+ result.event_id.as_bytes().len()
|
||||
+ result.message.as_bytes().len()
|
||||
}
|
||||
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
pub enum RelayMessage<'a> {
|
||||
OK(CommandResult<'a>),
|
||||
|
||||
@@ -13,6 +13,7 @@ use tracing::{debug, error};
|
||||
|
||||
pub mod message;
|
||||
pub mod pool;
|
||||
pub mod subs_debug;
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub enum RelayStatus {
|
||||
@@ -91,7 +92,7 @@ impl MulticastRelay {
|
||||
}
|
||||
|
||||
pub fn send(&self, msg: &EventClientMessage) -> Result<()> {
|
||||
let json = msg.to_json()?;
|
||||
let json = msg.to_json();
|
||||
let len = json.len();
|
||||
|
||||
debug!("writing to multicast relay");
|
||||
|
||||
@@ -13,6 +13,8 @@ use ewebsock::{WsEvent, WsMessage};
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
use tracing::{debug, error};
|
||||
|
||||
use super::subs_debug::SubsDebug;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct PoolEvent<'a> {
|
||||
pub relay: &'a str,
|
||||
@@ -124,6 +126,7 @@ impl WebsocketRelay {
|
||||
pub struct RelayPool {
|
||||
pub relays: Vec<PoolRelay>,
|
||||
pub ping_rate: Duration,
|
||||
pub debug: Option<SubsDebug>,
|
||||
}
|
||||
|
||||
impl Default for RelayPool {
|
||||
@@ -138,6 +141,7 @@ impl RelayPool {
|
||||
RelayPool {
|
||||
relays: vec![],
|
||||
ping_rate: Duration::from_secs(25),
|
||||
debug: None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -150,6 +154,10 @@ impl RelayPool {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn use_debug(&mut self) {
|
||||
self.debug = Some(SubsDebug::default());
|
||||
}
|
||||
|
||||
pub fn ping_rate(&mut self, duration: Duration) -> &mut Self {
|
||||
self.ping_rate = duration;
|
||||
self
|
||||
@@ -174,6 +182,9 @@ impl RelayPool {
|
||||
|
||||
pub fn send(&mut self, cmd: &ClientMessage) {
|
||||
for relay in &mut self.relays {
|
||||
if let Some(debug) = &mut self.debug {
|
||||
debug.send_cmd(relay.url().to_owned(), cmd);
|
||||
}
|
||||
if let Err(err) = relay.send(cmd) {
|
||||
error!("error sending {:?} to {}: {err}", cmd, relay.url());
|
||||
}
|
||||
@@ -182,7 +193,11 @@ impl RelayPool {
|
||||
|
||||
pub fn unsubscribe(&mut self, subid: String) {
|
||||
for relay in &mut self.relays {
|
||||
if let Err(err) = relay.send(&ClientMessage::close(subid.clone())) {
|
||||
let cmd = ClientMessage::close(subid.clone());
|
||||
if let Some(debug) = &mut self.debug {
|
||||
debug.send_cmd(relay.url().to_owned(), &cmd);
|
||||
}
|
||||
if let Err(err) = relay.send(&cmd) {
|
||||
error!(
|
||||
"error unsubscribing from {} on {}: {err}",
|
||||
&subid,
|
||||
@@ -194,6 +209,13 @@ impl RelayPool {
|
||||
|
||||
pub fn subscribe(&mut self, subid: String, filter: Vec<Filter>) {
|
||||
for relay in &mut self.relays {
|
||||
if let Some(debug) = &mut self.debug {
|
||||
debug.send_cmd(
|
||||
relay.url().to_owned(),
|
||||
&ClientMessage::req(subid.clone(), filter.clone()),
|
||||
);
|
||||
}
|
||||
|
||||
if let Err(err) = relay.send(&ClientMessage::req(subid.clone(), filter.clone())) {
|
||||
error!("error subscribing to {}: {err}", relay.url());
|
||||
}
|
||||
@@ -255,8 +277,11 @@ impl RelayPool {
|
||||
pub fn send_to(&mut self, cmd: &ClientMessage, relay_url: &str) {
|
||||
for relay in &mut self.relays {
|
||||
if relay.url() == relay_url {
|
||||
if let Some(debug) = &mut self.debug {
|
||||
debug.send_cmd(relay.url().to_owned(), cmd);
|
||||
}
|
||||
if let Err(err) = relay.send(cmd) {
|
||||
error!("error sending {:?} to {}: {err}", cmd, relay_url);
|
||||
error!("send_to err: {err}");
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -350,10 +375,17 @@ impl RelayPool {
|
||||
}
|
||||
}
|
||||
}
|
||||
return Some(PoolEvent {
|
||||
|
||||
if let Some(debug) = &mut self.debug {
|
||||
debug.receive_cmd(relay.url().to_owned(), (&event).into());
|
||||
}
|
||||
|
||||
let pool_event = PoolEvent {
|
||||
event,
|
||||
relay: relay.url(),
|
||||
});
|
||||
};
|
||||
|
||||
return Some(pool_event);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
267
crates/enostr/src/relay/subs_debug.rs
Normal file
267
crates/enostr/src/relay/subs_debug.rs
Normal file
@@ -0,0 +1,267 @@
|
||||
use std::{collections::HashMap, mem, time::SystemTime};
|
||||
|
||||
use ewebsock::WsMessage;
|
||||
use nostrdb::Filter;
|
||||
|
||||
use crate::{ClientMessage, Error, RelayEvent, RelayMessage};
|
||||
|
||||
use super::message::calculate_command_result_size;
|
||||
|
||||
type RelayId = String;
|
||||
type SubId = String;
|
||||
|
||||
pub struct SubsDebug {
|
||||
data: HashMap<RelayId, RelayStats>,
|
||||
time_incd: SystemTime,
|
||||
pub relay_events_selection: Option<RelayId>,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct RelayStats {
|
||||
pub count: TransferStats,
|
||||
pub events: Vec<RelayLogEvent>,
|
||||
pub sub_data: HashMap<SubId, SubStats>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum RelayLogEvent {
|
||||
Send(ClientMessage),
|
||||
Recieve(OwnedRelayEvent),
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum OwnedRelayEvent {
|
||||
Opened,
|
||||
Closed,
|
||||
Other(String),
|
||||
Error(String),
|
||||
Message(String),
|
||||
}
|
||||
|
||||
impl From<RelayEvent<'_>> for OwnedRelayEvent {
|
||||
fn from(value: RelayEvent<'_>) -> Self {
|
||||
match value {
|
||||
RelayEvent::Opened => OwnedRelayEvent::Opened,
|
||||
RelayEvent::Closed => OwnedRelayEvent::Closed,
|
||||
RelayEvent::Other(ws_message) => {
|
||||
let ws_str = match ws_message {
|
||||
WsMessage::Binary(_) => "Binary".to_owned(),
|
||||
WsMessage::Text(t) => format!("Text:{}", t),
|
||||
WsMessage::Unknown(u) => format!("Unknown:{}", u),
|
||||
WsMessage::Ping(_) => "Ping".to_owned(),
|
||||
WsMessage::Pong(_) => "Pong".to_owned(),
|
||||
};
|
||||
OwnedRelayEvent::Other(ws_str)
|
||||
}
|
||||
RelayEvent::Error(error) => OwnedRelayEvent::Error(error.to_string()),
|
||||
RelayEvent::Message(relay_message) => {
|
||||
let relay_msg = match relay_message {
|
||||
RelayMessage::OK(_) => "OK".to_owned(),
|
||||
RelayMessage::Eose(s) => format!("EOSE:{}", s),
|
||||
RelayMessage::Event(_, s) => format!("EVENT:{}", s),
|
||||
RelayMessage::Notice(s) => format!("NOTICE:{}", s),
|
||||
};
|
||||
OwnedRelayEvent::Message(relay_msg)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Hash, Clone)]
|
||||
pub struct RelaySub {
|
||||
pub(crate) subid: String,
|
||||
pub(crate) filter: String,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct SubStats {
|
||||
pub filter: String,
|
||||
pub count: TransferStats,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct TransferStats {
|
||||
pub up_total: usize,
|
||||
pub down_total: usize,
|
||||
|
||||
// 1 sec < last tick < 2 sec
|
||||
pub up_sec_prior: usize,
|
||||
pub down_sec_prior: usize,
|
||||
|
||||
// < 1 sec since last tick
|
||||
up_sec_cur: usize,
|
||||
down_sec_cur: usize,
|
||||
}
|
||||
|
||||
impl Default for SubsDebug {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
data: Default::default(),
|
||||
time_incd: SystemTime::now(),
|
||||
relay_events_selection: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl SubsDebug {
|
||||
pub fn get_data(&self) -> &HashMap<RelayId, RelayStats> {
|
||||
&self.data
|
||||
}
|
||||
|
||||
pub(crate) fn send_cmd(&mut self, relay: String, cmd: &ClientMessage) {
|
||||
let data = self.data.entry(relay).or_default();
|
||||
let msg_num_bytes = calculate_client_message_size(cmd);
|
||||
match cmd {
|
||||
ClientMessage::Req { sub_id, filters } => {
|
||||
data.sub_data.insert(
|
||||
sub_id.to_string(),
|
||||
SubStats {
|
||||
filter: filters_to_string(filters),
|
||||
count: Default::default(),
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
ClientMessage::Close { sub_id } => {
|
||||
data.sub_data.remove(sub_id);
|
||||
}
|
||||
|
||||
_ => {}
|
||||
}
|
||||
|
||||
data.count.up_sec_cur += msg_num_bytes;
|
||||
|
||||
data.events.push(RelayLogEvent::Send(cmd.clone()));
|
||||
}
|
||||
|
||||
pub(crate) fn receive_cmd(&mut self, relay: String, cmd: RelayEvent) {
|
||||
let data = self.data.entry(relay).or_default();
|
||||
let msg_num_bytes = calculate_relay_event_size(&cmd);
|
||||
if let RelayEvent::Message(RelayMessage::Event(sid, _)) = cmd {
|
||||
if let Some(sub_data) = data.sub_data.get_mut(sid) {
|
||||
let c = &mut sub_data.count;
|
||||
c.down_sec_cur += msg_num_bytes;
|
||||
}
|
||||
};
|
||||
|
||||
data.count.down_sec_cur += msg_num_bytes;
|
||||
|
||||
data.events.push(RelayLogEvent::Recieve(cmd.into()));
|
||||
}
|
||||
|
||||
pub fn try_increment_stats(&mut self) {
|
||||
let cur_time = SystemTime::now();
|
||||
if let Ok(dur) = cur_time.duration_since(self.time_incd) {
|
||||
if dur.as_secs() >= 1 {
|
||||
self.time_incd = cur_time;
|
||||
self.internal_inc_stats();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn internal_inc_stats(&mut self) {
|
||||
for relay_data in self.data.values_mut() {
|
||||
let c = &mut relay_data.count;
|
||||
inc_data_count(c);
|
||||
|
||||
for sub in relay_data.sub_data.values_mut() {
|
||||
inc_data_count(&mut sub.count);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn inc_data_count(c: &mut TransferStats) {
|
||||
c.up_total += c.up_sec_cur;
|
||||
c.up_sec_prior = c.up_sec_cur;
|
||||
|
||||
c.down_total += c.down_sec_cur;
|
||||
c.down_sec_prior = c.down_sec_cur;
|
||||
|
||||
c.up_sec_cur = 0;
|
||||
c.down_sec_cur = 0;
|
||||
}
|
||||
|
||||
fn calculate_client_message_size(message: &ClientMessage) -> usize {
|
||||
match message {
|
||||
ClientMessage::Event(note) => note.note_json.len() + 10, // 10 is ["EVENT",]
|
||||
ClientMessage::Req { sub_id, filters } => {
|
||||
mem::size_of_val(message)
|
||||
+ mem::size_of_val(sub_id)
|
||||
+ sub_id.as_bytes().len()
|
||||
+ filters.iter().map(mem::size_of_val).sum::<usize>()
|
||||
}
|
||||
ClientMessage::Close { sub_id } => {
|
||||
mem::size_of_val(message) + mem::size_of_val(sub_id) + sub_id.as_bytes().len()
|
||||
}
|
||||
ClientMessage::Raw(data) => mem::size_of_val(message) + data.as_bytes().len(),
|
||||
}
|
||||
}
|
||||
|
||||
fn calculate_relay_event_size(event: &RelayEvent<'_>) -> usize {
|
||||
let base_size = mem::size_of_val(event); // Size of the enum on the stack
|
||||
|
||||
let variant_size = match event {
|
||||
RelayEvent::Opened | RelayEvent::Closed => 0, // No additional data
|
||||
RelayEvent::Other(ws_message) => calculate_ws_message_size(ws_message),
|
||||
RelayEvent::Error(error) => calculate_error_size(error),
|
||||
RelayEvent::Message(message) => calculate_relay_message_size(message),
|
||||
};
|
||||
|
||||
base_size + variant_size
|
||||
}
|
||||
|
||||
fn calculate_ws_message_size(message: &WsMessage) -> usize {
|
||||
match message {
|
||||
WsMessage::Binary(vec) | WsMessage::Ping(vec) | WsMessage::Pong(vec) => {
|
||||
mem::size_of_val(message) + vec.len()
|
||||
}
|
||||
WsMessage::Text(string) | WsMessage::Unknown(string) => {
|
||||
mem::size_of_val(message) + string.as_bytes().len()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn calculate_error_size(error: &Error) -> usize {
|
||||
match error {
|
||||
Error::Empty
|
||||
| Error::DecodeFailed
|
||||
| Error::HexDecodeFailed
|
||||
| Error::InvalidBech32
|
||||
| Error::InvalidByteSize
|
||||
| Error::InvalidSignature
|
||||
| Error::Io(_)
|
||||
| Error::InvalidPublicKey => mem::size_of_val(error), // No heap usage
|
||||
|
||||
Error::Json(json_err) => mem::size_of_val(error) + json_err.to_string().as_bytes().len(),
|
||||
|
||||
Error::Nostrdb(nostrdb_err) => {
|
||||
mem::size_of_val(error) + nostrdb_err.to_string().as_bytes().len()
|
||||
}
|
||||
|
||||
Error::Generic(string) => mem::size_of_val(error) + string.as_bytes().len(),
|
||||
}
|
||||
}
|
||||
|
||||
fn calculate_relay_message_size(message: &RelayMessage) -> usize {
|
||||
match message {
|
||||
RelayMessage::OK(result) => calculate_command_result_size(result),
|
||||
RelayMessage::Eose(str_ref)
|
||||
| RelayMessage::Event(str_ref, _)
|
||||
| RelayMessage::Notice(str_ref) => mem::size_of_val(message) + str_ref.as_bytes().len(),
|
||||
}
|
||||
}
|
||||
|
||||
fn filters_to_string(f: &Vec<Filter>) -> String {
|
||||
let mut cur_str = String::new();
|
||||
for filter in f {
|
||||
if let Ok(json) = filter.json() {
|
||||
if !cur_str.is_empty() {
|
||||
cur_str.push_str(", ");
|
||||
}
|
||||
cur_str.push_str(&json);
|
||||
}
|
||||
}
|
||||
|
||||
cur_str
|
||||
}
|
||||
@@ -7,6 +7,7 @@ pub struct Args {
|
||||
pub keys: Vec<Keypair>,
|
||||
pub light: bool,
|
||||
pub debug: bool,
|
||||
pub relay_debug: bool,
|
||||
|
||||
/// Enable when running tests so we don't panic on app startup
|
||||
pub tests: bool,
|
||||
@@ -24,6 +25,7 @@ impl Args {
|
||||
keys: vec![],
|
||||
light: false,
|
||||
debug: false,
|
||||
relay_debug: false,
|
||||
tests: false,
|
||||
use_keystore: true,
|
||||
dbpath: None,
|
||||
@@ -108,6 +110,8 @@ impl Args {
|
||||
res.relays.push(relay.clone());
|
||||
} else if arg == "--no-keystore" {
|
||||
res.use_keystore = false;
|
||||
} else if arg == "--relay-debug" {
|
||||
res.relay_debug = true;
|
||||
}
|
||||
|
||||
i += 1;
|
||||
|
||||
@@ -7,6 +7,7 @@ use notedeck::{
|
||||
|
||||
use enostr::RelayPool;
|
||||
use nostrdb::{Config, Ndb, Transaction};
|
||||
use notedeck_columns::ui::relay_debug::RelayDebugView;
|
||||
use std::cell::RefCell;
|
||||
use std::path::Path;
|
||||
use std::rc::Rc;
|
||||
@@ -80,6 +81,16 @@ impl eframe::App for Notedeck {
|
||||
|
||||
self.app_rect_handler.try_save_app_size(ctx);
|
||||
|
||||
if self.args.relay_debug {
|
||||
if self.pool.debug.is_none() {
|
||||
self.pool.use_debug();
|
||||
}
|
||||
|
||||
if let Some(debug) = &mut self.pool.debug {
|
||||
RelayDebugView::window(ctx, debug);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "profiling")]
|
||||
puffin_egui::profiler_window(ctx);
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ pub mod note;
|
||||
pub mod preview;
|
||||
pub mod profile;
|
||||
pub mod relay;
|
||||
pub mod relay_debug;
|
||||
pub mod side_panel;
|
||||
pub mod support;
|
||||
pub mod thread;
|
||||
|
||||
@@ -61,7 +61,7 @@ impl PostAction {
|
||||
}
|
||||
};
|
||||
|
||||
pool.send(&enostr::ClientMessage::event(note));
|
||||
pool.send(&enostr::ClientMessage::event(note)?);
|
||||
drafts.get_from_post_type(&self.post_type).clear();
|
||||
|
||||
Ok(())
|
||||
|
||||
@@ -195,7 +195,7 @@ mod preview {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Preview for EditProfileView<'a> {
|
||||
impl Preview for EditProfileView<'_> {
|
||||
type Prev = EditProfilePreivew;
|
||||
|
||||
fn preview(_cfg: PreviewConfig) -> Self::Prev {
|
||||
|
||||
173
crates/notedeck_columns/src/ui/relay_debug.rs
Normal file
173
crates/notedeck_columns/src/ui/relay_debug.rs
Normal file
@@ -0,0 +1,173 @@
|
||||
use egui::ScrollArea;
|
||||
use enostr::{RelayLogEvent, SubsDebug};
|
||||
|
||||
pub struct RelayDebugView<'a> {
|
||||
debug: &'a mut SubsDebug,
|
||||
}
|
||||
|
||||
impl<'a> RelayDebugView<'a> {
|
||||
pub fn new(debug: &'a mut SubsDebug) -> Self {
|
||||
Self { debug }
|
||||
}
|
||||
}
|
||||
|
||||
impl RelayDebugView<'_> {
|
||||
pub fn ui(&mut self, ui: &mut egui::Ui) {
|
||||
ScrollArea::vertical()
|
||||
.id_salt(ui.id().with("relays_debug"))
|
||||
.max_height(ui.max_rect().height() / 2.0)
|
||||
.show(ui, |ui| {
|
||||
ui.label("Active Relays:");
|
||||
for (relay_str, data) in self.debug.get_data() {
|
||||
egui::CollapsingHeader::new(format!(
|
||||
"{} {} {}",
|
||||
relay_str,
|
||||
format_total(&data.count),
|
||||
format_sec(&data.count)
|
||||
))
|
||||
.default_open(true)
|
||||
.show(ui, |ui| {
|
||||
ui.horizontal_wrapped(|ui| {
|
||||
for (i, sub_data) in data.sub_data.values().enumerate() {
|
||||
ui.label(format!(
|
||||
"Filter {} ({})",
|
||||
i + 1,
|
||||
format_sec(&sub_data.count)
|
||||
))
|
||||
.on_hover_cursor(egui::CursorIcon::Help)
|
||||
.on_hover_text(sub_data.filter.to_string());
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
ui.separator();
|
||||
egui::ComboBox::from_label("Show events from relay")
|
||||
.selected_text(
|
||||
self.debug
|
||||
.relay_events_selection
|
||||
.as_ref()
|
||||
.map_or(String::new(), |s| s.clone()),
|
||||
)
|
||||
.show_ui(ui, |ui| {
|
||||
let mut make_selection = None;
|
||||
for relay in self.debug.get_data().keys() {
|
||||
if ui
|
||||
.selectable_label(
|
||||
if let Some(s) = &self.debug.relay_events_selection {
|
||||
*s == *relay
|
||||
} else {
|
||||
false
|
||||
},
|
||||
relay,
|
||||
)
|
||||
.clicked()
|
||||
{
|
||||
make_selection = Some(relay.clone());
|
||||
}
|
||||
}
|
||||
if make_selection.is_some() {
|
||||
self.debug.relay_events_selection = make_selection
|
||||
}
|
||||
});
|
||||
let show_relay_evs =
|
||||
|ui: &mut egui::Ui, relay: Option<String>, events: Vec<RelayLogEvent>| {
|
||||
for ev in events {
|
||||
ui.horizontal_wrapped(|ui| {
|
||||
if let Some(r) = &relay {
|
||||
ui.label("relay").on_hover_text(r.clone());
|
||||
}
|
||||
match ev {
|
||||
RelayLogEvent::Send(client_message) => {
|
||||
ui.label("SEND: ");
|
||||
let msg = &match client_message {
|
||||
enostr::ClientMessage::Event { .. } => "Event",
|
||||
enostr::ClientMessage::Req { .. } => "Req",
|
||||
enostr::ClientMessage::Close { .. } => "Close",
|
||||
enostr::ClientMessage::Raw(_) => "Raw",
|
||||
};
|
||||
|
||||
if let Ok(json) = client_message.to_json() {
|
||||
ui.label(*msg).on_hover_text(json)
|
||||
} else {
|
||||
ui.label(*msg)
|
||||
}
|
||||
}
|
||||
RelayLogEvent::Recieve(e) => {
|
||||
ui.label("RECIEVE: ");
|
||||
match e {
|
||||
enostr::OwnedRelayEvent::Opened => ui.label("Opened"),
|
||||
enostr::OwnedRelayEvent::Closed => ui.label("Closed"),
|
||||
enostr::OwnedRelayEvent::Other(s) => {
|
||||
ui.label("Other").on_hover_text(s)
|
||||
}
|
||||
enostr::OwnedRelayEvent::Error(s) => {
|
||||
ui.label("Error").on_hover_text(s)
|
||||
}
|
||||
enostr::OwnedRelayEvent::Message(s) => {
|
||||
ui.label("Message").on_hover_text(s)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
ScrollArea::vertical()
|
||||
.id_salt(ui.id().with("events"))
|
||||
.show(ui, |ui| {
|
||||
if let Some(relay) = &self.debug.relay_events_selection {
|
||||
if let Some(data) = self.debug.get_data().get(relay) {
|
||||
show_relay_evs(ui, None, data.events.clone());
|
||||
}
|
||||
} else {
|
||||
for (relay, data) in self.debug.get_data() {
|
||||
show_relay_evs(ui, Some(relay.clone()), data.events.clone());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
self.debug.try_increment_stats();
|
||||
}
|
||||
|
||||
pub fn window(ctx: &egui::Context, debug: &mut SubsDebug) {
|
||||
let mut open = true;
|
||||
egui::Window::new("Relay Debugger")
|
||||
.open(&mut open)
|
||||
.show(ctx, |ui| {
|
||||
RelayDebugView::new(debug).ui(ui);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
fn format_sec(c: &enostr::TransferStats) -> String {
|
||||
format!(
|
||||
"⬇{} ⬆️{}",
|
||||
byte_to_string(c.down_sec_prior),
|
||||
byte_to_string(c.up_sec_prior)
|
||||
)
|
||||
}
|
||||
|
||||
fn format_total(c: &enostr::TransferStats) -> String {
|
||||
format!(
|
||||
"total: ⬇{} ⬆️{}",
|
||||
byte_to_string(c.down_total),
|
||||
byte_to_string(c.up_total)
|
||||
)
|
||||
}
|
||||
|
||||
const MB: usize = 1_048_576;
|
||||
const KB: usize = 1024;
|
||||
fn byte_to_string(b: usize) -> String {
|
||||
if b >= MB {
|
||||
let mbs = b as f32 / MB as f32;
|
||||
format!("{:.2} MB", mbs)
|
||||
} else if b >= KB {
|
||||
let kbs = b as f32 / KB as f32;
|
||||
format!("{:.2} KB", kbs)
|
||||
} else {
|
||||
format!("{} B", b)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user