Skip to content

Example: otplike Logging System #28

@pwhittin

Description

@pwhittin

Here's some code to implement a simple otplike logging system:

(ns otplike-log.log
  (:require [clj-time.core :as t]
            [clj-time.local :as l]
            [otplike.process :as process :refer [!]]))

(defn pad0
  [field-width n]
  (let [s (pr-str n)
        pad-count (- field-width (count s))
        pad-string (apply str (repeat pad-count "0"))]
    (str pad-string s)))

(def pad00 (partial pad0 2))

(def pad000 (partial pad0 3))

(defn get-now-str
  []
  (let [now (l/local-now)]
    (str
      (pad00 (t/year now)) "-" (pad00 (t/month now)) "-" (pad00 (t/day now))
      " "
      (pad00 (t/hour now)) ":" (pad00 (t/minute now)) ":" (pad00 (t/second now))
      "." (pad000 (t/milli now)))))

(defn get-space-delimited-values-string
  [values]
  (apply str (interpose " " values)))

(defn get-log-line
  [values]
  (str (get-now-str) ": " (get-space-delimited-values-string values) "\n"))

(process/proc-defn
  log-proc
  [log-line-fn]
  (process/receive!
    msg (do (log-line-fn msg)
          (recur log-line-fn))))

(defn create-log
  [log-fn]
  (let [log (process/spawn log-proc [(comp log-fn get-log-line)])]
    (fn
      [& values]
      (! log values))))

and here's a demo of using it:

(ns otplike-log.core
  (:require [otplike-log.log :as l])
  (:gen-class))

(defn doit
  [this-many-times moniker sleep-ms log]
  (doall (for [n (range this-many-times)]
           (do
             (log moniker n)
             (Thread/sleep sleep-ms)))))

(def doit-slow (partial doit 10 "slow" 1000))

(def doit-fast (partial doit 20 "fast" 500))

(defn log-to-file
  [log-file-spec]
  (fn
    [log-line]
    (spit log-file-spec log-line :append true)))

(defn example-1
  [log]
  (log
    "one"
    (+ 1 2)
    (apply str (interpose "," "three")))
  (doseq [log-message (range 10)]
    (log log-message)))

(defn example-2
  [log]
  (future (doit-fast log))
  (doit-slow log))

(defn -main
  [& args]
  (let [log (l/create-log (log-to-file "log.txt"))]
    (example-1 log)
    (example-2 log)))

Running "-main" produces something like:

2017-09-08 15:18:15.799: one 3 t,h,r,e,e
2017-09-08 15:18:15.801: 0
2017-09-08 15:18:15.801: 1
2017-09-08 15:18:15.802: 2
2017-09-08 15:18:15.803: 3
2017-09-08 15:18:15.803: 4
2017-09-08 15:18:15.804: 5
2017-09-08 15:18:15.804: 6
2017-09-08 15:18:15.805: 7
2017-09-08 15:18:15.806: 8
2017-09-08 15:18:15.806: 9
2017-09-08 15:18:15.807: fast 0
2017-09-08 15:18:15.807: slow 0
2017-09-08 15:18:16.301: fast 1
2017-09-08 15:18:16.801: slow 1
2017-09-08 15:18:16.802: fast 2
2017-09-08 15:18:17.302: fast 3
2017-09-08 15:18:17.801: slow 2
2017-09-08 15:18:17.803: fast 4
2017-09-08 15:18:18.303: fast 5
2017-09-08 15:18:18.802: slow 3
2017-09-08 15:18:18.803: fast 6
2017-09-08 15:18:19.304: fast 7
2017-09-08 15:18:19.803: slow 4
2017-09-08 15:18:19.804: fast 8
2017-09-08 15:18:20.305: fast 9
2017-09-08 15:18:20.803: slow 5
2017-09-08 15:18:20.805: fast 10
2017-09-08 15:18:21.305: fast 11
2017-09-08 15:18:21.804: slow 6
2017-09-08 15:18:21.806: fast 12
2017-09-08 15:18:22.307: fast 13
2017-09-08 15:18:22.804: slow 7
2017-09-08 15:18:22.807: fast 14
2017-09-08 15:18:23.307: fast 15
2017-09-08 15:18:23.805: slow 8
2017-09-08 15:18:23.808: fast 16
2017-09-08 15:18:24.308: fast 17
2017-09-08 15:18:24.805: slow 9
2017-09-08 15:18:24.809: fast 18
2017-09-08 15:18:25.309: fast 19

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions