Negroni integration guide

Add BugSnag to your Negroni applications.

This library supports Go 1.11 and above. To integrate with older versions of Go, check out our legacy integration.

New to BugSnag? Create an account

Looking for performance monitoring? See our web app integration

Installation

Download the code via go get:

go get github.com/bugsnag/bugsnag-go-negroni

The latest available version of bugsnag-go-negroni is v2.3.1.

Basic configuration

  1. Add bugsnagnegroni.AutoNotify immediately after the negroni.Recovery middleware in main.go. This causes unhandled panics to notify BugSnag. If you are using negroni.Classic() to initialise Negroni, then it will automatically initialize Recovery for you, so just add the bugsnag AutoNotify after that call instead.

    import "github.com/bugsnag/bugsnag-go/v2"
    import "github.com/bugsnag/bugsnag-go-negroni"
    
    func main() {
        // Existing code initializes Negroni as 'm'
    
        errorHandlerConfig := bugsnag.Configuration{
            // Your BugSnag project API key, required unless set as environment
            // variable $BUGSNAG_API_KEY
            APIKey:          "YOUR API KEY HERE",
            // The import paths for the Go packages containing your source files
            ProjectPackages: []string{"main", "github.com/org/myapp"},
        }
        m.Use(negroni.Recovery())
        m.Use(bugsnagnegroni.AutoNotify(errorHandlerConfig))
    }
    

    You can find your API key in Project Settings from your BugSnag dashboard.

  2. Use your bugsnag.Configuration if you need to notify about non-fatal errors or recover from panics within goroutines.

    type App struct {
        errorHandlerConfig bugsnag.Configuration
    }
    
    // (app initialization) ...
    
    func MyHandler(w http.ResponseWriter, req *http.Request) {
        if err := processWhichMayErr() {
            bugsnag.Notify(err, ctx, app.errorHandlerConfig)
        }
    }
    

Using context.Context to manage HTTP session data

We strongly recommend passing in context.Context to appropriate BugSnag calls. Passing the context.Context from *http.Request objects will automatically attach HTTP request data to your error reports, as well as session data that helps BugSnag track the stability of your application. For more information around how to use context.Context with BugSnag, see the context reference here.

Context can be retrieved from an HTTP request or created if outside a request (see session tracking for more details on sessions)

// Get context from an HTTP request
ctx = request.Context()
// or from manually starting a session outside a http request
ctx = bugsnag.StartSession(context.Background())

Reporting unhandled panics

Unhandled panics are reported using panic-monitor, which is a program launcher that automatically reports any panics which occur in your program.

After completing installation and basic configuration, set the BUGSNAG_API_KEY environment variable to the API key for your project and launch the monitor with your program and its arguments.

BUGSNAG_API_KEY="YOUR API KEY HERE" panic-monitor ./my-app --my-app-flag

Unhandled panics will be automatically reported and error data will begin to appear in your project’s dashboard.

If you cannot use the panic-monitor

In-process panic detection and reporting

If the panic-monitor launcher system cannot be used in your deployment environment, bugsnag-go will instead attempt to detect panics in process with the following caveats:

  • In-process detection forks and monitors the application process. For Docker-based deployments and similar environments where your application is PID 1, this requires using a launcher script to keep the container running until the panic can be delivered. See Deploying with Docker below for a sample configuration.
  • bugsnag.Configure() must be called at the start of your application’s main() function, to avoid unintended side effects like re-calling any code prior to bugsnag.Configure() when the application is forked.
  • Panics inside goroutines may terminate the app before the panic can be reported. See reporting panics from goroutines below for options to work around this issue
  • All OnBeforeNotify callbacks must be registered prior to calling Configure() or will have no effect on events created from unrecovered panics. Panic handling in bugsnag-go forks the process when Configure() is first called, so any callbacks added after that point will not be present in the monitoring process.

See Configuration.PanicHandler to disable reporting panics in-process.

