In order to provide error reporting during normal program execution, the BugSnag python library includes functions for sending an exception directly.
The bugsnag.notify
function is available to send handled exceptions to
BugSnag using the default configuration.
try:
sign_in()
except Exception as e:
bugsnag.notify(e)
show_error_dialog()
Invocations of bugsnag.notify
can be customized using the
notification options to change report information.
Reporting clients can be created to cache notification and delivery options
separate from the defaults used by bugsnag.notify
and optionally scoped to
specific sections of code.
client = bugsnag.Client(api_key='...')
client.notify(Exception('Oh no'))
Note: By default, a client installs itself as the default exception hook.
To avoid duplicating error reports when using multiple clients, set
install_sys_hook
to False
for all but the client which should be used to
capture unhandled exceptions.
client = bugsnag.Client(api_key='...', install_sys_hook=False)
Custom clients support capturing exceptions on specific sections of code using
capture
. Capture reports any exception thrown during the execution of a
provided context, attaching additional report metadata where requested.
try:
with client.capture(severity='warning'):
sign_in()
begin_sync()
with client.capture():
load_user_info()
except:
show_error_dialog()
Captured and reported exceptions can also be further scoped by type to only report specific classes of exceptions.
try:
with client.capture((LoadError,), severity='warning'):
sign_in()
begin_sync()
with client.capture():
load_user_info()
except:
show_error_dialog()
Exceptions thrown within an entire function can be captured by using the
capture
decorator.
@client.capture
def update(self):
dialog = show_dialog()
if not dialog.visible:
raise LoadError('dialog failed to load')
The decorator also accepts additional arguments for exception type filtering and attaching additional information.
@client.capture((LoadError,), severity='warning')
def update(self):
dialog = show_dialog()
if not dialog.visible:
raise LoadError('dialog failed to load')
Invocations of bugsnag.Client.notify
and bugsnag.Client.capture
accept
notification options to change report information.
A client can generate a Handler to attach to a logger to output emitted log messages to BugSnag.
logger = logging.getLogger(__name__)
handler = client.log_handler()
logger.addHandler(handler)
To attach additional information to an error report from the
LogRecord,
add a callback. A callback is invoked with the LogRecord instance and the
options which will be passed to notify
:
def attach_custom_fields(record, options):
if 'metadata' not in options:
options['metadata'] = {}
options['metadata']['stats'] = {
'account_id': record.account_id,
'slice': record.slice
}
logger = logging.getLogger(__name__)
handler = client.log_handler()
handler.add_callback(attach_custom_fields)
logger.addHandler(handler)
To filter messages sent to BugSnag, attach a
Filter to
the handler, returning True
only if the message should be sent:
class CustomFilter(logging.Filter)
def filter(record):
return record.account_id != 0
logger = logging.getLogger(__name__)
handler = client.log_handler()
handler.addFilter(CustomFilter())
logger.addHandler(handler)
You can include the state of local variables when reporting handled exceptions. The values will appear in a tab in BugSnag called “Local variables”.
bugsnag.notify(e, metadata={"local variables": locals()})
The bugsnag.notify
and bugsnag.Client.capture
functions accept several
keyword arguments which can be used to override configuration or to send more
data to BugSnag. These same fields can be used to customize handled error
reports globally.
api_key
Use a specific API key for this event. (defaults to
bugsnag.configuration.api_key
)
Using the default global client:
bugsnag.notify(e, api_key="YOUR_API_KEY_HERE")
Or with a custom client:
client.notify(e, api_key="YOUR_API_KEY_HERE")
with client.capture(api_key="YOUR_API_KEY_HERE"):
sign_in()
@client.capture(api_key="YOUR_API_KEY_HERE")
def update(self):
sign_in()
app_type
Specify the component or configuration affected by this event. This allows filtering and grouping events by the worker queue, HTTP router, and more.
bugsnag.notify(e, app_type="email queue")
Or with a custom client:
client.notify(e, app_type="email queue")
with client.capture(app_type="email queue"):
process_events()
@client.capture(app_type="email queue")
def update(self):
process_events()
context
A string representing what was happening in your application at the time of the error. In Django apps, this is automatically set to be the path of the current request.
Using the default global client:
bugsnag.notify(e, context="sign up")
Or with a custom client:
client.notify(e, context="sign up")
with client.capture(context="sign up"):
sign_in()
@client.capture(context="sign up")
def update(self):
sign_in()
grouping_hash
A string to use to group errors using your own custom grouping algorithm.
Using the default global client:
bugsnag.notify(e, grouping_hash="Test Slice B Runtime Error")
Using a Logger:
logger.info("This happened", extra={'groupingHash': 'Test Slice B Runtime Error'})
Or With a custom client:
client.notify(e, grouping_hash="Test Slice B Runtime Error")
with client.capture(grouping_hash="Test Slice B Runtime Error"):
sign_in()
@client.capture(grouping_hash="Test Slice B Runtime Error")
def update(self):
sign_in()
metadata
A dictionary of dictionaries. Each dictionary will show up as a tab on BugSnag.
Using the default global client:
bugsnag.notify(e, metadata={"account":{"name":"ACME Inc.", "premium": True}})
Or with a custom client:
client.notify(e, metadata={"account":{"name":"ACME Inc.", "premium": True}})
with client.capture(account={"name":"ACME Inc.", "premium": True}):
sign_in()
@client.capture(account={"name":"ACME Inc.", "premium": True})
def update(self):
sign_in()
severity
You can set the severity of an error in BugSnag by including the severity option when notifying BugSnag.
Using the default global client:
bugsnag.notify(Exception("Something broke!"), severity="error")
Or with a custom client:
client.notify(Exception("Something broke!"), severity="error")
with client.capture(severity="error"):
sign_in()
@client.capture(severity="error")
def update(self):
sign_in()
Valid severities are error
, warning
, and info
.
Severity is displayed in the dashboard and can be used to filter the error list.
By default all crashes (or unhandled exceptions) are set to error
and all
bugsnag.notify()
calls default to warning
.
traceback
The traceback to use for the exception. If omitted this will be read from
sys.exc_info
.
Using the default global client:
bugsnag.notify(e, traceback=sys.exc_info()[2])
Or with a custom client:
client.notify(e, traceback=sys.exc_info()[2])
user
Information about the user currently using your app. This should be a dictionary
containing id
, email
and name
keys.
Using the default global client:
bugsnag.notify(e, user={"id":"bob", name: "Bob", email: "bob@example.com"})
Or with a custom client:
client.notify(e, user={"id":"bob", name: "Bob", email: "bob@example.com"})
with client.capture(user={"id":"bob", name: "Bob", email: "bob@example.com"}):
sign_in()