Honeybadger for Python

Typical installation time: ~5 minutes

Hi there! You've found Honeybadger's guide to Python exception and error tracking. Once installed, Honeybadger will automatically report errors from your Python application.

Getting Started

Honeybadger for Python works out of the box with Django with only a few configuration options required. The following is a basic setup - more advanced setup will be described later.

Install Honeybadger

Install honeybadger with pip.

$ pip install honeybadger

Note: Honeybadger does not report errors in development and test environments by default. To enable reporting in development environments, see the force_report_data setting.

Django

In a Django application, add the Honeybadger Django middleware to the top of your MIDDLEWARE config variable:

python
MIDDLEWARE = [ 'honeybadger.contrib.DjangoHoneybadgerMiddleware', ... ]

It's important that the Honeybadger middleware is at the top, so that it wraps the entire request process, including all other middlewares.

You'll also need to add a new HONEYBADGER config variable to your settings.py to specify your API key:

python
HONEYBADGER = { 'API_KEY': 'Your project API key' }

Flask

A Flask extension is available for initializing and configuring Honeybadger: honeybadger.contrib.flask.FlaskHoneybadger. The extension adds the following information to reported exceptions:

  • url: The URL the request was sent to.
  • component: The module that the view is defined at. If the view is a class-based view, then the name of the class is also added.
  • action: The name of the function called. If the action is defined within a blueprint, then the action name will have the name of the blueprint prefixed.
  • params: A dictionary containing query parameters and form data. If a variable is defined in both, then the form data are stored. Params are filtered (see Configuration).
  • session: Session data.
  • cgi_data: Request headers, filtered (see Configuration) and request method.

In addition, the FlaskHoneybadger extension: - Configures Honeybadger using Flask's configuration object. - (Optionally) Automatically report exceptions raised during views. - (Optionally) Reset honeybadger context after each request.

Note that FlaskHoneybadger uses Flask's signals in order to detect exceptions. In order for the extension to work, you'll have to install the blinker library as dependency.

FlaskHoneybadger checks Flask's configuration object for automatically configuring honeybadger. In order to configure it, it checks for the keys with same name as the environment variables in Configuration section. Note that if a value is also configured as an environment variable, then the environment variable's value will be used.

Example

python
from flask import Flask, jsonify, request from honeybadger.contrib import FlaskHoneybadger app = Flask(__name__) app.config['HONEYBADGER_ENVIRONMENT'] = 'production' app.config['HONEYBADGER_API_KEY'] = 'Your project API key' app.config['HONEYBADGER_PARAMS_FILTERS'] = 'password, secret, credit-card' FlaskHoneybadger(app, report_exceptions=True) @app.route('/') def index(): a = int(request.args.get('a')) b = int(request.args.get('b')) print('Dividing two numbers {} {}'.format(a, b)) return jsonify({'result': a / b}) [...]

The code above will:

  • Initialize honeybadger using Flask's configuration.
  • Listen for exceptions.
  • Log unhandled exceptions to Honeybadger.
  • It will also add url, component, action, params, cgi_data and context (as generated by context generators) to all errors send using honeybadger.notify().

FlaskHoneybadger will catch exception raised from a view. Note that calls to abort method result in an exception being raised. If you don't want this behavior, you can set report_exceptions to False and just call honeybadger.notify inside your exception handler.

You can also check more examples under directory examples.

Component naming in Flask

The following conventions are used for component names:

  • When using view functions, the name of the component will be <module name>#<view name>
  • For class-based views, the name of the component will be <module name>#<class name>
  • When using blueprints, the name of the component will be <module name>#<blueprint name>.<view name>

AWS Lambda

AWS Lambda environments are auto detected by Honeybadger with no additional configuration. Here's an example lambda function with Honeybadger:

python
from honeybadger import honeybadger honeybadger.configure(api_key='Your project API key') def lambda_handler(event, context): """ A buggy lambda function that tries to perform a zero division """ a = 1 b = 0 return (a/b) #This will be reported

ASGI

A generic ASGI middleware plugin is available for initializing and configuring Honeybadger: honeybadger.contrib.asgi.

The general pattern for these cases is wrapping your ASGI application with a middleware:

python
from honeybadger import contrib asgi_application = someASGIApplication() asgi_application = contrib.ASGIHoneybadger(asgi_application)

