Advertisement
Guest User

Untitled

a guest
Feb 8th, 2018
336
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 8.96 KB | None | 0 0
  1. '''
  2. Create a csv from bugsplat data
  3. '''
  4. from __future__ import print_function
  5. import json
  6. import requests
  7. import unicodecsv as csv
  8. import os
  9. import sys
  10. import re
  11. import tempfile
  12. import argparse
  13. import shutil
  14.  
  15.  
  16. PROGRAM_NAME = os.path.basename(__file__)
  17. LAST_UPDATED = 'March 29 2017'
  18.  
  19. def help_me():
  20.     """
  21.    Help menu and such, man style
  22.    """
  23.     print("     User Manual")
  24.     print("NAME")
  25.     print(" %s - Get BugSplat reports in CSV format - %s" % (PROGRAM_NAME, LAST_UPDATED))
  26.     print("")
  27.     print("SYNOPSIS")
  28.     print("%s <-g, --gl Get GL info (optional)" % PROGRAM_NAME)
  29.     print("%s {-s, --ss Sort by stackKeyId (optional)}" % PROGRAM_NAME)
  30.     print("%s {-i, --stackfilter Filter by stackKeyId (optional)}" % PROGRAM_NAME)
  31.     print("%s {-l, --pluginfilter Filter by plugin (optional)}" % PROGRAM_NAME)
  32.     print("%s {-q, --includeplugins includes plugins in csv (optional)}" % PROGRAM_NAME)
  33.     print("%s {-d, --db={bdname} BugSplat database name" % PROGRAM_NAME)
  34.     print("%s {-c, --count=[number] number of rows to collect" % PROGRAM_NAME)
  35.     print("%s {-u, --user={usename} username to bugsplat" % PROGRAM_NAME)
  36.     print("%s {-p, --password={usepassword} password to bugsplat" % PROGRAM_NAME)
  37.     print("%s {-f, --filename={outputfile.csv} output filename " % PROGRAM_NAME)
  38.     print("")
  39.     print("DESCRIPTION")
  40.     print(" %s is used to get a said number of crash reports from a specified \
  41. database in BugSplat. The generated csv can be used to create reports and filter \
  42. crash events." % PROGRAM_NAME)
  43.     print(" Examples:")
  44.     print("     %s -f ~/report.csv -p passw0rd -u bob -g --db=SU17Win --count=1000" % PROGRAM_NAME)
  45.     print("     %s --file=~/Desktop/SU16crashes.csv --password=p@$$ --user=dirk -d SU16Mac --count=100000" % PROGRAM_NAME)
  46.     print("")
  47.     print("AUTHOR")
  48.     print(" Hiram Bayless hiram@sketchup.com\nDanny Brill danny_brill@trimble.com")
  49.  
  50. class BugSplatApi(object):
  51.     """
  52.    Login and pull info from BugSplat
  53.    """
  54.     def __init__(self, user, password, stack_filter=None, include_plugins=None,  plugin_filter=None, get_gl=None):
  55.         """
  56.        Create a requests session to BugSplat
  57.        """
  58.         self.base_url = "https://app.bugsplat.com/"
  59.         self.login_url = self.base_url + "api/authenticate.php"
  60.         self.auth_payload = {"email": user, "password": password}
  61.         self.stack_filter = stack_filter
  62.         self.include_plugins = include_plugins
  63.         self.plugin_filter = plugin_filter
  64.         self.get_gl = get_gl
  65.         print("Attempting login in to %s as %s" %(self.login_url, user))
  66.         with requests.Session() as self.session_url:
  67.             try:
  68.                 self.session_url.post(self.login_url, data=self.auth_payload)
  69.             except:
  70.                 print("Unable to login to %s, please verify the URL and login are correct." % self.login_url)
  71.                 sys.exit(1)
  72.             print("Logged in!")
  73.  
  74.  
  75.     def getCrashes(self, page_size, database):
  76.         self.allcrash_url = self.base_url + "allcrash/?database=" + database + "&pagesize=" + page_size + "&data"
  77.         self.allcrash_url_results = self.session_url.get(self.allcrash_url)
  78.         tmp = self.allcrash_url_results.json()[0]['Rows']
  79.         self.returns = []
  80.  
  81.         for i in range(len(tmp)):
  82.             tmp_logs = self.getLogs(tmp[i]['id'], database)
  83.             tmp[i]['last command'] = self.getLastCommand(tmp[i]['id'], database, tmp_logs)
  84.             if self.stack_filter and tmp[i]['stackKeyId'] != self.stack_filter:
  85.                 print('%s != %s' % (tmp[i]['stackKeyId'], self.stack_filter))
  86.                 continue
  87.             if self.include_plugins or self.plugin_filter:
  88.                 tmp[i]['plugins'] = self.getPlugins(tmp[i]['id'], database, tmp_logs)
  89.             if self.plugin_filter and self.plugin_filter not in tmp[i]['plugins']:
  90.                 print('plugin poorly filtered!')
  91.                 continue
  92.             if self.get_gl:
  93.                 gl = self.getGL(tmp[i]['id'], database, tmp_logs)
  94.                 print("%s" % gl)
  95.                 tmp[i]['GL_RENDERER'] = gl['GL_RENDERER']
  96.                 tmp[i]['GL_VERSION'] = gl['GL_VERSION']
  97.             self.returns.append(tmp[i])
  98.         print("[*] %s" % len(self.returns))
  99.         return self.returns
  100.  
  101.  
  102.     def getLastCommand(self, bs_id, bs_db, logs):
  103.         #logs = self.getLogs(bs_id, bs_db).text.split('\n')
  104.         logs = logs.text.split('\n')
  105.         logs = filter(None, logs)
  106.  
  107.         return logs[-1]
  108.  
  109.     def getPlugins(self, bs_id, bs_db, logs):
  110.         #logs = self.getLogs(bs_id, bs_db).text.split('\n')
  111.         logs = logs.text.split('\n')
  112.         logs = filter(lambda x: 'ruby file:' in x, logs)
  113.         plugins = []
  114.         for i in logs:
  115.             plugins.append(i.split(':')[-1].split('/')[-1])
  116.  
  117.         return ", ".join(plugins)
  118.  
  119.  
  120.     def getLogs(self, bs_id, bs_db):
  121.         self.bugsplatlog_url = self.base_url + "individualCrash/?id=" + bs_id + "&database=" + bs_db
  122.         self.bugsplatlog = self.session_url.get(self.bugsplatlog_url)
  123.         self.sketchup_reg_ex = re.compile('href=\"(/browse/showzipcontents\\.php\\?item=SketchUpLog.+?(?=\"))')
  124.         for line in self.bugsplatlog.text.split('\n'):
  125.             self.file_match = self.sketchup_reg_ex.search(line)
  126.             if self.file_match:
  127.                 self.log_path = self.file_match.group(1)
  128.  
  129.         return self.session_url.get(self.base_url + self.log_path)
  130.  
  131.  
  132.     def getGL(self, bs_id, bs_db, logs):
  133.         self.gl_results = {'GL_RENDERER' : '', 'GL_VERSION' : ''}
  134.         self.gl_ver_reg_ex = re.compile('.*GL_VERSION:(.*)')
  135.         self.gl_rend_reg_ex = re.compile('GL_RENDERER: (.*)')
  136.         #logs = self.getLogs(bs_id, bs_db).text.split('\n')
  137.         logs = logs.text.split('\n')
  138.         for gl_line in logs:
  139.             self.gl_ver_match = self.gl_ver_reg_ex.match(gl_line)
  140.             self.gl_rend_match = self.gl_rend_reg_ex.match(gl_line)
  141.             if self.gl_ver_match:
  142.                 self.gl_results['GL_VERSION'] = self.gl_ver_match.group(1).strip()
  143.             if self.gl_rend_match:
  144.                 self.gl_results['GL_RENDERER'] = self.gl_rend_match.group(1).strip()
  145.  
  146.         return self.gl_results
  147.  
  148.  
  149. def main():
  150.     parser = argparse.ArgumentParser(description='BugSplat to csv, requires unicodecsv; sudo pip install unicodecsv')
  151.     parser.add_argument('--ss', '-s', action="store_true", help='Sort by stackKeyId', default=False)
  152.     parser.add_argument('--stackfilter', '-i', action="store", help='Only get entries with specified StackKeyId', default=None)
  153.     parser.add_argument('--pluginfilter', '-l', action="store", help='Only get entries with specified plugin', default=None)
  154.     parser.add_argument('--includeplugins', '-q', action="store_true", help='Include plugins in csv', default=False)
  155.     parser.add_argument('--gl', '-g', action="store_true", help='Get Open GL info', default=False)
  156.     parser.add_argument('--filename', '-f', action="store", required=True)
  157.     parser.add_argument('--count', '-c', action="store", required=True, help='Number of rows to gather', type=int)
  158.     parser.add_argument('--password', '-p', action="store", required=True)
  159.     parser.add_argument('--username', '-u', action="store", required=True)
  160.     parser.add_argument('--database', '-d', action="store", required=True)
  161.     args = parser.parse_args()
  162.     user_filename = args.filename
  163.     bs_password = args.password
  164.     bs_user = args.username
  165.     row_count = args.count
  166.     bs_db = args.database
  167.     get_gl = args.gl
  168.     sort_by_stack = args.ss
  169.     stack_filter = args.stackfilter
  170.     include_plugins = args.includeplugins
  171.     plugin_filter = args.pluginfilter
  172.     print("Output filename set to: " + user_filename)
  173.     print("Username set to: " + bs_user)
  174.     print("Getting " + str(row_count) + " row(s)")
  175.     print("Looking in the " + bs_db + " database")
  176.     if get_gl:
  177.         print("Getting GL info... this may take a while")
  178.  
  179.     csv_fields = [ 'additionalInfo',
  180.     'appName',
  181.     'appDescription',
  182.     'appVersion',
  183.     'Comments',
  184.     'email',
  185.     'skComments',
  186.     'stackKeyId',
  187.     'stackKey',
  188.     'crashTime',
  189.     'defectId',
  190.     'IpAddress',
  191.     'id',
  192.     'user',
  193.     'last command' ]
  194.  
  195.     bs = BugSplatApi(bs_user, bs_password, stack_filter, include_plugins, plugin_filter, get_gl)
  196.     crash_data = bs.getCrashes(str(row_count), bs_db)
  197.     print("%s" % crash_data)
  198.  
  199.     if sort_by_stack:
  200.         #key on each dictionary's 'stackKeyId' values
  201.         crash_data = sorted(crash_data, key= lambda k: int(k['stackKeyId']))
  202.     if include_plugins or plugin_filter:
  203.         csv_fields.append('plugins')
  204.     if get_gl:
  205.         csv_fields.append('GL_RENDERER')
  206.         csv_fields.append('GL_VERSION')
  207.  
  208.     with open(user_filename, 'wb+') as output_file:
  209.         dict_writer = csv.DictWriter(output_file, fieldnames=csv_fields)
  210.         dict_writer.writeheader()
  211.         dict_writer.writerows(crash_data)
  212.         print("wrote data to " + user_filename)
  213.  
  214. if __name__ == '__main__':
  215.     main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement