-
Notifications
You must be signed in to change notification settings - Fork 1
/
state_change.clj
124 lines (100 loc) · 4.14 KB
/
state_change.clj
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
(ns active.clojure.logger.state-change
"Facilities for logging state changes."
(:require [riemann.client :as riemann]
[taoensso.timbre :as timbre]
[active.clojure.config :as config]
[active.clojure.logger.riemann :as riemann-config]
[active.clojure.logger.internal :as internal]
[active.clojure.monad :as monad]
[active.clojure.record :refer [define-record-type]]))
;;;; Configuration
(def log-state-changes-command-config-setting
(config/setting :log-state-changes-command-config
"Monad command config for running state-change log commands."
;; TODO allow port/host settings
(config/one-of-range #{:riemann :events} :events)))
(def state-changes-config-default :events)
(defonce state-changes-config (atom state-changes-config-default))
(defn set-global-log-state-changes-config!
[scc]
(reset! state-changes-config scc))
(defn reset-global-log-state-changes-config!
"Reset to back to default, if the config equals `compare`."
[compare]
(swap! state-changes-config #(if (= % compare) state-changes-config-default %)))
(defn configure-state-changes-logging
"Returns an object that can be fed to
[[set-global-log-state-changes-config!]]."
[riemann-config desc]
(case desc
:events :events
:riemann (riemann-config/make-riemann-config riemann-config)))
;;;; Data definition and DSL
(define-record-type LogStateChange
(make-log-state-change namespace state ttl map)
log-state-change?
[^{:doc "String"}
;; in case this gets redirected to event log
namespace log-state-change-namespace
^{:doc "Arbitrary string, should be from finite set"}
state log-state-change-state
^{:doc "Floating-point number in seconds or `nil`."}
ttl log-state-change-ttl
^{:doc "Map with more data or `nil`. The context is a map that is merged
with the log context that's already active, if present."}
map log-state-change-map])
;;; Actions
; helper to avoid having to construct a merged map
(defmacro log-context-access
[?mp ?key]
`(or (get ~?mp ~?key)
(get timbre/*context* ~?key)))
; apply this before adding :metric, :ttl, :time etc.
(defn log-state-change-to-events!
[namespace state mp]
(internal/log-event!-internal "state"
namespace
:info
{:state state}
(delay
[(str "Changed state to "
state)])))
(defn log-state-change!-internal
[namespace state ttl mp]
(let [scconf @state-changes-config]
(case scconf
:events (log-state-change-to-events! namespace state mp)
(riemann-config/log-state-change-to-riemann! scconf state ttl mp))))
(defmacro log-state-change!
"Log a state change asynchronously (imperative version).
`?more`, if present, is a map with more properties."
([?context ?state]
`(internal/log-state-change!-internal ~(str *ns*) ~?state nil ~?context))
([?context ?state ?ttl]
`(internal/log-state-change!-internal ~(str *ns*) ~?state ~?ttl ~?context))
([?context ?state ?ttl ?mp]
`(internal/log-state-change!-internal ~(str *ns*) ~?state ~?ttl (merge ~?context ~?mp))))
(defmacro log-state-change
"Log a state change asynchronously (monadic version), constructed from the arguments.
`?ttl`, if present, is the time-to-live in seconds."
([?state]
`(make-log-state-change ~(str *ns*) ~?state nil nil))
([?state ?ttl]
`(make-log-state-change ~(str *ns*) ~?state ~?ttl nil))
([?state ?ttl ?mp]
`(make-log-state-change ~(str *ns*) ~?state ~?ttl ~?mp)))
;;;; Interpreter
(defn run-log-state-change
[run-any env mstate m]
(cond
(log-state-change? m)
(do
(log-state-change!-internal (log-state-change-namespace m)
(log-state-change-state m)
(log-state-change-ttl m)
(log-state-change-map m))
[nil mstate])
:else
monad/unknown-command))
(def log-state-changes-command-config
(monad/make-monad-command-config run-log-state-change {} {}))