Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 # Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 # Copyright (c) 2009 The Chromium Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
| 4 | 4 |
| 5 """Breakpad for Python. | 5 """Breakpad for Python. |
| 6 | 6 |
| 7 Sends a notification when a process stops on an exception. | 7 Sends a notification when a process stops on an exception. |
| 8 | 8 |
| 9 It is only enabled when all these conditions are met: | 9 It is only enabled when all these conditions are met: |
| 10 1. hostname finishes with '.google.com' | 10 1. hostname finishes with '.google.com' |
| 11 2. main module name doesn't contain the word 'test' | 11 2. main module name doesn't contain the word 'test' |
| 12 3. no NO_BREAKPAD environment variable is defined | 12 3. no NO_BREAKPAD environment variable is defined |
| 13 """ | 13 """ |
| 14 | 14 |
| 15 import atexit | 15 import atexit |
| 16 import time | |
| 16 import getpass | 17 import getpass |
| 17 import os | 18 import os |
| 18 import urllib | 19 import urllib |
| 19 import traceback | 20 import traceback |
| 20 import socket | 21 import socket |
| 21 import sys | 22 import sys |
| 22 | 23 |
| 23 | 24 |
| 24 # Configure these values. | 25 # Configure these values. |
| 25 DEFAULT_URL = 'https://chromium-status.appspot.com/breakpad' | 26 DEFAULT_URL = 'https://chromium-status.appspot.com' |
| 26 | 27 |
| 27 _REGISTERED = False | 28 _REGISTERED = False |
| 28 | 29 |
| 30 _TIME_STARTED = time.time() | |
| 31 | |
| 29 | 32 |
| 30 def FormatException(e): | 33 def FormatException(e): |
| 31 """Returns a human readable form of an exception. | 34 """Returns a human readable form of an exception. |
| 32 | 35 |
| 33 Adds the maximum number of interesting information in the safest way.""" | 36 Adds the maximum number of interesting information in the safest way.""" |
| 34 try: | 37 try: |
| 35 out = repr(e) | 38 out = repr(e) |
| 36 except Exception: | 39 except Exception: |
| 37 out = '' | 40 out = '' |
| 38 try: | 41 try: |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 51 if hasattr(e, 'info') and callable(e.info): | 54 if hasattr(e, 'info') and callable(e.info): |
| 52 out += '\ninfo(): %s' % e.info() | 55 out += '\ninfo(): %s' % e.info() |
| 53 except Exception: | 56 except Exception: |
| 54 pass | 57 pass |
| 55 return out | 58 return out |
| 56 | 59 |
| 57 | 60 |
| 58 def SendStack(last_tb, stack, url=None, maxlen=50): | 61 def SendStack(last_tb, stack, url=None, maxlen=50): |
| 59 """Sends the stack trace to the breakpad server.""" | 62 """Sends the stack trace to the breakpad server.""" |
| 60 if not url: | 63 if not url: |
| 61 url = DEFAULT_URL | 64 url = DEFAULT_URL + '/breakpad' |
| 62 print 'Sending crash report ...' | 65 print 'Sending crash report ...' |
| 63 try: | 66 try: |
| 64 params = { | 67 params = { |
| 65 'args': sys.argv, | 68 'args': sys.argv, |
| 66 'stack': stack[0:4096], | 69 'stack': stack[0:4096], |
| 67 'user': getpass.getuser(), | 70 'user': getpass.getuser(), |
| 68 'exception': FormatException(last_tb), | 71 'exception': FormatException(last_tb), |
| 69 'host': socket.getfqdn(), | 72 'host': socket.getfqdn(), |
| 70 'cwd': os.getcwd(), | 73 'cwd': os.getcwd(), |
| 71 'version': sys.version, | 74 'version': sys.version, |
| 72 } | 75 } |
| 73 # pylint: disable=W0702 | 76 # pylint: disable=W0702 |
| 74 print('\n'.join(' %s: %s' % (k, v[0:maxlen]) | 77 print('\n'.join(' %s: %s' % (k, v[0:maxlen]) |
| 75 for k, v in params.iteritems())) | 78 for k, v in params.iteritems())) |
| 76 request = urllib.urlopen(url, urllib.urlencode(params)) | 79 request = urllib.urlopen(url, urllib.urlencode(params)) |
| 77 print(request.read()) | 80 print(request.read()) |
| 78 request.close() | 81 request.close() |
| 79 except IOError: | 82 except IOError: |
| 80 print('There was a failure while trying to send the stack trace. Too bad.') | 83 print('There was a failure while trying to send the stack trace. Too bad.') |
| 81 | 84 |
| 82 | 85 |
| 86 def SendProfiling(url=None): | |
| 87 try: | |
| 88 if not url: | |
| 89 url = DEFAULT_URL + '/profiling' | |
| 90 params = { | |
| 91 'argv': ' '.join(sys.argv), | |
| 92 'duration': time.time() - _TIME_STARTED, | |
|
cmp
2011/04/27 21:30:05
please add 'os' here (result of uname or whatever)
| |
| 93 } | |
| 94 request = urllib.urlopen(url, urllib.urlencode(params)) | |
| 95 request.read() | |
| 96 request.close() | |
| 97 except IOError: | |
| 98 pass | |
|
cmp
2011/04/27 21:30:05
since this runs all of the time, set a timer to ke
| |
| 99 | |
| 100 | |
| 83 def CheckForException(): | 101 def CheckForException(): |
| 84 """Runs at exit. Look if there was an exception active.""" | 102 """Runs at exit. Look if there was an exception active.""" |
| 85 last_value = getattr(sys, 'last_value', None) | 103 last_value = getattr(sys, 'last_value', None) |
| 86 if last_value and not isinstance(last_value, KeyboardInterrupt): | 104 if last_value: |
| 87 last_tb = getattr(sys, 'last_traceback', None) | 105 if not isinstance(last_value, KeyboardInterrupt): |
| 88 if last_tb: | 106 last_tb = getattr(sys, 'last_traceback', None) |
| 89 SendStack(last_value, ''.join(traceback.format_tb(last_tb))) | 107 if last_tb: |
| 108 SendStack(last_value, ''.join(traceback.format_tb(last_tb))) | |
| 109 else: | |
| 110 SendProfiling() | |
| 90 | 111 |
| 91 | 112 |
| 92 def Register(): | 113 def Register(): |
| 93 """Registers the callback at exit. Calling it multiple times is no-op.""" | 114 """Registers the callback at exit. Calling it multiple times is no-op.""" |
| 94 global _REGISTERED | 115 global _REGISTERED |
| 95 if _REGISTERED: | 116 if _REGISTERED: |
| 96 return | 117 return |
| 97 _REGISTERED = True | 118 _REGISTERED = True |
| 98 atexit.register(CheckForException) | 119 atexit.register(CheckForException) |
| 99 | 120 |
| 100 | 121 |
| 101 # Skip unit tests and we don't want anything from non-googler. | 122 # Skip unit tests and we don't want anything from non-googler. |
| 102 if (not 'test' in sys.modules['__main__'].__file__ and | 123 if (not 'test' in sys.modules['__main__'].__file__ and |
| 103 not 'NO_BREAKPAD' in os.environ and | 124 not 'NO_BREAKPAD' in os.environ and |
| 104 (socket.getfqdn().endswith('.google.com') or | 125 (socket.getfqdn().endswith('.google.com') or |
| 105 socket.getfqdn().endswith('.chromium.org'))): | 126 socket.getfqdn().endswith('.chromium.org'))): |
| 106 Register() | 127 Register() |
| 107 | 128 |
| 108 # Uncomment this line if you want to test it out. | 129 # Uncomment this line if you want to test it out. |
| 109 #Register() | 130 #Register() |
| OLD | NEW |