|
7 | 7 | [compojure.route :as cjr] |
8 | 8 | [clj-time.core :as time] |
9 | 9 | [clj-time.coerce :as time-coerce] |
| 10 | + [clj-time.format :as time-format] |
10 | 11 | [clojure.core.match :as cmatch] |
11 | 12 | [clojure.core.reducers :as r] |
12 | 13 | [environ.core :as env] |
13 | 14 | [manifold.deferred :as md] |
14 | 15 | [manifold.time :as mt] |
15 | 16 | [taoensso.timbre :as timbre] |
16 | | - [twitter.oauth :as tw-auth] |
17 | | - [twitter.api.restful :as tw-api] |
18 | 17 | [prometheus.core :as prometheus]) |
19 | 18 | (:import |
20 | 19 | [java.util.concurrent TimeoutException]) |
|
32 | 31 | (def timeout-after (mt/seconds 10)) |
33 | 32 |
|
34 | 33 | (def state (atom {:alarm-state ::good |
| 34 | + :statuses nil |
35 | 35 | :last-update (time/now)})) |
36 | 36 |
|
37 | 37 | (def store (atom nil)) |
|
83 | 83 | :travis travis-status |
84 | 84 | :github github-status}))) |
85 | 85 |
|
86 | | -(defn red-alert? |
| 86 | +(defn down? |
87 | 87 | [{:keys [github codecov travis]}] |
88 | 88 | (if (and (= status-io-good codecov) |
89 | 89 | (= status-io-good travis) |
|
99 | 99 | [::bad ::bad] ::dark |
100 | 100 | [::bad ::good] ::brightening)) |
101 | 101 |
|
102 | | -(defn setup-twitter |
103 | | - [env] |
104 | | - (let [{:keys [api-key api-secret access-token access-token-secret]} env |
105 | | - token (tw-auth/make-oauth-creds api-key |
106 | | - api-secret |
107 | | - access-token |
108 | | - access-token-secret)] |
109 | | - token)) |
110 | | - |
111 | | -(defn tweet! |
112 | | - [message] |
113 | | - (timbre/info "tweeting" message) |
114 | | - (let [token (setup-twitter env/env)] |
115 | | - (-> |
116 | | - (md/chain |
117 | | - ;; this should also be able to timeout |
118 | | - (md/future (tw-api/statuses-update :oauth-creds token :params {:status message})) |
119 | | - (fn [_] (timbre/info "tweeted"))) |
120 | | - (md/catch |
121 | | - Exception |
122 | | - (fn [exc] (timbre/warn "exception while tweeting:" exc)))))) |
123 | | - |
124 | | -(defn tweet-alert! |
125 | | - [status] |
126 | | - (timbre/info "tweet alert" status) |
127 | | - (condp = status |
128 | | - ::darkening (tweet! "expect problems @chriswwolfe") |
129 | | - ::brightening (tweet! "should be back to normal @chriswwolfe") |
130 | | - ;; else |
131 | | - (md/success-deferred ::no-tweet))) |
132 | | - |
133 | 102 | (defn alert! |
134 | 103 | [ctx statuses] |
135 | 104 | (let [{s0 :alarm-state} ctx |
136 | | - s1 (red-alert? statuses) |
137 | | - tweet-status (get-next-state s0 s1)] |
138 | | - (md/chain |
139 | | - (tweet-alert! tweet-status) |
140 | | - (fn [arg] |
141 | | - (-> ctx |
142 | | - (assoc :alarm-state s1) |
143 | | - (assoc :last-update (time/now))))))) |
| 105 | + s1 (down? statuses) |
| 106 | + status (get-next-state s0 s1)] |
| 107 | + (-> ctx |
| 108 | + (assoc :alarm-state s1) |
| 109 | + (assoc :statuses statuses) |
| 110 | + (assoc :last-update (time/now))))) |
144 | 111 |
|
145 | 112 | (defn run-world! |
146 | 113 | [] |
|
149 | 116 | (get-parse-statuses!) |
150 | 117 | #(alert! @state %) |
151 | 118 | (fn [new-world] |
| 119 | + (timbre/info (:statuses new-world)) |
152 | 120 | (reset! state new-world) |
153 | 121 | (timbre/infof "s0=%s, s1=%s" (:alarm-state old-state) (:alarm-state @state)))))) |
154 | 122 |
|
|
179 | 147 | (register-metrics) |
180 | 148 | (reset! store))) |
181 | 149 |
|
| 150 | +(def built-in-formatter (time-format/formatters :basic-date-time)) |
| 151 | + |
| 152 | +(defn status-handler |
| 153 | + [_req] |
| 154 | + (let [{:keys [statuses last-update alarm-state]} @state |
| 155 | + body {:statuses statuses |
| 156 | + :alarm-state alarm-state |
| 157 | + :last-update (time-coerce/to-date last-update)} |
| 158 | + as-json (json/generate-string body {:pretty true})] |
| 159 | + {:status 200 |
| 160 | + :headers {"content-type" "text/plain"} |
| 161 | + :body as-json})) |
| 162 | + |
182 | 163 | (cjc/defroutes app |
| 164 | + (cjc/GET "/" [] status-handler) |
183 | 165 | (cjc/GET "/metrics" [] metrics-handler) |
184 | 166 | (cjr/not-found "404: Not Found")) |
185 | 167 |
|
186 | 168 | (defn -main |
187 | 169 | [& args] |
188 | 170 | (let [port (Integer/parseInt (first args))] |
| 171 | + (prn port) |
189 | 172 | (init-metrics!) |
190 | 173 | (http/start-server app {:port port :host "0.0.0.0"}) |
191 | 174 | (keep-checking (mt/minutes 2)) |
|
0 commit comments