You can pass configuration parameters (or additional configuration parameters) as keyword arguments at plugin's initialization:

python
from honeybadger import contrib asgi_application = someASGIApplication() asgi_application = contrib.ASGIHoneybadger(asgi_application, api_key="Your project API key", params_filters=["sensible_data"])

Or you may want to initialize Honeybadger before your application, and then just registering the plugin/middleware:

python
from honeybadger import honeybadger, contrib honeybadger.configure(api_key='Your project API key') some_possibly_failing_function() # you can track errors happening before your plugin initialization. asgi_application = someASGIApplication() asgi_application = contrib.ASGIHoneybadger(asgi_application)

FastAPI

FastAPI is based on Starlette, an ASGI application. You use Honeybadger's ASGI middleware on these types of applications.

python
from fastapi import FastAPI from honeybadger import contrib app = FastAPI() app.add_middleware(contrib.ASGIHoneybadger)

You can pass additional keyword paramters, too:

python
from fastapi import FastAPI from honeybadger import honeybadger, contrib honeybadger.configure(api_key="Your project API key") app = FastAPI() app.add_middleware(contrib.ASGIHoneybadger, params_filters=["dont-include-this"])

FastAPI advanced usage.

Consuming the request body in an ASGI application's middleware is problematic and discouraged. This is the reason why request body data won't be sent to the web UI.

FastAPI allows overriding the logic used by the Request and APIRoute classes, by using custom APIRoute classes. This gives more control over the request body, and makes it possible to send request body data along with honeybadger notifications.

A custom API Route is available at honeybadger.contrib.fastapi.

Here's an example of setting the router class:

python
from fastapi import FastAPI from honeybadger import honeybadger from honeybadger.contrib.fastapi import HoneybadgerRoute honeybadger.configure(api_key="Your project API key") app = FastAPI() app.router.route_class = HoneybadgerRoute

Here's an example of creating a new APIRouter instance:

python
from fastapi import FastAPI, APIRouter from honeybadger import honeybadger from honeybadger.contrib.fastapi import HoneybadgerRoute honeybadger.configure(api_key="Your project API key") app = FastAPI() router = APIRouter(route_class=HoneybadgerRoute) app.router = router

Starlette

You can configure Honeybadger to work with Starlette just like in any other ASGI framework.

python
from starlette.applications import Starlette from starlette.middleware import Middleware from honeybadger import contrib app = Starlette() app.add_middleware(contrib.ASGIHoneybadger)

Celery

A Celery extension is available for initializing and configuring Honeybadger: honeybadger.contrib.celery.CeleryHoneybadger. The extension adds the following information to reported exceptions:

  • component: The module that the task is defined at.
  • action: The name of the task.
  • params: The arguments and keyword arguments passed to the task.
  • context: A dictionary containing the following:
    • task_id: The id of the current task.
    • retries: The number of retries that have been attempted.
    • max_retries: The maximum number of retries that will be attempted.

Example

python
from celery import Celery from honeybadger.contrib import CeleryHoneybadger app = Celery(__name__) app.conf.update( HONEYBADGER_API_KEY= '<your key>', HONEYBADGER_ENVIRONMENT= 'production' ) CeleryHoneybadger(app, report_exceptions=True)

Other frameworks / plain Python app

Django and Flask are the only explicitly supported frameworks at the moment. For other frameworks (tornado, web2py, etc.) or a plain Python script, simply import honeybadger and configure it with your API key. Honeybadger uses a global exception hook to automatically report any uncaught exceptions.

python
from honeybadger import honeybadger honeybadger.configure(api_key='Your project API key') raise Exception("This will get reported!")

All set!

That's it! For additional configuration options, keep reading.

Note: By default, honeybadger reports errors in separate threads. For platforms that disallows threading (such as serving a flask/django app with uwsgi and disabling threading), Honeybadger will fail to report errors. You can either enable threading if you have the option, or set force_sync config option to True. This causes Honeybadger to report errors in a single thread.

Configuration

To set configuration options, use the honeybadger.configure method, like so:

python
honeybadger.configure(api_key='Your project API key', environment='production')

All of Honeybadger's configuration options can also be set via environment variables with the HONEYBADGER prefix (12-factor style). For example, the api_key option can be set via the HONEYBADGER_API_KEY environment variable.

The following options are available to you:

Name Type Default Example Environment variable
api_key str "" "badgers" HONEYBADGER_API_KEY
project_root str The current working directory "/path/to/project" HONEYBADGER_PROJECT_ROOT
environment[^1] str "production" "staging" HONEYBADGER_ENVIRONMENT
hostname str The hostname of the current server. "badger01" HONEYBADGER_HOSTNAME
endpoint str "https://api.honeybadger.io" "https://honeybadger.example.com/" HONEYBADGER_ENDPOINT
params_filters list ['password', 'password_confirmation', 'credit_card'] ['super', 'secret', 'keys'] HONEYBADGER_PARAMS_FILTERS
force_report_data bool False True HONEYBADGER_FORCE_REPORT_DATA
excluded_exceptions list [] ['Http404', 'MyCustomIgnoredError'] HONEYBADGER_EXCLUDED_EXCEPTIONS
force_sync bool False True HONEYBADGER_FORCE_SYNC
report_local_variables bool False True HONEYBADGER_REPORT_LOCAL_VARIABLES

[^1]: Honeybadger will try to infer the correct environment when possible. For example, in the case of the Django integration, if Django settings are set to DEBUG = True, the environment will default to development.

Logging

By default, Honeybadger uses the logging.NullHandler for logging so it doesn't make any assumptions about your logging setup. In Django, add a honeybadger section to your LOGGING config to enable Honeybadger logging. For example:

python
LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'handlers': { 'file': { 'level': 'DEBUG', 'class': 'logging.FileHandler', 'filename': '/path/to/django/debug.log', }, }, 'loggers': { 'honeybadger': { 'handlers': ['file'], 'level': 'DEBUG', 'propagate': True, }, }, }

For other frameworks or a plain Python script, you can use logging.dictConfig or explicitly configure it like so:

python
import logging logging.getLogger('honeybadger').addHandler(logging.StreamHandler())

Log Handler

Honeybadger includes a log handler that can be used to report logs of any level via python's logging module.

python
import logging from honeybadger.contrib.logger import HoneybadgerHandler hb_handler = HoneybadgerHandler(api_key='Your project API key') logger = logging.getLogger('honeybadger') logger.addHandler(hb_handler) try: 1/0 except: logger.error("Something went wrong")

or using Dict Config:

python
LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'handlers': { 'honeybadger': { 'level': 'ERROR', 'class': 'honeybadger.contrib.logger.HoneybadgerHandler', 'api_key': 'Your project API key', }, }, 'loggers': { # root logger '': { 'level': 'WARNING', 'handlers': ['console', 'honeybadger'], }, }, }

Public Methods

honeybadger.set_context: Set global context data

This method allows you to send additional information to the Honeybadger API to assist in debugging. This method sets global context data and is additive - eg. every time you call it, it adds to the existing set unless you call reset_context, documented below.

Examples:

python
from honeybadger import honeybadger honeybadger.set_context(my_data='my_value')

honeybadger.reset_context: Clear global context data

This method clears the global context dictionary.

Examples:

python
from honeybadger import honeybadger honeybadger.reset_context()

honeybadger.context: Python context manager interface

What if you don't want to set global context data? You can use Python context managers to set case-specific contextual information.

Examples:

python
# from a Django view from honeybadger import honeybadger def my_view(request): with honeybadger.context(user_email=request.POST.get('user_email', None)): form = UserForm(request.POST) ...

honeybadger.configure: Specify additional configuration options

Allows you to configure honeybadger within your code. Accepts any of the above-listed configuration options as keyword arguments.

Example:

python
honeybadger.configure(api_key='Your project API key', project_root='/home/dave/crywolf-django')

honeybadger.notify: Send an error notice to Honeybadger

In cases where you'd like to manually send error notices to Honeybadger, this is what you're looking for. You can either pass it an exception as the first argument, or an error_class/error_message pair of keyword arguments. You can also pass it a: - custom context dictionary which will get merged with the global context - fingerprint option to customize the error grouping

Examples:

python
# with an exception mydict = dict(a=1) try: print mydict['b'] except KeyError, exc: honeybadger.notify(exc, context={'foo': 'bar'}) # with custom arguments honeybadger.notify(error_class='ValueError', error_message='Something bad happened!', fingerprint='custom_fingerprint')

Supported Versions

Tested with Python 3.x against Django latest and LTS releases as well as Flask 1.0 and 1.1.