Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- '''
- Create a csv from bugsplat data
- '''
- from __future__ import print_function
- import json
- import requests
- import unicodecsv as csv
- import os
- import sys
- import re
- import tempfile
- import argparse
- import shutil
- PROGRAM_NAME = os.path.basename(__file__)
- LAST_UPDATED = 'March 29 2017'
- def help_me():
- """
- Help menu and such, man style
- """
- print(" User Manual")
- print("NAME")
- print(" %s - Get BugSplat reports in CSV format - %s" % (PROGRAM_NAME, LAST_UPDATED))
- print("")
- print("SYNOPSIS")
- print("%s <-g, --gl Get GL info (optional)" % PROGRAM_NAME)
- print("%s {-s, --ss Sort by stackKeyId (optional)}" % PROGRAM_NAME)
- print("%s {-i, --stackfilter Filter by stackKeyId (optional)}" % PROGRAM_NAME)
- print("%s {-l, --pluginfilter Filter by plugin (optional)}" % PROGRAM_NAME)
- print("%s {-q, --includeplugins includes plugins in csv (optional)}" % PROGRAM_NAME)
- print("%s {-d, --db={bdname} BugSplat database name" % PROGRAM_NAME)
- print("%s {-c, --count=[number] number of rows to collect" % PROGRAM_NAME)
- print("%s {-u, --user={usename} username to bugsplat" % PROGRAM_NAME)
- print("%s {-p, --password={usepassword} password to bugsplat" % PROGRAM_NAME)
- print("%s {-f, --filename={outputfile.csv} output filename " % PROGRAM_NAME)
- print("")
- print("DESCRIPTION")
- print(" %s is used to get a said number of crash reports from a specified \
- database in BugSplat. The generated csv can be used to create reports and filter \
- crash events." % PROGRAM_NAME)
- print(" Examples:")
- print(" %s -f ~/report.csv -p passw0rd -u bob -g --db=SU17Win --count=1000" % PROGRAM_NAME)
- print(" %s --file=~/Desktop/SU16crashes.csv --password=p@$$ --user=dirk -d SU16Mac --count=100000" % PROGRAM_NAME)
- print("")
- print("AUTHOR")
- print(" Hiram Bayless hiram@sketchup.com\nDanny Brill danny_brill@trimble.com")
- class BugSplatApi(object):
- """
- Login and pull info from BugSplat
- """
- def __init__(self, user, password, stack_filter=None, include_plugins=None, plugin_filter=None, get_gl=None):
- """
- Create a requests session to BugSplat
- """
- self.base_url = "https://app.bugsplat.com/"
- self.login_url = self.base_url + "api/authenticate.php"
- self.auth_payload = {"email": user, "password": password}
- self.stack_filter = stack_filter
- self.include_plugins = include_plugins
- self.plugin_filter = plugin_filter
- self.get_gl = get_gl
- print("Attempting login in to %s as %s" %(self.login_url, user))
- with requests.Session() as self.session_url:
- try:
- self.session_url.post(self.login_url, data=self.auth_payload)
- except:
- print("Unable to login to %s, please verify the URL and login are correct." % self.login_url)
- sys.exit(1)
- print("Logged in!")
- def getCrashes(self, page_size, database):
- self.allcrash_url = self.base_url + "allcrash/?database=" + database + "&pagesize=" + page_size + "&data"
- self.allcrash_url_results = self.session_url.get(self.allcrash_url)
- tmp = self.allcrash_url_results.json()[0]['Rows']
- self.returns = []
- for i in range(len(tmp)):
- tmp_logs = self.getLogs(tmp[i]['id'], database)
- tmp[i]['last command'] = self.getLastCommand(tmp[i]['id'], database, tmp_logs)
- if self.stack_filter and tmp[i]['stackKeyId'] != self.stack_filter:
- print('%s != %s' % (tmp[i]['stackKeyId'], self.stack_filter))
- continue
- if self.include_plugins or self.plugin_filter:
- tmp[i]['plugins'] = self.getPlugins(tmp[i]['id'], database, tmp_logs)
- if self.plugin_filter and self.plugin_filter not in tmp[i]['plugins']:
- print('plugin poorly filtered!')
- continue
- if self.get_gl:
- gl = self.getGL(tmp[i]['id'], database, tmp_logs)
- print("%s" % gl)
- tmp[i]['GL_RENDERER'] = gl['GL_RENDERER']
- tmp[i]['GL_VERSION'] = gl['GL_VERSION']
- self.returns.append(tmp[i])
- print("[*] %s" % len(self.returns))
- return self.returns
- def getLastCommand(self, bs_id, bs_db, logs):
- #logs = self.getLogs(bs_id, bs_db).text.split('\n')
- logs = logs.text.split('\n')
- logs = filter(None, logs)
- return logs[-1]
- def getPlugins(self, bs_id, bs_db, logs):
- #logs = self.getLogs(bs_id, bs_db).text.split('\n')
- logs = logs.text.split('\n')
- logs = filter(lambda x: 'ruby file:' in x, logs)
- plugins = []
- for i in logs:
- plugins.append(i.split(':')[-1].split('/')[-1])
- return ", ".join(plugins)
- def getLogs(self, bs_id, bs_db):
- self.bugsplatlog_url = self.base_url + "individualCrash/?id=" + bs_id + "&database=" + bs_db
- self.bugsplatlog = self.session_url.get(self.bugsplatlog_url)
- self.sketchup_reg_ex = re.compile('href=\"(/browse/showzipcontents\\.php\\?item=SketchUpLog.+?(?=\"))')
- for line in self.bugsplatlog.text.split('\n'):
- self.file_match = self.sketchup_reg_ex.search(line)
- if self.file_match:
- self.log_path = self.file_match.group(1)
- return self.session_url.get(self.base_url + self.log_path)
- def getGL(self, bs_id, bs_db, logs):
- self.gl_results = {'GL_RENDERER' : '', 'GL_VERSION' : ''}
- self.gl_ver_reg_ex = re.compile('.*GL_VERSION:(.*)')
- self.gl_rend_reg_ex = re.compile('GL_RENDERER: (.*)')
- #logs = self.getLogs(bs_id, bs_db).text.split('\n')
- logs = logs.text.split('\n')
- for gl_line in logs:
- self.gl_ver_match = self.gl_ver_reg_ex.match(gl_line)
- self.gl_rend_match = self.gl_rend_reg_ex.match(gl_line)
- if self.gl_ver_match:
- self.gl_results['GL_VERSION'] = self.gl_ver_match.group(1).strip()
- if self.gl_rend_match:
- self.gl_results['GL_RENDERER'] = self.gl_rend_match.group(1).strip()
- return self.gl_results
- def main():
- parser = argparse.ArgumentParser(description='BugSplat to csv, requires unicodecsv; sudo pip install unicodecsv')
- parser.add_argument('--ss', '-s', action="store_true", help='Sort by stackKeyId', default=False)
- parser.add_argument('--stackfilter', '-i', action="store", help='Only get entries with specified StackKeyId', default=None)
- parser.add_argument('--pluginfilter', '-l', action="store", help='Only get entries with specified plugin', default=None)
- parser.add_argument('--includeplugins', '-q', action="store_true", help='Include plugins in csv', default=False)
- parser.add_argument('--gl', '-g', action="store_true", help='Get Open GL info', default=False)
- parser.add_argument('--filename', '-f', action="store", required=True)
- parser.add_argument('--count', '-c', action="store", required=True, help='Number of rows to gather', type=int)
- parser.add_argument('--password', '-p', action="store", required=True)
- parser.add_argument('--username', '-u', action="store", required=True)
- parser.add_argument('--database', '-d', action="store", required=True)
- args = parser.parse_args()
- user_filename = args.filename
- bs_password = args.password
- bs_user = args.username
- row_count = args.count
- bs_db = args.database
- get_gl = args.gl
- sort_by_stack = args.ss
- stack_filter = args.stackfilter
- include_plugins = args.includeplugins
- plugin_filter = args.pluginfilter
- print("Output filename set to: " + user_filename)
- print("Username set to: " + bs_user)
- print("Getting " + str(row_count) + " row(s)")
- print("Looking in the " + bs_db + " database")
- if get_gl:
- print("Getting GL info... this may take a while")
- csv_fields = [ 'additionalInfo',
- 'appName',
- 'appDescription',
- 'appVersion',
- 'Comments',
- 'email',
- 'skComments',
- 'stackKeyId',
- 'stackKey',
- 'crashTime',
- 'defectId',
- 'IpAddress',
- 'id',
- 'user',
- 'last command' ]
- bs = BugSplatApi(bs_user, bs_password, stack_filter, include_plugins, plugin_filter, get_gl)
- crash_data = bs.getCrashes(str(row_count), bs_db)
- print("%s" % crash_data)
- if sort_by_stack:
- #key on each dictionary's 'stackKeyId' values
- crash_data = sorted(crash_data, key= lambda k: int(k['stackKeyId']))
- if include_plugins or plugin_filter:
- csv_fields.append('plugins')
- if get_gl:
- csv_fields.append('GL_RENDERER')
- csv_fields.append('GL_VERSION')
- with open(user_filename, 'wb+') as output_file:
- dict_writer = csv.DictWriter(output_file, fieldnames=csv_fields)
- dict_writer.writeheader()
- dict_writer.writerows(crash_data)
- print("wrote data to " + user_filename)
- if __name__ == '__main__':
- main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement