Skip to content

Instantly share code, notes, and snippets.

@danodic
Last active June 22, 2020 01:27
Show Gist options
  • Save danodic/4adb5f0c5439eff2101e23f2c9f818c3 to your computer and use it in GitHub Desktop.
Save danodic/4adb5f0c5439eff2101e23f2c9f818c3 to your computer and use it in GitHub Desktop.
A simple log lib using mutable data in clojure
(ns dev.danodic.log
"A simple module with mutable data structures. Used to create logs grouped
by discrete elements, like files. It was meant to be used as the logging
lib for rushbeat, but at this point I'm not sure if this is being used or
not. As it relies on refs, it is probably thread safe as well (did not
test this and at this point I'm a beginner at Clojure."
(:require [clj-time.local :as time])
(:gen-class))
; Stores the log entries
(def logs (ref {}))
; Stores the data from a single log entry
(defrecord LogEntry [logtype timestamp value])
; Some utilities functions
; THANKS_TO: j-g-faustus @ https://stackoverflow.com/a/3249777/5032148
(defn has-value?
"Will return the list of elements that match the value provided in the
collection provided as argument."
[coll value]
(some #(= value %) coll))
(defn contains-all?
"Will check if a list of values provided are contained inside the
collection passed as argument."
[coll values]
(every? #(contains? values %) coll))
(defn has-key?
"Will check if a given key is contained within a map."
[map value]
(contains? map value))
(defn- logtype-string
"Just converts a log type keyword to a string that can be used to print
the log entry."
[logtype]
(cond
(= logtype :info) "INFO"
(= logtype :fatal) "FATAL"
:else "UNKNOWN"))
(defn- create-log
"Creates an entry of LogEntry with information provided and the current
timestamp."
[logtype value]
(LogEntry. logtype (time/local-now) value))
(defn- log-string
"Will return the string representation of a given log entry."
[log]
(let [{logtype :logtype
timestamp :timestamp
value :value} log
str-logtype (logtype-string logtype)
str-timestamp (time/format-local-time timestamp :basic-date-time)]
(format "%s - %s: %s" str-timestamp str-logtype value)))
(defn- has-filename?
"Will check if the filename provided already have an entry in the main log
map."
[filename] (has-key? (deref logs) filename))
(defn- add-filename
"Will alter the main map with the logs and add an entry for the filename
provided with an empty vector inside a ref."
[filename]
(dosync
(alter logs into {filename (ref [])})))
(defn- get-filename
"Will return the vector with log entries for a given file name."
[filename]
(when-not (has-filename? filename) (add-filename filename))
(get (deref logs) filename))
(defn- log
"Will add a new log entry for the given filename."
[filename logtype value]
(let [file (get-filename filename)]
(dosync (alter file conj (create-log logtype value)))))
(defn info
"Will add a new log entry with type :info."
[filename value]
(log filename :info value))
(defn fatal
"Will add a new log entry with type :fatal."
[filename value]
(log filename :fatal value))
(defn get-logs
"Will return all logs for all files inside a map."
[]
(into {}
(for [[filename value] (seq (deref logs))]
{filename (mapv log-string (deref value))})))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment