changeset 45:90a4e4589d5e

Refactor logs query parameter handling
author Lewin Bormann <lbo@spheniscida.de>
date Tue, 19 Jul 2022 20:48:01 -0700
parents e7e91f288868
children 746d8278aa31
files src/logsdb.rs src/main.rs
diffstat 2 files changed, 64 insertions(+), 64 deletions(-) [+]
line wrap: on
line diff
--- a/src/logsdb.rs	Tue Jul 19 20:18:25 2022 -0700
+++ b/src/logsdb.rs	Tue Jul 19 20:48:01 2022 -0700
@@ -15,6 +15,13 @@
 
 pub struct LogsDBSession<'p, DB: sqlx::Database>(pub &'p mut sqlx::pool::PoolConnection<DB>);
 
+pub struct LogsQueryContext {
+    pub domain: Option<String>,
+    pub from: OffsetDateTime,
+    pub to: OffsetDateTime,
+    pub tz_offset: i64,
+}
+
 impl<'p> LogsDBSession<'p, Sqlite> {
     pub async fn log_request<
         S1: AsRef<str>,
@@ -103,15 +110,12 @@
         Ok(())
     }
 
-    pub async fn query_visits_sessions_counts<S: AsRef<str>>(
+    pub async fn query_visits_sessions_counts(
         &mut self,
-        from: OffsetDateTime,
-        to: OffsetDateTime,
-        tz_offset: Option<i64>,
-        domainpattern: Option<S>,
+        ctx: &LogsQueryContext,
     ) -> Result<(Vec<String>, Vec<u32>, Vec<u32>), Error> {
-        let domain = domainpattern.as_ref().map(AsRef::as_ref).unwrap_or("%");
-        let tz_offset = tz_offset.unwrap_or(0);
+        let domain = ctx.domain.as_ref().map(String::as_str).unwrap_or("%");
+        let tz_offset = ctx.tz_offset;
         let mut results = sqlx::query(
             r#"
 SELECT DATE(atime + ?, 'unixepoch') AS rqdate, COUNT(requestlog.id) AS rqcount, sesscount
@@ -128,9 +132,9 @@
         .bind(tz_offset)
         .bind(domain)
         .bind(tz_offset)
-        .bind(from.unix_timestamp())
+        .bind(ctx.from.unix_timestamp())
         .bind(tz_offset)
-        .bind(to.unix_timestamp())
+        .bind(ctx.to.unix_timestamp())
         .bind(domain)
         .fetch(&mut *self.0);
 
@@ -159,12 +163,9 @@
 
     pub async fn query_top_countries(
         &mut self,
-        from: OffsetDateTime,
-        to: OffsetDateTime,
-        tz_offset: Option<i64>,
-        domain: Option<&str>,
+        ctx: &LogsQueryContext,
     ) -> Result<Vec<(String, i64)>, Error> {
-        let tz_offset = tz_offset.unwrap_or(0);
+        let tz_offset = ctx.tz_offset;
         let result = sqlx::query(
             r#"
 SELECT origin_country, COUNT(*) AS count
@@ -174,24 +175,25 @@
 ORDER BY count DESC;"#,
         )
         .bind(tz_offset)
-        .bind(from.unix_timestamp())
+        .bind(ctx.from.unix_timestamp())
         .bind(tz_offset)
-        .bind(to.unix_timestamp())
-        .bind(domain.unwrap_or("%"))
-        .fetch_all(&mut *self.0).await?;
+        .bind(ctx.to.unix_timestamp())
+        .bind(ctx.domain.as_ref().map(String::as_str).unwrap_or("%"))
+        .fetch_all(&mut *self.0)
+        .await?;
 
-        Ok(result.into_iter().map(|row| (row.get(0), row.get(1))).collect())
+        Ok(result
+            .into_iter()
+            .map(|row| (row.get(0), row.get(1)))
+            .collect())
     }
 
     pub async fn query_top_paths(
         &mut self,
-        from: OffsetDateTime,
-        to: OffsetDateTime,
-        tz_offset: Option<i64>,
-        domainpattern: Option<&str>,
+        ctx: &LogsQueryContext,
         n: i64,
     ) -> Result<Vec<(String, i64)>, Error> {
-        let tz_offset = tz_offset.unwrap_or(0);
+        let tz_offset = ctx.tz_offset;
         let result = sqlx::query(
             r#"
 SELECT path, COUNT(*) AS pathcount
@@ -202,10 +204,10 @@
 LIMIT ?;"#,
         )
         .bind(tz_offset)
-        .bind(from.unix_timestamp())
+        .bind(ctx.from.unix_timestamp())
         .bind(tz_offset)
-        .bind(to.unix_timestamp())
-        .bind(domainpattern.unwrap_or("%"))
+        .bind(ctx.to.unix_timestamp())
+        .bind(ctx.domain.as_ref().map(String::as_str).unwrap_or("%"))
         .bind(n)
         .fetch(&mut *self.0);
 
@@ -226,12 +228,9 @@
 
     pub async fn query_requests_per_session(
         &mut self,
-        from: OffsetDateTime,
-        to: OffsetDateTime,
-        tz_offset: Option<i64>,
-        domainpattern: Option<&str>,
+        ctx: &LogsQueryContext,
     ) -> Result<Vec<(String, f32)>, Error> {
-        let tz_offset = tz_offset.unwrap_or(0);
+        let tz_offset = ctx.tz_offset;
         let result = sqlx::query(
             r#"
 SELECT d, CAST(nreq AS REAL)/nses
@@ -251,15 +250,15 @@
 ORDER BY d ASC"#,
         )
         .bind(tz_offset)
-        .bind(from.unix_timestamp())
+        .bind(ctx.from.unix_timestamp())
         .bind(tz_offset)
-        .bind(to.unix_timestamp())
-        .bind(domainpattern.unwrap_or("%"))
+        .bind(ctx.to.unix_timestamp())
+        .bind(ctx.domain.as_ref().map(String::as_str).unwrap_or("%"))
         .bind(tz_offset)
-        .bind(from.unix_timestamp())
+        .bind(ctx.from.unix_timestamp())
         .bind(tz_offset)
-        .bind(to.unix_timestamp())
-        .bind(domainpattern.unwrap_or("%"))
+        .bind(ctx.to.unix_timestamp())
+        .bind(ctx.domain.as_ref().map(String::as_str).unwrap_or("%"))
         .fetch(&mut *self.0);
 
         Ok(result
--- a/src/main.rs	Tue Jul 19 20:18:25 2022 -0700
+++ b/src/main.rs	Tue Jul 19 20:48:01 2022 -0700
@@ -127,7 +127,7 @@
 #[derive(Default)]
 struct ChartOptions {
     typ: String,               // bar/line/etc.
-    indexAxis: Option<String>, // x/y
+    index_axis: Option<String>, // x/y
     stack: Option<String>,
 }
 
@@ -144,10 +144,11 @@
     }
     let datasets: Vec<Value> = values
         .iter()
-        .map(|((name, val))| {
+        .map(|(name, val)| {
             json!({
                 "label": name,
                 "data": val,
+                // TODO: these colors don't work well: differently for different chart types
                 "borderColor": colors,
                 "backgroundColor": colors,
             })
@@ -161,7 +162,7 @@
         },
         "options": {
             "scales": { "y": { "beginAtZero": true }},
-            "indexAxis": opt.indexAxis,
+            "indexAxis": opt.index_axis,
             "stack": opt.stack.as_ref().map(String::as_str),
         },
     });
@@ -189,7 +190,7 @@
     mut config_conn: Connection<ConfigDB>,
     lig: LoggedInGuard,
     flash: Option<FlashMessage<'_>>,
-    domain: Option<&str>,
+    domain: Option<String>,
     from: Option<&str>,
     duration: Option<&str>,
 ) -> Template {
@@ -231,36 +232,39 @@
             0
         }
     };
+
+    let ctx = logsdb::LogsQueryContext {
+        domain: domain.clone(),
+        from: begin,
+        to: end,
+        tz_offset,
+    };
+
     let vissess = match LogsDBSession(&mut conn)
-        .query_visits_sessions_counts(begin, end, Some(tz_offset), domain)
+        .query_visits_sessions_counts(&ctx)
         .await
     {
-        Ok((dates, visits, sessions)) => {
-            create_chart(
-                dates,
-                vec![("Visits".into(), visits), ("Sessions".into(), sessions)],
-                &ChartOptions {
-                    typ: "line".into(),
-                    ..ChartOptions::default()
-                },
-            )
-            .to_string()
-        }
+        Ok((dates, visits, sessions)) => create_chart(
+            dates,
+            vec![("Visits".into(), visits), ("Sessions".into(), sessions)],
+            &ChartOptions {
+                typ: "line".into(),
+                ..ChartOptions::default()
+            },
+        )
+        .to_string(),
         Err(e) => {
             error!("Couldn't build chart: {}", e);
             "undefined".to_string()
         }
     };
-    let toppaths = match LogsDBSession(&mut conn)
-        .query_top_paths(begin, end, Some(tz_offset), domain, 10)
-        .await
-    {
+    let toppaths = match LogsDBSession(&mut conn).query_top_paths(&ctx, 10).await {
         Ok(tp) => create_chart(
             tp.iter().map(|(p, c)| p).collect(),
             vec![("Top Pages".into(), tp.iter().map(|(p, c)| c).collect())],
             &ChartOptions {
                 typ: "bar".into(),
-                indexAxis: Some("y".into()),
+                index_axis: Some("y".into()),
                 ..ChartOptions::default()
             },
         )
@@ -271,7 +275,7 @@
         }
     };
     let reqbyses = match LogsDBSession(&mut conn)
-        .query_requests_per_session(begin, end, Some(tz_offset), domain)
+        .query_requests_per_session(&ctx)
         .await
     {
         Ok(rs) => create_chart(
@@ -291,10 +295,7 @@
             "undefined".to_string()
         }
     };
-    let sesbycountry = match LogsDBSession(&mut conn)
-        .query_top_countries(begin, end, Some(tz_offset), domain)
-        .await
-    {
+    let sesbycountry = match LogsDBSession(&mut conn).query_top_countries(&ctx).await {
         Ok(rs) => create_chart(
             rs.iter().map(|(c, n)| c).collect(),
             vec![(