Skip to content

Instantly share code, notes, and snippets.

@ahal
Last active August 29, 2015 14:13
Show Gist options
  • Save ahal/4de89ecd91dd143a307f to your computer and use it in GitHub Desktop.
Save ahal/4de89ecd91dd143a307f to your computer and use it in GitHub Desktop.
Consume structured mochitest logs from pulse
import json
import sys
import traceback
import requests
from mozillapulse.consumers import NormalizedBuildConsumer
def run(args=sys.argv[1:]):
pulse_args = {
# a string to identify this consumer when logged into pulse.mozilla.org
'applabel': 'mochitest-log-consumer',
# each message contains a topic. Only messages that match the topic specified here will
# be delivered. '#' is a wildcard, so this topic matches all messages that start with
# 'unittest'.
'topic': 'unittest.#',
# durable queues will store messages inside pulse even if your consumer goes offline for
# a bit. Otherwise, any messages published while the consumer is not explicitly
# listeneing will be lost forever. Keep it set to False for testing purposes.
'durable': False,
# the user you created on pulse.mozilla.org
'user': 'ahal',
# the password you created for the user
'password': 'hunter1',
# a callback that will get invoked on each build event
'callback': on_build_event,
}
pulse = NormalizedBuildConsumer(**pulse_args)
while True:
try:
pulse.listen()
except KeyboardInterrupt:
# without this ctrl-c won't work!
raise
except IOError:
# sometimes you'll get a socket timeout. Just call listen again and all will be
# well. This was fairly common and probably not worth logging.
pass
except:
# it is possible for rabbitmq to throw other exceptions. You likely
# want to log them and move on.
traceback.print_exc()
def on_build_event(data, message):
# each message needs to be acknowledged. This tells the pulse queue that the message has been
# processed and that it is safe to discard. Normally you'd want to ack the message when you know
# for sure that nothing went wrong, but this is a simple example so I'll just ack it right away.
message.ack()
# pulse data has two main properties, a payload and metadata. Normally you'll only care about
# the payload.
payload = data['payload']
print('Got a {} job on {}'.format(payload['test'], payload['tree']))
# ignore anything not from mozilla-central or mozilla-inbound
if payload['tree'] not in ('mozilla-central', 'mozilla-inbound'):
return
# ignore anything that's not mochitests
if not payload['test'].startswith('mochitest'):
return
# ignore jobs that don't have the blobber_files property
if 'blobber_files' not in payload:
return
# this is a message we care about, download the structured log!
for filename, url in payload['blobber_files'].iteritems():
if filename.endswith('_raw.log'):
print('Downloading a {} log from revision {}'.format(
payload['test'], payload['revision']))
r = requests.get(url, stream=True)
# save the log
with open('mochitest.log', 'wb') as f:
for chunk in r.iter_content(1024):
f.write(chunk)
break
else:
# the job supports blobber but no (recognized) structured logs were uploaded
return
# now time to do something with the log!
if __name__ == '__main__':
sys.exit(run())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment