Skip to content

Instantly share code, notes, and snippets.

@MarinPostma
Created March 24, 2020 08:16
Show Gist options
  • Save MarinPostma/955ef5c0a30a4e989c3fa17c05940524 to your computer and use it in GitHub Desktop.
Save MarinPostma/955ef5c0a30a4e989c3fa17c05940524 to your computer and use it in GitHub Desktop.
use std::collections::VecDeque;
use std::time::Instant;
use std::time::{SystemTime, UNIX_EPOCH};
use tokio::select;
use tokio::stream::StreamExt;
use tokio::time::{self, Duration};
#[derive(Debug)]
struct Website {
pub url: String,
pub interval: Duration,
last_active: Option<Duration>,
up: Option<bool>,
logs: VecDeque<Log>,
}
impl PartialEq for Website {
fn eq(&self, other: &Self) -> bool {
self.url == other.url
}
}
impl Eq for Website {}
impl std::hash::Hash for Website {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.url.hash(state);
}
}
#[derive(Debug)]
struct Log {
pub status: reqwest::StatusCode,
pub timestamp: Duration,
pub request_time: Duration,
}
async fn make_req(url: &str) -> Log {
let begin_time = Instant::now();
let resp = reqwest::get(url).await.unwrap();
Log {
status: resp.status(),
request_time: begin_time.elapsed(),
timestamp: SystemTime::now()
.duration_since(UNIX_EPOCH)
.expect("error computing time"),
}
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let matches = clap::App::new("monitron")
.author("mposmta, postma.marin@protonmail.com")
.version("0.1")
.about("Monitors website metrics, with user defined specs")
.arg(
clap::Arg::with_name("add_monitor")
.short('a')
.long("add")
.required(true)
.multiple(true)
.number_of_values(2)
.help("add a website to monitor, with an interval in millis")
.value_names(&["url", "interval"]),
)
.get_matches();
let mut logs = tokio::stream::StreamMap::new();
for pair in matches
.values_of("add_monitor")
.unwrap()
.collect::<Vec<&str>>()
.chunks(2)
{
let url = pair[0].to_string();
let interval = Duration::from_millis(pair[1].parse()?);
let site = Website {
url,
interval,
up: None,
last_active: None,
logs: VecDeque::new(),
};
logs.insert(
site,
time::interval(site.interval).map(move |_| make_req(&site.url)),
);
}
loop {
select! {
Some(event) = logs.next() => {
println!("here");
},
else => break,
};
}
Ok(())
}
/*
error[E0599]: no method named `next` found for struct `tokio::stream::stream_map::StreamMap<Website, tokio::stream::map::Map<tokio::time::interval::Interval, [closure@src/main.rs:86:47: 86:75 site:_]>>` in the current scope
--> src/main.rs:91:32
|
91 | Some(event) = logs.next() => {
| ^^^^ method not found in `tokio::stream::stream_map::StreamMap<Website, tokio::stream::map::Map<tokio::time::interval::Interval, [closure@src/main.rs:86:47: 86:75 site:_]>>`
|
= note: the method `next` exists but the following trait bounds were not satisfied:
`tokio::stream::stream_map::StreamMap<Website, tokio::stream::map::Map<tokio::time::interval::Interval, [closure@src/main.rs:86:47: 86:75 site:_]>> : tokio::stream::StreamExt`
error[E0599]: no method named `poll` found for struct `std::pin::Pin<&mut _>` in the current scope
--> src/main.rs:90:9
|
90 | / select! {
91 | | Some(event) = logs.next() => {
92 | | println!("here");
93 | | },
94 | | else => break,
95 | | };
| |__________^ method not found in `std::pin::Pin<&mut _>`
|
= note: `fut` is a function, perhaps you wish to call it
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment