write metrics to the /host/logs

Signed-off-by: Valentyn Faychuk <valy@detee.ltd>
This commit is contained in:
Valentyn Faychuk 2024-11-29 16:12:27 +02:00
parent c2e751d893
commit 3c93b258f5
Signed by: valy
GPG Key ID: F1AB995E20FEADC5
9 changed files with 70 additions and 27 deletions

2
.cargo/config Normal file

@ -0,0 +1,2 @@
[net]
git-fetch-with-cli=true

@ -9,9 +9,11 @@ message NodeUpdate {
google.protobuf.Timestamp keepalive = 3; google.protobuf.Timestamp keepalive = 3;
uint64 mint_requests = 4; uint64 mint_requests = 4;
uint64 mints = 5; uint64 mints = 5;
uint64 ratls_conns = 6; uint64 mratls_conns = 6;
uint64 ratls_attacks = 7; uint64 quote_attacks = 7;
bool public = 8; bool public = 8;
uint64 restarts = 9;
uint64 disk_attacks = 10;
} }
message Keys { message Keys {

@ -2,6 +2,7 @@
use crate::solana::Client as SolClient; use crate::solana::Client as SolClient;
use dashmap::{DashMap, DashSet}; use dashmap::{DashMap, DashSet};
use std::time::{Duration, SystemTime}; use std::time::{Duration, SystemTime};
use crate::persistence::Logfile;
type IP = String; type IP = String;
pub const LOCALHOST: &str = "localhost"; pub const LOCALHOST: &str = "localhost";
@ -12,9 +13,11 @@ pub struct NodeInfo {
pub keepalive: SystemTime, pub keepalive: SystemTime,
pub mint_requests: u64, pub mint_requests: u64,
pub mints: u64, pub mints: u64,
pub ratls_conns: u64, pub mratls_conns: u64,
pub ratls_attacks: u64, pub quote_attacks: u64,
pub public: bool, pub public: bool,
pub restarts: u64,
pub disk_attacks: u64,
} }
impl NodeInfo { impl NodeInfo {
@ -25,8 +28,8 @@ impl NodeInfo {
} }
} }
if self.mint_requests > other_node.mint_requests if self.mint_requests > other_node.mint_requests
|| self.ratls_attacks > other_node.ratls_attacks || self.quote_attacks > other_node.quote_attacks
|| self.ratls_conns > other_node.ratls_conns || self.mratls_conns > other_node.mratls_conns
|| self.mints > other_node.mints || self.mints > other_node.mints
|| (self.public && !other_node.public) || (self.public && !other_node.public)
{ {
@ -34,6 +37,12 @@ impl NodeInfo {
} }
false false
} }
pub fn log(&self, ip: &IP) {
if let Err(e) = Logfile::append(&format!("{}: {:?}", ip, self)) {
println!("Could not log: {:?}", e);
}
}
} }
/// Keypair must already be known when creating a Store /// Keypair must already be known when creating a Store
@ -55,9 +64,11 @@ impl Store {
keepalive: SystemTime::now(), keepalive: SystemTime::now(),
mint_requests: 0, mint_requests: 0,
mints: 0, mints: 0,
ratls_conns: 0, mratls_conns: 0,
ratls_attacks: 0, quote_attacks: 0,
public: false, public: false,
restarts: 0,
disk_attacks: 0,
}, },
); );
store store
@ -86,18 +97,28 @@ impl Store {
pub fn increase_mint_requests(&self) { pub fn increase_mint_requests(&self) {
if let Some(mut localhost_info) = self.nodes.get_mut(LOCALHOST) { if let Some(mut localhost_info) = self.nodes.get_mut(LOCALHOST) {
localhost_info.mint_requests += 1; localhost_info.mint_requests += 1;
localhost_info.log(localhost_info.key());
} }
} }
pub fn increase_mints(&self) { pub fn increase_mints(&self) {
if let Some(mut localhost_info) = self.nodes.get_mut(LOCALHOST) { if let Some(mut localhost_info) = self.nodes.get_mut(LOCALHOST) {
localhost_info.mints += 1; localhost_info.mints += 1;
localhost_info.log(localhost_info.key());
} }
} }
pub fn increase_ratls_conns(&self) { pub fn increase_mratls_conns(&self) {
if let Some(mut localhost_info) = self.nodes.get_mut(LOCALHOST) { if let Some(mut localhost_info) = self.nodes.get_mut(LOCALHOST) {
localhost_info.ratls_conns += 1; localhost_info.mratls_conns += 1;
localhost_info.log(localhost_info.key());
}
}
pub fn increase_disk_attacks(&self) {
if let Some(mut localhost_info) = self.nodes.get_mut(LOCALHOST) {
localhost_info.disk_attacks += 1;
localhost_info.log(localhost_info.key());
} }
} }
@ -116,10 +137,7 @@ impl Store {
} }
/// This returns true if NodeInfo got modified. /// This returns true if NodeInfo got modified.
/// pub fn process_node_update(&self, (ip, mut node_info): (String, NodeInfo)) -> bool {
/// On a side note, there are two types of people in this world:
/// 1. Those that can extrapolate... WAT?
pub async fn process_node_update(&self, (ip, mut node_info): (String, NodeInfo)) -> bool {
if let Some(old_node) = self.nodes.get(&ip) { if let Some(old_node) = self.nodes.get(&ip) {
if !node_info.newer_than(&old_node) { if !node_info.newer_than(&old_node) {
return false; return false;
@ -127,6 +145,7 @@ impl Store {
node_info.public = node_info.public || old_node.public; node_info.public = node_info.public || old_node.public;
} }
println!("Inserting: {}, {:?}", ip, node_info); println!("Inserting: {}, {:?}", ip, node_info);
node_info.log(&ip);
self.nodes.insert(ip, node_info); self.nodes.insert(ip, node_info);
true true
} }
@ -153,6 +172,7 @@ impl Store {
pub fn remove_inactive_nodes(&self) { pub fn remove_inactive_nodes(&self) {
self.nodes.retain(|_, v| { self.nodes.retain(|_, v| {
// HACK: Check if it is possible to abuse network by corrupting system time
let age = let age =
SystemTime::now().duration_since(v.keepalive).unwrap_or(Duration::ZERO).as_secs(); SystemTime::now().duration_since(v.keepalive).unwrap_or(Duration::ZERO).as_secs();
age <= 600 age <= 600

@ -108,7 +108,7 @@ impl ConnManager {
} }
// update the entire network in case the information is new // update the entire network in case the information is new
if self.ds.process_node_update(update.clone().into()).await if self.ds.process_node_update(update.clone().into())
&& self.tx.send(update.clone()).is_err() && self.tx.send(update.clone()).is_err()
{ {
println!("tokio broadcast receivers had an issue consuming the channel"); println!("tokio broadcast receivers had an issue consuming the channel");

@ -15,9 +15,11 @@ impl From<(String, NodeInfo)> for NodeUpdate {
keepalive: Some(prost_types::Timestamp::from(info.keepalive)), keepalive: Some(prost_types::Timestamp::from(info.keepalive)),
mint_requests: info.mint_requests, mint_requests: info.mint_requests,
mints: info.mints, mints: info.mints,
ratls_conns: info.ratls_conns, mratls_conns: info.mratls_conns,
ratls_attacks: info.ratls_attacks, quote_attacks: info.quote_attacks,
public: info.public, public: info.public,
restarts: info.restarts,
disk_attacks: info.disk_attacks
} }
} }
} }
@ -44,9 +46,11 @@ impl From<NodeUpdate> for (String, NodeInfo) {
keepalive, keepalive,
mint_requests: val.mint_requests, mint_requests: val.mint_requests,
mints: val.mints, mints: val.mints,
ratls_conns: val.ratls_conns, mratls_conns: val.mratls_conns,
ratls_attacks: val.ratls_attacks, quote_attacks: val.quote_attacks,
public: val.public, public: val.public,
restarts: val.restarts,
disk_attacks: val.disk_attacks
}; };
(ip, self_info) (ip, self_info)
} }

@ -113,7 +113,7 @@ impl Update for MyServer {
&self, &self,
req: Request<Streaming<NodeUpdate>>, req: Request<Streaming<NodeUpdate>>,
) -> Result<Response<Self::GetUpdatesStream>, Status> { ) -> Result<Response<Self::GetUpdatesStream>, Status> {
self.ds.increase_ratls_conns(); self.ds.increase_mratls_conns();
let remote_ip = req.remote_addr().unwrap().ip().to_string(); let remote_ip = req.remote_addr().unwrap().ip().to_string();
let tx = self.tx.clone(); let tx = self.tx.clone();
let mut rx = self.tx.subscribe(); let mut rx = self.tx.subscribe();
@ -136,7 +136,7 @@ impl Update for MyServer {
// note that we don't set this node online, // note that we don't set this node online,
// as it can be behind NAT // as it can be behind NAT
} }
if update.ip != "127.0.0.1" && ds.process_node_update(update.clone().into()).await && tx.send(update.clone()).is_err() { if update.ip != "127.0.0.1" && ds.process_node_update(update.clone().into()) && tx.send(update.clone()).is_err() {
println!("tokio broadcast receivers had an issue consuming the channel"); println!("tokio broadcast receivers had an issue consuming the channel");
}; };
} }

