1// Package bugsnagrevel adds Bugsnag to revel.
2// It lets you pass *revel.Controller into bugsnag.Notify(),
3// and provides a Filter to catch errors.
4package bugsnagrevel
5
6import (
7	"strings"
8	"sync"
9
10	"github.com/bugsnag/bugsnag-go"
11	"github.com/revel/revel"
12)
13
14var once sync.Once
15
16// Filter should be added to the filter chain just after the PanicFilter.
17// It sends errors to Bugsnag automatically. Configuration is read out of
18// conf/app.conf, you should set bugsnag.apikey, and can also set
19// bugsnag.endpoint, bugsnag.releasestage, bugsnag.appversion,
20// bugsnag.projectroot, bugsnag.projectpackages if needed.
21func Filter(c *revel.Controller, fc []revel.Filter) {
22	defer bugsnag.AutoNotify(c)
23	fc[0](c, fc[1:])
24}
25
26// Add support to bugsnag for reading data out of *revel.Controllers
27func middleware(event *bugsnag.Event, config *bugsnag.Configuration) error {
28	for _, datum := range event.RawData {
29		if controller, ok := datum.(*revel.Controller); ok {
30			// make the request visible to the builtin HttpMIddleware
31			event.RawData = append(event.RawData, controller.Request.Request)
32			event.Context = controller.Action
33			event.MetaData.AddStruct("Session", controller.Session)
34		}
35	}
36
37	return nil
38}
39
40func init() {
41	revel.OnAppStart(func() {
42		bugsnag.OnBeforeNotify(middleware)
43
44		var projectPackages []string
45		if packages, ok := revel.Config.String("bugsnag.projectpackages"); ok {
46			projectPackages = strings.Split(packages, ",")
47		} else {
48			projectPackages = []string{revel.ImportPath + "/app/*", revel.ImportPath + "/app"}
49		}
50
51		bugsnag.Configure(bugsnag.Configuration{
52			APIKey:          revel.Config.StringDefault("bugsnag.apikey", ""),
53			Endpoint:        revel.Config.StringDefault("bugsnag.endpoint", ""),
54			AppVersion:      revel.Config.StringDefault("bugsnag.appversion", ""),
55			ReleaseStage:    revel.Config.StringDefault("bugsnag.releasestage", revel.RunMode),
56			ProjectPackages: projectPackages,
57			Logger:          revel.ERROR,
58		})
59	})
60}
61