blackwater0.0.8Pretty logging for SQL queries in JDBC for Clojure dependencies
| (this space intentionally left almost blank) | ||||||||||||||||||
(ns black.water.jdbc (:require [clojure.java.jdbc :as j] [robert.hooke :refer [add-hook]] [clojure.java.jdbc.sql :as s] [clansi.core :refer :all] [black.water.log :refer [log-sql]] [clj-time.core :as time])) | |||||||||||||||||||
(def extract-transaction? #'j/extract-transaction?) | |||||||||||||||||||
Hook for c.j.j query, destructures sql from arguments and times the run-time, sending the results to the log fn. | (defn query-hook [f & args] (let [start (time/now) result (apply f args) end (time/now) time-taken (time/in-millis (time/interval start end))] (log-sql (first (second args)) time-taken) result)) | ||||||||||||||||||
Hook for c.j.j execute! | (defn execute-hook [f & args] (let [start (time/now) result (apply f args) end (time/now) time-taken (time/in-millis (time/interval start end))] (log-sql (clojure.string/join " | " (second args)) time-taken) result)) | ||||||||||||||||||
Hook for c.j.j insert! | (defn insert-hook [f & args] (let [start (time/now) [db table & options] args [transaction? maps-or-cols-and-values-etc] (extract-transaction? options) stmts (apply s/insert table maps-or-cols-and-values-etc) result (apply f args) end (time/now) time-taken (time/in-millis (time/interval start end))] (log-sql (clojure.string/join " | " (first stmts)) time-taken) result)) | ||||||||||||||||||
decorate c.j.j/query, wraps the fn var. | (defn decorate-query! [] (add-hook #'j/query #'query-hook)) | ||||||||||||||||||
decorate c.j.j/insert!, wraps the fn var. | (defn decorate-insert! [] (add-hook #'j/insert! #'insert-hook)) | ||||||||||||||||||
decorate c.j.j/execute!, wraps the fn var. | (defn decorate-execute! [] (add-hook #'j/execute! #'execute-hook)) | ||||||||||||||||||
Hooks into clojure.java.jdbc to log queries, inserts, and execute | (defn decorate-cjj! [] (decorate-query!) (decorate-insert!) (decorate-execute!)) | ||||||||||||||||||
(ns black.water.korma (:require [clojure.java.jdbc :as j] [robert.hooke :refer [add-hook]] [korma.db :as kdb] [korma.core :as kc] [clansi.core :refer :all] [black.water.log :refer [log-sql]] [clj-time.core :as time])) | |||||||||||||||||||
Hook for korma, mercifully the library has a universal, singular function where all queries eventually end up. <3 | (defn korma-hook [f & args] (let [start (time/now) result (apply f args) end (time/now) time-taken (time/in-millis (time/interval start end))] (log-sql (:sql-str (first args)) time-taken) result)) | ||||||||||||||||||
Hooks into Korma to log SQL that gets executed. | (defn decorate-korma! [] (add-hook #'kdb/exec-sql #'korma-hook)) | ||||||||||||||||||
(ns black.water.log (:require [clansi.core :refer :all] [clj-time.core :as time])) | |||||||||||||||||||
Color global variables, rebind as thou wilt. | (def sql-color :green) (def time-color :red) | ||||||||||||||||||
(def logga nil) | |||||||||||||||||||
(defn set-logger! [fun] (alter-var-root (var logga) (fn [f] fun))) | |||||||||||||||||||
(defn sanitize [sql] (let [single-line (apply str (replace {\newline " "} sql))] (clojure.string/replace single-line #" {2,}" " "))) | |||||||||||||||||||
Given the sql string and the milliseconds it took to execute, print a (possibly) colorized readout of the string and the millis. | (defn log-sql [sql millis] (let [clean-sql (sanitize sql) formatted (str (style clean-sql sql-color) "| took:" (style millis time-color) "ms")] (if (and logga (fn? logga)) (logga clean-sql millis) (println formatted)))) | ||||||||||||||||||