Deploying with Docker

Unhandled panics will terminate the app process, and when deployed with Docker as the main command, may not allow enough time to send the final panic event to BugSnag. Go apps deployed with Docker as PID 1 should use a launcher which will wait for a few seconds prior to allowing the container to terminate.

Sample launcher script for Docker-based deployments

A bash script which launches and waits on an app named my-go-app, terminating if requested by the operating system and waits after the app terminates to send a pending request. This script is intended to be run as the CMD of a Dockerfile.

#!/usr/bin/env bash

# Forward signals to the app process so it terminates if
# requested by the system
_forward_signal() {
    sig="$1"
    kill -$sig "$app_pid" 2>/dev/null
    wait $app_pid
}

_trap_signals() {
    for sig in "$@"; do
        trap "_forward_signal $sig" "$sig"
    done
}

# Wait to allow potential unhandled panic requests to complete
_at_exit() {
  sleep 3
}

_trap_signals INT TERM
trap _at_exit EXIT

./my-go-app &

# Wait until the app process terminates (ensuring signals
# can be captured)
app_pid=$!
wait $app_pid

Reporting panics from goroutines

Since goroutines are generally non-blocking, panics captured on a goroutine may crash the application before having the opportunity to be delivered to BugSnag unless intentionally handled.

Use bugsnag.AutoNotify() to notify bugsnag of a panic while letting the program continue to panic. This is useful if you’re using a framework that already has some handling of panics and you are retrofitting BugSnag support.

go func(ctx context.Context) {
    defer bugsnag.AutoNotify(ctx)

    // ...
}(ctx)

To avoid a panic in a goroutine from crashing your entire app, you can use bugsnag.Recover() to stop a panic from unwinding the stack any further. When Recover() is hit, it will send any current panic to BugSnag and then stop panicking. This is most useful at the start of a goroutine:

go func(ctx context.Context) {
    defer bugsnag.Recover(ctx)

    // ...
}(ctx)

Reporting handled errors

Sometimes it is useful to manually notify BugSnag of a problem. To do this, call bugsnag.Notify()

if err != nil {
    bugsnag.Notify(err, ctx)
}

When reporting handled errors, it’s often helpful to send us custom diagnostic data or to adjust the severity of particular errors. For more information, see the reporting handled errors reference.

Sending diagnostic data

Most functions in the BugSnag API, including bugsnag.Notify(), bugsnag.Recover(), bugsnag.AutoNotify(), and bugsnag.Handler() let you attach data to the notifications that they send. To do this you pass in rawData, which can be any of the supported types listed here.

Custom metaData appears as tabs on error reports on your BugSnag dashboard. You can set it by passing a bugsnag.MetaData object as rawData.

bugsnag.Notify(err, ctx,
    bugsnag.MetaData{
        "Account": {
            "Name": Account.Name,
            "Paying": Account.Plan.Premium,
        },
    })

For more information, see the reporting handled errors reference.

See this reference to learn more about the ctx argument and the advantages of using it.

Identifying users

User data is searchable, and the Id powers the count of users affected. You can set which user an error affects by passing a bugsnag.User object as rawData.

bugsnag.Notify(err, ctx,
    bugsnag.User{Id: "1234", Name: "Conrad", Email: "me@example.com"})

For more information, see the reporting handled errors reference.

See this reference to learn more about the ctx argument and the advantages of using it.

Session tracking

BugSnag tracks the number of “sessions” that happen within your application. This allows you to compare stability scores between releases and helps you to understand the quality of your releases.

Sessions are captured and reported by default. This behavior can be disabled using the AutoCaptureSessions configuration option.

Tracking releases

Configure your app version to see the release that each error was introduced in.

bugsnag.Configure(bugsnag.Configuration{
    AppVersion: "1.2.3",
})

Then set up a build tool integration to enable linking to code in your source control provider from the releases dashboard, timeline annotations, and stack traces.

Next steps