Skip to content

Instantly share code, notes, and snippets.

@benton
Created November 1, 2017 20:59
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 benton/08b0a0c2de8d0bc91d639a1af7c88145 to your computer and use it in GitHub Desktop.
Save benton/08b0a0c2de8d0bc91d639a1af7c88145 to your computer and use it in GitHub Desktop.
Process output of track-icmp-state.sh
#!/usr/bin/env boot
; Converts track-imcp-state.sh output into minute-by-minute CSV datapoints
; Requirements: Java 8 and Boot
; Use "brew install boot-clj", or see https://github.com/boot-clj/boot
; Best used with only one day's worth of logs at a time from STDIN, like this:
; cat [output.log] | grep [DATE] | ./process-track-ip-state.clj > [DATE].csv
(set-env! :dependencies '[[clj-time "0.14.0"]])
(require '[clj-time.core :as t])
(require '[clj-time.format :as f])
(def initial-status "up")
(def line-matcher
#"\s*Connection .* ((up|down)) at (\d+)-(\d+)-(\d+) (\d+):(\d+):(\d+)\s*.*")
(defn midnight-the-day-of
"returns a date-time representing midnight on the day of the input time"
[time]
(f/parse (f/unparse
(f/formatters :date-hour-minute-second)
(t/date-midnight (t/year time) (t/month time) (t/day time)))))
(defn event-from-fields
"returns a tuple of [date-time, status] from the given list of fields"
[[status year month day hour min sec]]
(let [numeric-fields (map #(Integer. %) [year month day hour min sec])
date-time (apply t/date-time numeric-fields)]
[date-time status]))
(def previous-event (atom nil))
(defn process-line
"turns a log line into a pair of events based on the line and previous-event"
[line]
(let [fields (rest (rest (re-matches line-matcher line)))]
(if (empty? fields) nil
(let [new-event (event-from-fields fields)
old-event (or @previous-event
[(midnight-the-day-of (first new-event))
initial-status])]
(reset! previous-event new-event)
[old-event new-event]))))
(defn print-event!
[[time status]]
(printf "%s,%s,%d\n"
(f/unparse (f/formatter "yyyy-MM-dd") time)
(f/unparse (f/formatter "HH:mm:ss") time)
(if (= status "up") 1 0)))
(defn print-events!
"prints two lines of CSV to STDOUT based on the pair of input events"
[[[start-time start-status] [end-time end-status]]]
(if (and start-time end-time)
(do
(print-event! [start-time start-status])
(print-event! [(t/plus end-time (t/seconds -1)) start-status]))))
(defn -main [& args]
(reset! previous-event nil)
(doseq [ln (line-seq (java.io.BufferedReader. *in*))]
(print-events! (process-line ln)))
(let [today (first @previous-event)
next-midnight (t/plus (midnight-the-day-of today) (t/days 1))
last-event [next-midnight (last @previous-event)]]
(print-events! [@previous-event last-event])))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment