aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOscar Najera <hi@oscarnajera.com>2025-02-09 20:05:48 +0100
committerOscar Najera <hi@oscarnajera.com>2025-02-09 20:05:48 +0100
commit5db6afef2702a9ad0e175df8675dee4607d8476f (patch)
tree323aade86b52da60515df63c79078eb3e5e1de45
parent87ef3a1635aae064bfcfac0be532b9904bdd927d (diff)
downloadscratch-5db6afef2702a9ad0e175df8675dee4607d8476f.tar.gz
scratch-5db6afef2702a9ad0e175df8675dee4607d8476f.tar.bz2
scratch-5db6afef2702a9ad0e175df8675dee4607d8476f.zip
plot site visits
-rw-r--r--webstats/queries.sql11
-rw-r--r--webstats/server.lisp32
-rw-r--r--webstats/stats.paren18
3 files changed, 60 insertions, 1 deletions
diff --git a/webstats/queries.sql b/webstats/queries.sql
index 2a3f762..5e16da0 100644
--- a/webstats/queries.sql
+++ b/webstats/queries.sql
@@ -19,3 +19,14 @@ DROP TABLE IF EXISTS STATS
-- Insert a data point
INSERT INTO STATS (click, page, referrer, ip, user_agent, title)
VALUES (:click, :page, :referer, :ip, :user_agent, :title)
+
+
+-- name: activity-stats
+-- timeseries of activity
+SELECT
+ (timestamp / 600) * 600 AS time,
+ count(*)
+FROM
+ STATS
+GROUP BY
+ 1;
diff --git a/webstats/server.lisp b/webstats/server.lisp
index 44dbe89..6c74b3e 100644
--- a/webstats/server.lisp
+++ b/webstats/server.lisp
@@ -1,4 +1,4 @@
-(ql:quickload '(hunchentoot spinneret cl-yesql cl-yesql/sqlite parenscript))
+(ql:quickload '(hunchentoot spinneret cl-yesql cl-yesql/sqlite parenscript cl-json))
(defpackage :webstats
(:use :common-lisp :hunchentoot :spinneret))
@@ -96,3 +96,33 @@
(:input :type "text" :name "title")
(:input :type "submit" :value "submit" :name "submit"))))
))
+
+(hunchentoot:define-easy-handler (metric :uri "/metric.json") (q)
+ (setf (hunchentoot:content-type*) "application/json")
+ (sqlite:with-open-database (db "test.db")
+ (let ((series (activity-stats db)))
+ (cl-json:encode-json-to-string
+ (apply #'mapcar #'list series)))))
+
+(hunchentoot:define-easy-handler (graphs :uri "/graphs") ()
+ (with-html-string
+ (:doctype)
+ (:html
+ (:head (:title "hu yu ipi")
+ (:meta :charset "utf-8")
+ (:link :rel "stylesheet" :href "/webstats/static/uPlot.min.css")
+ (:script :async t :src "/webstats/static/uPlot.iife.min.js" :type "text/javascript")
+ (:script :async t :src "/stats/stats.js" :type "text/javascript")
+ (:script :async t :src "http://127.0.0.1:8095/skewer"))
+ (:body
+ (:h1 "great graph stats")
+ (:div :id "graph")
+ (:script
+ (:raw
+ (ps:ps
+ (add-event-listener
+ "load"
+ (lambda ()
+ (ps:chain (fetch "/stats/metric.json")
+ (then #'response-to-json)
+ (then #'plot)))))))))))
diff --git a/webstats/stats.paren b/webstats/stats.paren
index b9d3974..4721272 100644
--- a/webstats/stats.paren
+++ b/webstats/stats.paren
@@ -38,6 +38,24 @@
((@ r text))))
(then (@ console log)))))
+(defun response-to-json (response)
+ (if (@ response ok)
+ (chain response (json))
+ (throw (new (-error "not 2XX resp")))))
+
+(defun plot (data)
+ (new
+ (u-plot
+ (create
+ :title "Site activity visits"
+ :width 450
+ :height 400
+ :cursor (create sync (create key "moo"))
+ :series (list (create label "Time")
+ (create label "visits" stroke "red")))
+ data
+ (chain document (get-element-by-id "graph")))))
+
(add-event-listener
"load"
(lambda ()