Skip to content

Commit

Permalink
Metrics fixes.
Browse files Browse the repository at this point in the history
  • Loading branch information
cryptoquick committed Nov 13, 2023
1 parent 92e6a36 commit 1db840d
Showing 1 changed file with 113 additions and 54 deletions.
167 changes: 113 additions & 54 deletions src/carbonado/metrics.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::{collections::BTreeMap, path::Path, time::SystemTime};

use anyhow::Result;
use chrono::{DateTime, Utc};
use chrono::{DateTime, Duration, NaiveDate, Utc};
use serde::{Deserialize, Serialize};
use walkdir::WalkDir;

Expand All @@ -10,6 +10,9 @@ pub struct MetricsResponse {
bytes: u64,
bytes_by_day: BTreeMap<String, u64>,
bitcoin_wallets_by_day: BTreeMap<String, usize>,
signet_wallets_by_day: BTreeMap<String, usize>,
testnet_wallets_by_day: BTreeMap<String, usize>,
regtest_wallets_by_day: BTreeMap<String, usize>,
wallets_by_network: BTreeMap<String, usize>,
}

Expand All @@ -23,38 +26,18 @@ pub fn metrics(dir: &Path) -> Result<MetricsResponse> {
response.wallets_by_network.insert("total".to_string(), 0);

let mut total_wallets = 0;
let mut day_prior = None;

for entry in WalkDir::new(dir) {
let entry = entry?;
let filename = entry.file_name().to_string_lossy().to_string();
let metadata = entry.metadata()?;
let day = metadata.created()?;
let day = round_system_time_to_day(day);
let day_created = metadata.modified()?; // TODO: .created();
let day = round_datetime_to_day(day_created.into());

if metadata.is_file() {
response.bytes += metadata.len();

let bytes_total_day_prior = if let Some(dp) = &day_prior {
response.bytes_by_day.get(dp).unwrap_or(&0).to_owned()
} else {
0
};

let bitcoin_wallets_total_day_prior = if let Some(dp) = day_prior {
response
.bitcoin_wallets_by_day
.get(&dp)
.unwrap_or(&0)
.to_owned()
} else {
0
};

*response
.bytes_by_day
.entry(day.clone())
.or_insert(bytes_total_day_prior) += metadata.len();
*response.bytes_by_day.entry(day.clone()).or_insert(0) += metadata.len();

if filename
== "bitcoin-6075e9716c984b37840f76ad2b50b3d1b98ed286884e5ceba5bcc8e6b74988d3.c15"
Expand All @@ -66,7 +49,7 @@ pub fn metrics(dir: &Path) -> Result<MetricsResponse> {
*response
.bitcoin_wallets_by_day
.entry(day.clone())
.or_insert(bitcoin_wallets_total_day_prior) += 1;
.or_insert(0) += 1;
}

if filename
Expand All @@ -76,6 +59,10 @@ pub fn metrics(dir: &Path) -> Result<MetricsResponse> {
.wallets_by_network
.get_mut("testnet")
.unwrap_or(&mut 0) += 1;
*response
.testnet_wallets_by_day
.entry(day.clone())
.or_insert(0) += 1;
}

if filename
Expand All @@ -85,6 +72,10 @@ pub fn metrics(dir: &Path) -> Result<MetricsResponse> {
.wallets_by_network
.get_mut("signet")
.unwrap_or(&mut 0) += 1;
*response
.signet_wallets_by_day
.entry(day.clone())
.or_insert(0) += 1;
}

if filename
Expand All @@ -94,6 +85,10 @@ pub fn metrics(dir: &Path) -> Result<MetricsResponse> {
.wallets_by_network
.get_mut("regtest")
.unwrap_or(&mut 0) += 1;
*response
.regtest_wallets_by_day
.entry(day.clone())
.or_insert(0) += 1;
}

if filename == "bitcoin-6075e9716c984b37840f76ad2b50b3d1b98ed286884e5ceba5bcc8e6b74988d3.c15"
Expand All @@ -104,8 +99,6 @@ pub fn metrics(dir: &Path) -> Result<MetricsResponse> {
total_wallets += 1;
}
}

day_prior = Some(day);
}

*response
Expand All @@ -122,26 +115,27 @@ pub fn metrics(dir: &Path) -> Result<MetricsResponse> {
);
let end_day: DateTime<Utc> = SystemTime::now().into();
let end_day = round_datetime_to_day(end_day);

let mut d = 0;

loop {
let day_prior = start_day + Duration::days(d - 1);
let start_day = start_day + Duration::days(d);
let day_prior = start_day - Duration::days(1);
let day_prior = round_datetime_to_day(day_prior);
let day = round_datetime_to_day(start_day + Duration::days(d));
let day = round_datetime_to_day(start_day);

let bytes_day_prior = {
let mut bytes_day_prior = {
response
.bytes_by_day
.get(&day_prior)
.unwrap_or(&0)
.to_owned()
};

response
*response
.bytes_by_day
.entry(day.clone())
.and_modify(|b| *b += bytes_day_prior)
.or_insert(bytes_day_prior);
.get_mut(&day)
.unwrap_or(&mut bytes_day_prior) = bytes_day_prior;

let bitcoin_wallets_day_prior = {
response
Expand All @@ -157,6 +151,48 @@ pub fn metrics(dir: &Path) -> Result<MetricsResponse> {
.and_modify(|w| *w += bitcoin_wallets_day_prior)
.or_insert(bitcoin_wallets_day_prior);

let testnet_wallets_day_prior = {
response
.testnet_wallets_by_day
.get(&day_prior)
.unwrap_or(&0)
.to_owned()
};

response
.testnet_wallets_by_day
.entry(day.clone())
.and_modify(|w| *w += testnet_wallets_day_prior)
.or_insert(testnet_wallets_day_prior);

let signet_wallets_day_prior = {
response
.signet_wallets_by_day
.get(&day_prior)
.unwrap_or(&0)
.to_owned()
};

response
.signet_wallets_by_day
.entry(day.clone())
.and_modify(|w| *w += signet_wallets_day_prior)
.or_insert(signet_wallets_day_prior);

let regtest_wallets_day_prior = {
response
.regtest_wallets_by_day
.get(&day_prior)
.unwrap_or(&0)
.to_owned()
};

response
.regtest_wallets_by_day
.entry(day.clone())
.and_modify(|w| *w += regtest_wallets_day_prior)
.or_insert(regtest_wallets_day_prior);

if day == end_day {
break;
} else {
Expand All @@ -168,13 +204,16 @@ pub fn metrics(dir: &Path) -> Result<MetricsResponse> {
}

pub fn metrics_csv(metrics: MetricsResponse) -> String {
let lines = vec![vec![
"Wallet",
"Wallet Count",
"Bytes Total",
"Day",
"Bitcoin Wallets by Day",
"Bytes by Day",
let mut lines = vec![vec![
"Wallet".to_owned(),
"Wallet Count".to_owned(),
"Bytes Total".to_owned(),
"Day".to_owned(),
"Bitcoin Wallets by Day".to_owned(),
"Testnet Wallets by Day".to_owned(),
"Signet Wallets by Day".to_owned(),
"Regtest Wallets by Day".to_owned(),
"Bytes by Day".to_owned(),
]];

for (day, bitcoin_wallets) in metrics.bitcoin_wallets_by_day {
Expand All @@ -186,7 +225,7 @@ pub fn metrics_csv(metrics: MetricsResponse) -> String {
metrics
.wallets_by_network
.get("bitcoin")
.unwrap()
.expect("network is defined")
.to_string(),
);
line.push(metrics.bytes.to_string());
Expand All @@ -198,7 +237,7 @@ pub fn metrics_csv(metrics: MetricsResponse) -> String {
metrics
.wallets_by_network
.get("testnet")
.unwrap()
.expect("network is defined")
.to_string(),
);
line.push("".to_owned());
Expand All @@ -210,7 +249,7 @@ pub fn metrics_csv(metrics: MetricsResponse) -> String {
metrics
.wallets_by_network
.get("signet")
.unwrap()
.expect("network is defined")
.to_string(),
);
line.push("".to_owned());
Expand All @@ -222,7 +261,7 @@ pub fn metrics_csv(metrics: MetricsResponse) -> String {
metrics
.wallets_by_network
.get("regtest")
.unwrap()
.expect("network is defined")
.to_string(),
);
line.push("".to_owned());
Expand All @@ -236,20 +275,40 @@ pub fn metrics_csv(metrics: MetricsResponse) -> String {

line.push(day.clone());
line.push(bitcoin_wallets.to_string());
line.push(metrics.bytes_by_day.get(&day).unwrap().to_string())
line.push(
metrics
.testnet_wallets_by_day
.get(&day)
.unwrap_or(&0)
.to_string(),
);
line.push(
metrics
.signet_wallets_by_day
.get(&day)
.unwrap_or(&0)
.to_string(),
);
line.push(
metrics
.regtest_wallets_by_day
.get(&day)
.unwrap_or(&0)
.to_string(),
);
line.push(metrics.bytes_by_day.get(&day).unwrap_or(&0).to_string());

lines.push(line);
}

let lines: Vec<String> = lines.iter().map(|line| line.join(",")).collect();
lines.join("\n")
}

fn round_system_time_to_day(system_time: SystemTime) -> String {
// Convert SystemTime to a Chrono DateTime
let datetime: DateTime<Utc> = system_time.into();

// Round down to the nearest day (00:00:00)
let rounded = datetime.date_naive().and_hms_opt(0, 0, 0).unwrap();

// Format the date as a string in "YYYY-MM-DD" format
fn round_datetime_to_day(datetime: DateTime<Utc>) -> String {
let rounded = datetime
.date_naive()
.and_hms_opt(0, 0, 0)
.expect("valid time");
rounded.format("%Y-%m-%d").to_string()
}

0 comments on commit 1db840d

Please sign in to comment.