PagerDuty desktop notifications

I’m a fan of PagerDuty. I have used it for a while now and it’s great. I use the webapp, but I love the mobile app because I can quickly acknowledge tickets that I’m looking into, and I can quickly look to see if I missed anything. However the one thing I’m missing… are desktop notifications. Here’s the way it usually goes down for me:

  1. Get ready for work, and head to the (beautiful) office.
  2. When I get there I put my phone on vibrate out of respect for my co-workers.
  3. Something breaks and PagerDuty pushes a notification to my phone.
  4. I sit there working, blissfully unaware that my phone is trying to tell me something went wrong.
  5. Eventually I stumble upon my phone or email that tells me there is a problem, but I’m responding later than I intend.

Luckily PagerDuty has a rest api which made it really easy to create rudimentary desktop notifications.

All I did was create a python script that looks something like this:

#!/usr/bin/env python
# Docs: /usr/share/doc/python-notify/examples

# Python imports
import json
import logging
import time

# Third party imports
import pynotify
import requests

log = logging.getLogger('pagerduty')
token = '...'
user_id = '...'

api = 'https://climate.pagerduty.com/api/v1/incidents'
headers = {'Content-type': 'application/json',
           'Authorization': 'Token token=%s' % token}
params = {'assigned_to_user': user_id,
          'sort_by': 'urgency:asc,incident_number:desc',
          'status': 'triggered'}
pynotify.init('Pagerduty issue applet')


def poll():
    r = requests.get(api, params=params, headers=headers)
    r.raise_for_status()
    for incident in r.json().get('incidents', []):
        show(incident)
    else:
        log.info('No assigned issues')


def show(incident):
    summary = 'PagerDuty:'
    body = json.dumps(incident, indent=2)
    msg = pynotify.Notification(summary, body)
    msg.set_urgency(pynotify.URGENCY_NORMAL)
    if not msg.show():
        print 'failed to show notification'


def main():
    fmt = '%(asctime)-15s %(message)s'
    logging.basicConfig(level=logging.INFO, format=fmt)
    noisy = logging.getLogger('urllib3.connectionpool')
    noisy.setLevel(logging.WARNING)

    while True:
        try:
            poll()
        except Exception:
            log.exception('oops')
        finally:
            time.sleep(60)

if __name__ == '__main__':
    main()

It’s for sure nothing fancy, but it gets the job done :)