diff options
Diffstat (limited to 'corgi_stats/src/main.rs')
-rw-r--r-- | corgi_stats/src/main.rs | 101 |
1 files changed, 69 insertions, 32 deletions
diff --git a/corgi_stats/src/main.rs b/corgi_stats/src/main.rs index 1097685..2e0c372 100644 --- a/corgi_stats/src/main.rs +++ b/corgi_stats/src/main.rs @@ -3,15 +3,19 @@ use std::time::Instant; use time::{Duration, OffsetDateTime}; // Thank you, cat, for optimizing my query -const TOP_TEN_ALL_TIME: &str = "SELECT reqs.cnt, agents.agent -FROM agents -JOIN ( - SELECT count(id) as cnt, agent_id - FROM requests - GROUP BY agent_id -) reqs -ON reqs.agent_id=agents.id -ORDER BY reqs.cnt DESC LIMIT 10;"; +const TOP_TEN_ALL_TIME: &str = "\ + SELECT reqs.cnt, agents.agent + FROM agents + JOIN ( + SELECT count(id) as cnt, agent_id + FROM requests + GROUP BY agent_id + ) reqs + ON reqs.agent_id=agents.id + ORDER BY reqs.cnt DESC LIMIT 10; +"; + +const STYLE: &'static str = include_str!("style.css"); fn main() { let db_path = std::env::var("CORGI_STATS_DB").ok(); @@ -25,13 +29,9 @@ fn main() { error_and_die(500, "database key not set"); }; - let mut body = String::new(); - let now = OffsetDateTime::now_utc(); let fifteen_ago = now - Duration::minutes(15); - let start = Instant::now(); - let query = "SELECT count(requests.id) AS request_count, agents.agent FROM requests \ INNER JOIN agents ON requests.agent_id = agents.id \ WHERE requests.timestamp > ?1 \ @@ -54,30 +54,67 @@ fn main() { .collect(); let sum_highest_five = highest_five.iter().fold(0, |acc, (count, _)| acc + count); - body.push_str("<p>In the last fifteen minutes:<br/><code><pre>"); - body.push_str("total | req/m | agent\n"); + println!("Content-Type: text/html\n"); + println!("<html>"); + #[rustfmt::skip] + println!("<head>\n\ + <title>corgi stats</title>\n\ + <style>\n{STYLE}\n</style>\n\ + </head>"); + + println!("<body>"); + println!("<h1>Corgi Stats :)</h1>"); + + #[rustfmt::skip] + println!("<table>\n\ + <thead>\n\ + \t<tr>\n\ + \t\t<th scope='row' colspan='3' class='ttitle'>Requests for the last 15 minutes</th>\n\ + \t</tr>\n\ + \t<tr>\n\ + \t\t<th># Req.</th>\n\ + \t\t<th>Req/min</th>\n\ + \t\t<th>Agent</th>\n\ + \t</tr>\n\ + </thead>\n<tbody>"); + for (count, agent) in &agents { - body.push_str(&format!( - "{count:<5} | {:<5.1} | {agent}\n", - *count as f32 / 15.0 - )); + #[rustfmt::skip] + println!("<tr>\n\ + \t<td>{count}</td>\n\ + \t<td>{:.1}</td>\n\ + \t<td>{agent}</td>\n\ + </tr>", + *count as f32 / 15.0); } - body.push_str("</pre></code></p>"); - body.push_str("<p>Highest ten all time requesters:<br/><code><pre>"); - body.push_str(" total | %of10 | agent\n"); - for (count, agent) in highest_five { - body.push_str(&format!( - " {count:<7} | {:<5.1} | {agent}\n", - (count as f32 / sum_highest_five as f32) * 100.0 - )); - } - body.push_str("</pre></code></p>"); + println!("</tbody>\n</table>"); - body.push_str(&format!("<p>took {}ms</p>", start.elapsed().as_millis())); + #[rustfmt::skip] + println!("<table>\n\ + <thead>\n\ + \t<tr>\n\ + \t\t<th scope='row' colspan='3' class='ttitle'>Top 10 User Agents All Time</th>\n\ + \t</tr>\n\ + \t<tr>\n\ + \t\t<th># Req.</th>\n\ + \t\t<th>Req/min</th>\n\ + \t\t<th>Agent</th>\n\ + \t</tr>\n\ + </thead>\n<tbody>"); - println!("Status: 200\nContent-Type: text/html\n"); - println!("{body}"); + // Finish what we started + println!("</body>\n</html>"); + + for (count, agent) in highest_five { + #[rustfmt::skip] + println!("<tr>\n\ + \t<td>{count}</td>\n\ + \t<td>{:.1}</td>\n\ + \t<td>{agent}</td>\n\ + </tr>", + (count as f32 / sum_highest_five as f32) * 100.0); + } } fn error_and_die<S: Into<String>>(status: u16, msg: S) -> ! { |