mirror of
https://github.com/mikedilger/gossip.git
synced 2024-09-30 00:41:42 +00:00
Track how many bytes are read and display on stats page
This commit is contained in:
parent
1cf520fcf2
commit
3ce38ed9ba
18
Cargo.lock
generated
18
Cargo.lock
generated
@ -1613,14 +1613,17 @@ dependencies = [
|
|||||||
"dirs",
|
"dirs",
|
||||||
"eframe",
|
"eframe",
|
||||||
"egui_extras",
|
"egui_extras",
|
||||||
|
"encoding_rs",
|
||||||
"futures",
|
"futures",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"hex",
|
"hex",
|
||||||
"http",
|
"http",
|
||||||
|
"humansize",
|
||||||
"image",
|
"image",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"linkify",
|
"linkify",
|
||||||
"memoize",
|
"memoize",
|
||||||
|
"mime",
|
||||||
"nostr-types",
|
"nostr-types",
|
||||||
"parking_lot",
|
"parking_lot",
|
||||||
"qrcode",
|
"qrcode",
|
||||||
@ -1756,6 +1759,15 @@ version = "1.0.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421"
|
checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "humansize"
|
||||||
|
version = "2.1.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6cb51c9a029ddc91b07a787f1d86b53ccfa49b0e86688c946ebe8d3555685dd7"
|
||||||
|
dependencies = [
|
||||||
|
"libm",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hyper"
|
name = "hyper"
|
||||||
version = "0.14.24"
|
version = "0.14.24"
|
||||||
@ -2000,6 +2012,12 @@ dependencies = [
|
|||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libm"
|
||||||
|
version = "0.2.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "348108ab3fba42ec82ff6e9564fc4ca0247bdccdc68dd8af9764bbc79c3c8ffb"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libsqlite3-sys"
|
name = "libsqlite3-sys"
|
||||||
version = "0.25.2"
|
version = "0.25.2"
|
||||||
|
@ -18,14 +18,17 @@ dashmap = "5.4"
|
|||||||
dirs = "4.0"
|
dirs = "4.0"
|
||||||
eframe = { version = "0.21", features = [ "dark-light", "persistence" ] }
|
eframe = { version = "0.21", features = [ "dark-light", "persistence" ] }
|
||||||
egui_extras = { version = "0.21", features = [ "image", "svg", "tracing" ] }
|
egui_extras = { version = "0.21", features = [ "image", "svg", "tracing" ] }
|
||||||
|
encoding_rs = "0.8"
|
||||||
futures = "0.3"
|
futures = "0.3"
|
||||||
futures-util = "0.3"
|
futures-util = "0.3"
|
||||||
hex = "0.4"
|
hex = "0.4"
|
||||||
http = "0.2"
|
http = "0.2"
|
||||||
|
humansize = "2.1"
|
||||||
image = { version = "0.24", features = [ "png", "jpeg" ] }
|
image = { version = "0.24", features = [ "png", "jpeg" ] }
|
||||||
lazy_static = "1.4"
|
lazy_static = "1.4"
|
||||||
linkify = "0.9"
|
linkify = "0.9"
|
||||||
memoize = "0.4"
|
memoize = "0.4"
|
||||||
|
mime = "0.3"
|
||||||
nostr-types = { git = "https://github.com/mikedilger/nostr-types" }
|
nostr-types = { git = "https://github.com/mikedilger/nostr-types" }
|
||||||
parking_lot = "0.12"
|
parking_lot = "0.12"
|
||||||
qrcode = { git = "https://github.com/mikedilger/qrcode-rust" }
|
qrcode = { git = "https://github.com/mikedilger/qrcode-rust" }
|
||||||
|
@ -186,6 +186,8 @@ impl Fetcher {
|
|||||||
|
|
||||||
let bytes = maybe_bytes?;
|
let bytes = maybe_bytes?;
|
||||||
|
|
||||||
|
GLOBALS.bytes_read.fetch_add(bytes.len(), Ordering::Relaxed);
|
||||||
|
|
||||||
let cache_file = GLOBALS.fetcher.cache_file(&url);
|
let cache_file = GLOBALS.fetcher.cache_file(&url);
|
||||||
|
|
||||||
// Write to the file
|
// Write to the file
|
||||||
|
@ -11,7 +11,7 @@ use crate::signer::Signer;
|
|||||||
use nostr_types::{Event, Id, Profile, PublicKeyHex, RelayUrl};
|
use nostr_types::{Event, Id, Profile, PublicKeyHex, RelayUrl};
|
||||||
use rusqlite::Connection;
|
use rusqlite::Connection;
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
use std::sync::atomic::{AtomicBool, AtomicU32};
|
use std::sync::atomic::{AtomicBool, AtomicU32, AtomicUsize};
|
||||||
use tokio::sync::{broadcast, mpsc, Mutex, RwLock};
|
use tokio::sync::{broadcast, mpsc, Mutex, RwLock};
|
||||||
|
|
||||||
/// Only one of these is ever created, via lazy_static!, and represents
|
/// Only one of these is ever created, via lazy_static!, and represents
|
||||||
@ -80,6 +80,8 @@ pub struct Globals {
|
|||||||
pub status_message: RwLock<String>,
|
pub status_message: RwLock<String>,
|
||||||
|
|
||||||
pub pull_following_merge: AtomicBool,
|
pub pull_following_merge: AtomicBool,
|
||||||
|
|
||||||
|
pub bytes_read: AtomicUsize,
|
||||||
}
|
}
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
@ -112,6 +114,7 @@ lazy_static! {
|
|||||||
pixels_per_point_times_100: AtomicU32::new(139), // 100 dpi, 1/72th inch => 1.38888
|
pixels_per_point_times_100: AtomicU32::new(139), // 100 dpi, 1/72th inch => 1.38888
|
||||||
status_message: RwLock::new("Welcome to Gossip. Status messages will appear here. Click them to dismiss them.".to_owned()),
|
status_message: RwLock::new("Welcome to Gossip. Status messages will appear here. Click them to dismiss them.".to_owned()),
|
||||||
pull_following_merge: AtomicBool::new(true),
|
pull_following_merge: AtomicBool::new(true),
|
||||||
|
bytes_read: AtomicUsize::new(0),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ use crate::globals::GLOBALS;
|
|||||||
use crate::people::DbPerson;
|
use crate::people::DbPerson;
|
||||||
use dashmap::mapref::entry::Entry;
|
use dashmap::mapref::entry::Entry;
|
||||||
use nostr_types::{Metadata, Nip05, PublicKeyHex, RelayUrl, Unixtime};
|
use nostr_types::{Metadata, Nip05, PublicKeyHex, RelayUrl, Unixtime};
|
||||||
|
use std::sync::atomic::Ordering;
|
||||||
|
|
||||||
// This updates the people map and the database with the result
|
// This updates the people map and the database with the result
|
||||||
pub async fn validate_nip05(person: DbPerson) -> Result<(), Error> {
|
pub async fn validate_nip05(person: DbPerson) -> Result<(), Error> {
|
||||||
@ -183,5 +184,7 @@ async fn fetch_nip05(user: &str, domain: &str) -> Result<Nip05, Error> {
|
|||||||
.header("Host", domain)
|
.header("Host", domain)
|
||||||
.send();
|
.send();
|
||||||
let response = nip05_future.await?;
|
let response = nip05_future.await?;
|
||||||
Ok(response.json::<Nip05>().await?)
|
let bytes = response.bytes().await?;
|
||||||
|
GLOBALS.bytes_read.fetch_add(bytes.len(), Ordering::Relaxed);
|
||||||
|
Ok(serde_json::from_slice(&bytes)?)
|
||||||
}
|
}
|
||||||
|
@ -6,13 +6,18 @@ use crate::db::DbRelay;
|
|||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
use crate::globals::GLOBALS;
|
use crate::globals::GLOBALS;
|
||||||
use base64::Engine;
|
use base64::Engine;
|
||||||
|
use encoding_rs::{Encoding, UTF_8};
|
||||||
use futures::{SinkExt, StreamExt};
|
use futures::{SinkExt, StreamExt};
|
||||||
use futures_util::stream::{SplitSink, SplitStream};
|
use futures_util::stream::{SplitSink, SplitStream};
|
||||||
use http::Uri;
|
use http::Uri;
|
||||||
|
use mime::Mime;
|
||||||
use nostr_types::{
|
use nostr_types::{
|
||||||
ClientMessage, EventKind, Filter, IdHex, IdHexPrefix, PublicKeyHex, PublicKeyHexPrefix,
|
ClientMessage, EventKind, Filter, IdHex, IdHexPrefix, PublicKeyHex, PublicKeyHexPrefix,
|
||||||
RelayInformationDocument, RelayUrl, Unixtime,
|
RelayInformationDocument, RelayUrl, Unixtime,
|
||||||
};
|
};
|
||||||
|
use reqwest::Response;
|
||||||
|
use std::borrow::Cow;
|
||||||
|
use std::sync::atomic::Ordering;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use subscription::Subscriptions;
|
use subscription::Subscriptions;
|
||||||
use tokio::net::TcpStream;
|
use tokio::net::TcpStream;
|
||||||
@ -98,6 +103,7 @@ impl Minion {
|
|||||||
return Err(Error::UrlHasEmptyHostname);
|
return Err(Error::UrlHasEmptyHostname);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Read NIP-11 information
|
||||||
let request_nip11_future = reqwest::Client::builder()
|
let request_nip11_future = reqwest::Client::builder()
|
||||||
.timeout(std::time::Duration::new(30, 0))
|
.timeout(std::time::Duration::new(30, 0))
|
||||||
.redirect(reqwest::redirect::Policy::none())
|
.redirect(reqwest::redirect::Policy::none())
|
||||||
@ -109,9 +115,8 @@ impl Minion {
|
|||||||
.header("Host", host)
|
.header("Host", host)
|
||||||
.header("Accept", "application/nostr+json")
|
.header("Accept", "application/nostr+json")
|
||||||
.send();
|
.send();
|
||||||
|
let response = request_nip11_future.await?;
|
||||||
// Read NIP-11 information
|
match Self::text_with_charset(response, "utf-8").await {
|
||||||
match request_nip11_future.await?.text().await {
|
|
||||||
Ok(text) => match serde_json::from_str::<RelayInformationDocument>(&text) {
|
Ok(text) => match serde_json::from_str::<RelayInformationDocument>(&text) {
|
||||||
Ok(nip11) => {
|
Ok(nip11) => {
|
||||||
tracing::info!("{}: {}", &self.url, nip11);
|
tracing::info!("{}: {}", &self.url, nip11);
|
||||||
@ -239,6 +244,8 @@ impl Minion {
|
|||||||
}
|
}
|
||||||
}?;
|
}?;
|
||||||
|
|
||||||
|
GLOBALS.bytes_read.fetch_add(ws_message.len(), Ordering::Relaxed);
|
||||||
|
|
||||||
tracing::trace!("{}: Handling message", &self.url);
|
tracing::trace!("{}: Handling message", &self.url);
|
||||||
match ws_message {
|
match ws_message {
|
||||||
WsMessage::Text(t) => {
|
WsMessage::Text(t) => {
|
||||||
@ -918,4 +925,33 @@ impl Minion {
|
|||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This replictes reqwest Response text_with_charset to handle decoding
|
||||||
|
// whatever charset they used into UTF-8, as well as counting the bytes.
|
||||||
|
async fn text_with_charset(
|
||||||
|
response: Response,
|
||||||
|
default_encoding: &str,
|
||||||
|
) -> Result<String, Error> {
|
||||||
|
let content_type = response
|
||||||
|
.headers()
|
||||||
|
.get(reqwest::header::CONTENT_TYPE)
|
||||||
|
.and_then(|value| value.to_str().ok())
|
||||||
|
.and_then(|value| value.parse::<Mime>().ok());
|
||||||
|
let encoding_name = content_type
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|mime| mime.get_param("charset").map(|charset| charset.as_str()))
|
||||||
|
.unwrap_or(default_encoding);
|
||||||
|
let encoding = Encoding::for_label(encoding_name.as_bytes()).unwrap_or(UTF_8);
|
||||||
|
let full = response.bytes().await?;
|
||||||
|
GLOBALS.bytes_read.fetch_add(full.len(), Ordering::Relaxed);
|
||||||
|
let (text, _, _) = encoding.decode(&full);
|
||||||
|
if let Cow::Owned(s) = text {
|
||||||
|
return Ok(s);
|
||||||
|
}
|
||||||
|
unsafe {
|
||||||
|
// decoding returned Cow::Borrowed, meaning these bytes
|
||||||
|
// are already valid utf8
|
||||||
|
Ok(String::from_utf8_unchecked(full.to_vec()))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,15 @@
|
|||||||
use super::GossipUi;
|
use super::GossipUi;
|
||||||
|
use crate::globals::GLOBALS;
|
||||||
use eframe::egui;
|
use eframe::egui;
|
||||||
use egui::{Context, Ui};
|
use egui::{Context, Ui};
|
||||||
|
use humansize::{format_size, DECIMAL};
|
||||||
|
use std::sync::atomic::Ordering;
|
||||||
|
|
||||||
pub(super) fn update(_app: &mut GossipUi, _ctx: &Context, _frame: &mut eframe::Frame, ui: &mut Ui) {
|
pub(super) fn update(_app: &mut GossipUi, _ctx: &Context, _frame: &mut eframe::Frame, ui: &mut Ui) {
|
||||||
ui.label("STATS PAGE - Coming Soon".to_string());
|
ui.label("STATS PAGE - Coming Soon".to_string());
|
||||||
|
|
||||||
|
ui.label(format!(
|
||||||
|
"BYTES READ: {}",
|
||||||
|
format_size(GLOBALS.bytes_read.load(Ordering::Relaxed), DECIMAL)
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user