@ -39,8 +39,8 @@ impl From<(String, datastore::NodeInfo)> for NodesResp {
joined_at, joined_at,
last_keepalive, last_keepalive,
mints: node_info.mints, mints: node_info.mints,
total_ratls_conns: node_info.ratls_conns, total_ratls_conns: node_info.mratls_conns,
ratls_attacks: node_info.ratls_attacks, ratls_attacks: node_info.quote_attacks,
public: node_info.public, public: node_info.public,
mint_requests: node_info.mint_requests, mint_requests: node_info.mint_requests,
} }
@ -63,12 +63,12 @@ struct MintReq {
async fn mint(ds: web::Data<Arc<Store>>, req: web::Json<MintReq>) -> impl Responder { async fn mint(ds: web::Data<Arc<Store>>, req: web::Json<MintReq>) -> impl Responder {
ds.increase_mint_requests(); ds.increase_mint_requests();
let result = let result =
actix_web::web::block(move || ds.mint(&req.into_inner().wallet).map_err(|e| e.to_string())) web::block(move || ds.mint(&req.into_inner().wallet).map_err(|e| e.to_string()))
.await .await
.unwrap(); // TODO: check if this can get a BlockingError .unwrap(); // TODO: check if this can get a BlockingError
match result { match result {
Ok(s) => HttpResponse::Ok().body(format!(r#"{{ "signature": "{s}"}}"#)), Ok(s) => HttpResponse::Ok().body(format!(r#"{{" signature": "{s} "}}"#)),
Err(e) => HttpResponse::InternalServerError().body(format!(r#"{{ "error": "{e}"}}"#)), Err(e) => HttpResponse::InternalServerError().body(format!(r#"{{ "error": "{e}" }}"#)),
} }
} }

@ -81,7 +81,7 @@ async fn main() {
let sol_client = get_sol_client().await; let sol_client = get_sol_client().await;
let ds = Arc::new(Store::init(sol_client)); let ds = Arc::new(Store::init(sol_client));
let (tx, mut _rx) = broadcast::channel(500); let (tx, _) = broadcast::channel(500);
let mut tasks = JoinSet::new(); let mut tasks = JoinSet::new();

@ -40,3 +40,18 @@ impl Data {
(keypair, pubkey) (keypair, pubkey)
} }
} }
const LOG_PATH: &str = "/host/logs";
pub struct Logfile {}
impl Logfile {
pub fn append(msg: &str) -> Result<(), Box<dyn std::error::Error>> {
use std::io::Write;
let mut file = std::fs::OpenOptions::new()
.append(true)
.open(LOG_PATH)?;
file.write_all(msg.as_bytes())?;
Ok(())
}
}