Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@frankiesardo
Created January 4, 2017 17:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save frankiesardo/c6b074a3e442e2d49503d849a495c2b9 to your computer and use it in GitHub Desktop.
Save frankiesardo/c6b074a3e442e2d49503d849a495c2b9 to your computer and use it in GitHub Desktop.
(ns tinylog.core
(:require [clj-http.client :as http]
[cheshire.core :as json]
[clojure.core.async :as async]))
(defprotocol Logger
(log [this msg]))
(defn map* [f logger]
(reify Logger
(log [this msg] (log logger (f msg)))))
;; Convenience fns. You probably want trace, debug and failure as well. And add :timestamp, :host etc.
(defn info [logger service desc]
(log logger {:service service :level :info :description desc}))
(defn warn [logger service desc]
(log logger {:service service :level :warn :description desc}))
(defn error [logger service desc]
(log logger {:service service :level :error :description desc}))
(defrecord AsyncLogger [channel] Logger
(log [this msg] (async/go (async/>! channel msg))))
;; Parse logs
(defn batch [in out max-time max-count]
(async/go-loop [buf [] t (async/timeout max-time)]
(let [[v p] (async/alts! [in t])]
(cond
(= p t)
(do
(async/>! out buf)
(recur [] (async/timeout max-time)))
(nil? v)
(if (seq buf)
(async/>! out buf))
(== (count buf) (dec max-count))
(do
(async/>! out (conj buf v))
(recur [] (async/timeout max-time)))
:else
(recur (conj buf v) t)))))
(defn send-logs [in config]
(let [out (async/chan)
_ (batch in out 1000 10)]
(async/go-loop []
(let [msg (async/<! out)]
(http/post "elastic.domain" (json/encode msg))))))
;; Use logs
(defn update-profile [logger user]
(if (some? user)
(info logger ::profile.update user)
(warn logger ::profile.update {:reason "Not found"})))
(defn handle-user-request [logger user-id]
(let [logger* (map* #(assoc % :user-id user-id) logger)
user (comment (get-user-from-db))]
(update-profile logger* user)))
;; Test logs
(require '[clojure.test :refer :all])
(defrecord TestLogger [logs] Logger
(log [this msg] (swap! logs conj msg)))
(deftest logs-correct-data
(let [{:keys [logs] :as logger} (TestLogger. (atom []))]
(handle-user-request logger 123)
(is (= [[::profile.update 123]] (map (juxt :service :user-id) @logs)))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment