about summary refs log tree commit diff
path: root/corgi_stats
diff options
context:
space:
mode:
Diffstat (limited to 'corgi_stats')
-rw-r--r--corgi_stats/src/main.rs101
-rw-r--r--corgi_stats/src/style.css37
2 files changed, 106 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) -> ! {
diff --git a/corgi_stats/src/style.css b/corgi_stats/src/style.css
new file mode 100644
index 0000000..5b3995d
--- /dev/null
+++ b/corgi_stats/src/style.css
@@ -0,0 +1,37 @@
+h1 {
+	font-family: sans-serif;
+}
+
+table {
+	border-collapse: collapse;
+	border: 2px solid gray;
+	margin: 1rem 0px;
+}
+
+tr {
+	background-color: white;
+}
+
+tbody>tr:nth-of-type(odd) {
+	background-color: cornsilk;
+}
+
+th,
+td {
+	border: 1px solid darkslateblue;
+	padding: 2px 3px;
+}
+
+thead th {
+	background-color: darksalmon;
+}
+
+th {
+	text-align: left;
+	padding: 4px 6px;
+	white-space: nowrap;
+}
+
+th.ttitle {
+	text-align: center;
+}
\ No newline at end of file