Contents

Timelines from Emacs org-mode

Contents

I use Emacs org-mode for all of my notes and todos. My workflow for handling outages and other immediate issues is:

  1. Create and clock-in an entry for the problem.
  2. Work the issue and keep brief timestamped notes under that entry.
  3. Generate a timeline afterward.

Here’s a fictional example, typical of a hotline:

* Trouble Tickets
** CLOSED RT00012345: HIGH PRIORITY!!1! teh app is down, please do the necessary
   - State "CLOSED"     from "STARTED"    [2010-09-29 Wed 19:16]
   - State "STARTED"    from "WAITING"    [2010-09-29 Wed 19:00]
     - [2010-09-29 Wed 19:00] received callback from user
     - [2010-09-29 Wed 19:05] user reports inet, phone & cable tv down
     - [2010-09-29 Wed 19:06] confirmed issue resolved
     - [2010-09-29 Wed 19:16] closed... PEBCAK
   - State "WAITING"    from "STARTED"    [2010-09-29 Wed 18:10] 
     pending callback from reporting user
   - State "STARTED"    from "TODO"       [2010-09-29 Wed 18:00]
     - [2010-09-29 Wed 18:00] started checkout
     - [2010-09-29 Wed 18:01] confirmed- no downtime scheduled
       per http://gdc (global downtime calendar)
     - [2010-09-29 Wed 18:01] confirmed- no open issues reported by NOC
       per x5900 hotline, spoke w/Ketur S.
     - [2010-09-29 Wed 18:02] confirmed- no events in site survey heatmap
     - [2010-09-29 Wed 18:04] app farm checkout OKAY, local avg RTT 11ms
     - [2010-09-29 Wed 18:06] called originating user, left vmail.
     :CLOCK:
     CLOCK: [2010-09-29 Wed 19:00]--[2010-09-29 Wed 19:16]
     CLOCK: [2010-09-29 Wed 18:00]--[2010-09-29 Wed 18:10]
     :END:

And the resulting timeline looks like:

* CLOSED RT00012345: HIGH PRIORITY!!1! teh app is down, please do the necessary
     - [2010-09-29 Wed 18:00] started checkout
     - [2010-09-29 Wed 18:01] confirmed- no downtime scheduled
     - [2010-09-29 Wed 18:01] confirmed- no open issues reported by NOC
     - [2010-09-29 Wed 18:02] confirmed- no events in site survey heatmap
     - [2010-09-29 Wed 18:04] app farm checkout OKAY, local avg RTT 11ms
     - [2010-09-29 Wed 18:06] called originating user, left vmail.
     - [2010-09-29 Wed 19:00] received callback from user
     - [2010-09-29 Wed 19:05] user reports inet, phone & cable tv down
     - [2010-09-29 Wed 19:06] confirmed issue resolved
     - [2010-09-29 Wed 19:16] closed... PEBCAK

To get this, I define a format for note and a quick keyboard shortcut for it:

(push '("!" "Timestamped note to current clock" item (clock) "  - %U %?n%in")
  org-capture-templates)
(global-set-key (kbd "C-c o !") '(lambda () (interactive) (org-capture nil "!")))

and a routine that generates a timeline from the current heading

(defun rel-org-maybe-copy-ts-item (buf)
  "Copy current line to specified buffer if line is a timestamped item"
  (when (save-excursion
          (beginning-of-line 1)
          (skip-chars-forward "t ")
          (looking-at (concat "- " org-ts-regexp3)))
    (let ((l (buffer-substring (line-beginning-position) (line-end-position))))
      (with-current-buffer (get-buffer-create buf)
        (insert l "n")))))

(defun rel-org-extract-timeline ()
  "Iterate over the current heading collecting the first line of
  timestamped items into a sorted timeline in a buffer"
  (interactive)
  (save-excursion
    (org-back-to-heading)
    (unless (> (org-current-level) 1) (error "Must be at sublevel"))
    (let ((bufname "timeline")
          (heading (org-get-heading t))
          (clktime (apply 'encode-time (append `(0 ,(org-clock-sum-current-item) 0) (nthcdr 3 (decode-time)))))
          (start (point))
          (end (save-excursion (org-end-of-subtree :invisible-OK t))))
      (with-current-buffer (get-buffer-create bufname)
        (insert "* " heading "n")
        (org-entry-put (point) "ClockedTime" (format-time-string "%R" clktime) "n"))
      (while (progn (forward-line 1) (< (point) end))
        (funcall 'rel-org-maybe-copy-ts-item bufname))
      (with-current-buffer (get-buffer-create bufname)
        (org-back-to-heading)
        (forward-line 1)
        (org-sort-entries-or-items :sorting-type ?t)))))