package gobrake import ( "fmt" "net/http" "os" "path/filepath" "runtime" ) var defaultContext map[string]interface{} func getDefaultContext() map[string]interface{} { if defaultContext != nil { return defaultContext } defaultContext = map[string]interface{}{ "notifier": map[string]interface{}{ "name": "gobrake", "version": "2.0.4", "url": "https://github.com/airbrake/gobrake", }, "language": runtime.Version(), "os": runtime.GOOS, "architecture": runtime.GOARCH, } if s, err := os.Hostname(); err == nil { defaultContext["hostname"] = s } if s := os.Getenv("GOPATH"); s != "" { list := filepath.SplitList(s) // TODO: multiple root dirs? defaultContext["rootDirectory"] = list[0] } return defaultContext } type Error struct { Type string `json:"type"` Message string `json:"message"` Backtrace []StackFrame `json:"backtrace"` } type Notice struct { Errors []Error `json:"errors"` Context map[string]interface{} `json:"context"` Env map[string]interface{} `json:"environment"` Session map[string]interface{} `json:"session"` Params map[string]interface{} `json:"params"` } func (n *Notice) String() string { if len(n.Errors) == 0 { return "Notice<no errors>" } e := n.Errors[0] return fmt.Sprintf("Notice<%s: %s>", e.Type, e.Message) } func NewNotice(e interface{}, req *http.Request, depth int) *Notice { notice := &Notice{ Errors: []Error{{ Type: fmt.Sprintf("%T", e), Message: fmt.Sprint(e), Backtrace: stack(depth), }}, Context: map[string]interface{}{}, Env: map[string]interface{}{}, Session: map[string]interface{}{}, Params: map[string]interface{}{}, } for k, v := range getDefaultContext() { notice.Context[k] = v } if req != nil { notice.Context["url"] = req.URL.String() if ua := req.Header.Get("User-Agent"); ua != "" { notice.Context["userAgent"] = ua } for k, v := range req.Header { if len(v) == 1 { notice.Env[k] = v[0] } else { notice.Env[k] = v } } if err := req.ParseForm(); err == nil { for k, v := range req.Form { if len(v) == 1 { notice.Params[k] = v[0] } else { notice.Params[k] = v } } } } return notice }