mirror of
https://github.com/grafana/grafana.git
synced 2025-02-15 01:53:33 -06:00
* basic frontend Sentry integration * backend endpoint to capture sentry events * WIP! * log user email for frontend logs * remove debug logging * lint fixes * Fix type exports & property names Co-authored-by: Arve Knudsen <arve.knudsen@gmail.com> * additional struct naming fix * rename log endpoint, config section & interface * add sentry sample rate to config * refac to use EchoSrv * log user id * backend tests * tests for SentryEchoBackend * sentry echo backend tests * CustomEndpointTransport tests * Update pkg/api/frontend_logging_test.go Co-authored-by: Arve Knudsen <arve.knudsen@gmail.com> * Update conf/defaults.ini Co-authored-by: Arve Knudsen <arve.knudsen@gmail.com> * Update pkg/api/frontend_logging_test.go Co-authored-by: Arve Knudsen <arve.knudsen@gmail.com> * don't export unnecesasrily * update go.sum * get rid of Convey in tests, use stdlib * add sentry config to sample.ini * cleanup to set orig logging handler in test * Apply suggestions from code review Co-authored-by: Arve Knudsen <arve.knudsen@gmail.com> * PR feedback changes * lock sentry version Co-authored-by: Arve Knudsen <arve.knudsen@gmail.com>
91 lines
2.3 KiB
Go
91 lines
2.3 KiB
Go
package api
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
|
|
"github.com/getsentry/sentry-go"
|
|
"github.com/grafana/grafana/pkg/infra/log"
|
|
"github.com/grafana/grafana/pkg/models"
|
|
"github.com/inconshreveable/log15"
|
|
)
|
|
|
|
var frontendLogger = log.New("frontend")
|
|
|
|
type frontendSentryExceptionValue struct {
|
|
Value string `json:"value,omitempty"`
|
|
Type string `json:"type,omitempty"`
|
|
Stacktrace sentry.Stacktrace `json:"stacktrace,omitempty"`
|
|
}
|
|
|
|
type frontendSentryException struct {
|
|
Values []frontendSentryExceptionValue `json:"values,omitempty"`
|
|
}
|
|
|
|
type frontendSentryEvent struct {
|
|
*sentry.Event
|
|
Exception *frontendSentryException `json:"exception,omitempty"`
|
|
}
|
|
|
|
func (value *frontendSentryExceptionValue) FmtMessage() string {
|
|
return fmt.Sprintf("%s: %s", value.Type, value.Value)
|
|
}
|
|
|
|
func (value *frontendSentryExceptionValue) FmtStacktrace() string {
|
|
var stacktrace = value.FmtMessage()
|
|
for _, frame := range value.Stacktrace.Frames {
|
|
stacktrace += fmt.Sprintf("\n at %s (%s:%v:%v)", frame.Function, frame.Filename, frame.Lineno, frame.Colno)
|
|
}
|
|
return stacktrace
|
|
}
|
|
|
|
func (exception *frontendSentryException) FmtStacktraces() string {
|
|
var stacktraces []string
|
|
for _, value := range exception.Values {
|
|
stacktraces = append(stacktraces, value.FmtStacktrace())
|
|
}
|
|
return strings.Join(stacktraces, "\n\n")
|
|
}
|
|
|
|
func (event *frontendSentryEvent) ToLogContext() log15.Ctx {
|
|
var ctx = make(log15.Ctx)
|
|
ctx["url"] = event.Request.URL
|
|
ctx["user_agent"] = event.Request.Headers["User-Agent"]
|
|
ctx["event_id"] = event.EventID
|
|
ctx["original_timestamp"] = event.Timestamp
|
|
if event.Exception != nil {
|
|
ctx["stacktrace"] = event.Exception.FmtStacktraces()
|
|
}
|
|
if len(event.User.Email) > 0 {
|
|
ctx["user_email"] = event.User.Email
|
|
ctx["user_id"] = event.User.ID
|
|
}
|
|
|
|
return ctx
|
|
}
|
|
|
|
func (hs *HTTPServer) logFrontendMessage(c *models.ReqContext, event frontendSentryEvent) Response {
|
|
var msg = "unknown"
|
|
|
|
if len(event.Message) > 0 {
|
|
msg = event.Message
|
|
} else if event.Exception != nil && len(event.Exception.Values) > 0 {
|
|
msg = event.Exception.Values[0].FmtMessage()
|
|
}
|
|
|
|
var ctx = event.ToLogContext()
|
|
|
|
switch event.Level {
|
|
case sentry.LevelError:
|
|
frontendLogger.Error(msg, ctx)
|
|
case sentry.LevelWarning:
|
|
frontendLogger.Warn(msg, ctx)
|
|
case sentry.LevelDebug:
|
|
frontendLogger.Debug(msg, ctx)
|
|
default:
|
|
frontendLogger.Info(msg, ctx)
|
|
}
|
|
|
|
return Success("ok")
|
|
}
|