Frontend logging: Remove Sentry javascript agent support (#67493)
* remove Sentry * fix sourcemap resolve
This commit is contained in:
@@ -9,7 +9,6 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/getsentry/sentry-go"
|
||||
"github.com/go-kit/log"
|
||||
"github.com/go-kit/log/level"
|
||||
"github.com/stretchr/testify/assert"
|
||||
@@ -30,79 +29,6 @@ type SourceMapReadRecord struct {
|
||||
|
||||
type logScenarioFunc func(c *scenarioContext, logs map[string]interface{}, sourceMapReads []SourceMapReadRecord)
|
||||
|
||||
func logSentryEventScenario(t *testing.T, desc string, event frontendlogging.FrontendSentryEvent, fn logScenarioFunc) {
|
||||
t.Run(desc, func(t *testing.T) {
|
||||
var logcontent = make(map[string]interface{})
|
||||
logcontent["logger"] = "frontend"
|
||||
newfrontendLogger := log.Logger(log.LoggerFunc(func(keyvals ...interface{}) error {
|
||||
for i := 0; i < len(keyvals); i += 2 {
|
||||
logcontent[keyvals[i].(string)] = keyvals[i+1]
|
||||
}
|
||||
return nil
|
||||
}))
|
||||
|
||||
origHandler := frontendLogger.GetLogger()
|
||||
frontendLogger.Swap(level.NewFilter(newfrontendLogger, level.AllowInfo()))
|
||||
sourceMapReads := []SourceMapReadRecord{}
|
||||
|
||||
t.Cleanup(func() {
|
||||
frontendLogger.Swap(origHandler)
|
||||
})
|
||||
|
||||
sc := setupScenarioContext(t, "/log")
|
||||
|
||||
cdnRootURL, e := url.Parse("https://storage.googleapis.com/grafana-static-assets")
|
||||
require.NoError(t, e)
|
||||
|
||||
cfg := &setting.Cfg{
|
||||
StaticRootPath: "/staticroot",
|
||||
CDNRootURL: cdnRootURL,
|
||||
}
|
||||
|
||||
readSourceMap := func(dir string, path string) ([]byte, error) {
|
||||
sourceMapReads = append(sourceMapReads, SourceMapReadRecord{
|
||||
dir: dir,
|
||||
path: path,
|
||||
})
|
||||
if strings.Contains(path, "error") {
|
||||
return nil, errors.New("epic hard drive failure")
|
||||
}
|
||||
if strings.HasSuffix(path, "foo.js.map") {
|
||||
f, err := os.ReadFile("./frontendlogging/test-data/foo.js.map")
|
||||
require.NoError(t, err)
|
||||
return f, nil
|
||||
}
|
||||
return nil, os.ErrNotExist
|
||||
}
|
||||
|
||||
// fake plugin route so we will try to find a source map there
|
||||
pm := fakePluginStaticRouteResolver{
|
||||
routes: []*plugins.StaticRoute{
|
||||
{
|
||||
Directory: "/usr/local/telepathic-panel",
|
||||
PluginID: "telepathic",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
sourceMapStore := frontendlogging.NewSourceMapStore(cfg, &pm, readSourceMap)
|
||||
|
||||
loggingHandler := NewFrontendLogMessageHandler(sourceMapStore)
|
||||
|
||||
handler := routing.Wrap(func(c *contextmodel.ReqContext) response.Response {
|
||||
sc.context = c
|
||||
c.Req.Body = mockRequestBody(event)
|
||||
c.Req.Header.Add("Content-Type", "application/json")
|
||||
loggingHandler(nil, c.Context)
|
||||
return response.Success("ok")
|
||||
})
|
||||
|
||||
sc.m.Post(sc.url, handler)
|
||||
sc.fakeReqWithParams("POST", sc.url, map[string]string{}).exec()
|
||||
fn(sc, logcontent, sourceMapReads)
|
||||
})
|
||||
}
|
||||
|
||||
func logGrafanaJavascriptAgentEventScenario(t *testing.T, desc string, event frontendlogging.FrontendGrafanaJavascriptAgentEvent, fn logScenarioFunc) {
|
||||
t.Run(desc, func(t *testing.T) {
|
||||
var logcontent = make(map[string]interface{})
|
||||
@@ -176,216 +102,6 @@ func logGrafanaJavascriptAgentEventScenario(t *testing.T, desc string, event fro
|
||||
})
|
||||
}
|
||||
|
||||
func TestFrontendLoggingEndpointSentry(t *testing.T) {
|
||||
ts, err := time.Parse("2006-01-02T15:04:05.000Z", "2020-10-22T06:29:29.078Z")
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Run("FrontendLoggingEndpoint", func(t *testing.T) {
|
||||
request := sentry.Request{
|
||||
URL: "http://localhost:3000/",
|
||||
Headers: map[string]string{
|
||||
"User-Agent": "Chrome",
|
||||
},
|
||||
}
|
||||
|
||||
user := sentry.User{
|
||||
Email: "geralt@kaermorhen.com",
|
||||
ID: "45",
|
||||
}
|
||||
|
||||
event := sentry.Event{
|
||||
EventID: "123",
|
||||
Level: sentry.LevelError,
|
||||
Request: &request,
|
||||
Timestamp: ts,
|
||||
}
|
||||
|
||||
errorEvent := frontendlogging.FrontendSentryEvent{
|
||||
Event: &event,
|
||||
Exception: &frontendlogging.FrontendSentryException{
|
||||
Values: []frontendlogging.FrontendSentryExceptionValue{
|
||||
{
|
||||
Type: "UserError",
|
||||
Value: "Please replace user and try again",
|
||||
Stacktrace: sentry.Stacktrace{
|
||||
Frames: []sentry.Frame{
|
||||
{
|
||||
Function: "foofn",
|
||||
Filename: "foo.js",
|
||||
Lineno: 123,
|
||||
Colno: 23,
|
||||
},
|
||||
{
|
||||
Function: "barfn",
|
||||
Filename: "bar.js",
|
||||
Lineno: 113,
|
||||
Colno: 231,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
logSentryEventScenario(t, "Should log received error event", errorEvent,
|
||||
func(sc *scenarioContext, logs map[string]interface{}, sourceMapReads []SourceMapReadRecord) {
|
||||
assert.Equal(t, http.StatusAccepted, sc.resp.Code)
|
||||
assertContextContains(t, logs, "logger", "frontend")
|
||||
assertContextContains(t, logs, "url", errorEvent.Request.URL)
|
||||
assertContextContains(t, logs, "user_agent", errorEvent.Request.Headers["User-Agent"])
|
||||
assertContextContains(t, logs, "event_id", errorEvent.EventID)
|
||||
assertContextContains(t, logs, "original_timestamp", errorEvent.Timestamp)
|
||||
assertContextContains(t, logs, "stacktrace", `UserError: Please replace user and try again
|
||||
at foofn (foo.js:123:23)
|
||||
at barfn (bar.js:113:231)`)
|
||||
assert.NotContains(t, logs, "context")
|
||||
})
|
||||
|
||||
messageEvent := frontendlogging.FrontendSentryEvent{
|
||||
Event: &sentry.Event{
|
||||
EventID: "123",
|
||||
Level: sentry.LevelInfo,
|
||||
Request: &request,
|
||||
Timestamp: ts,
|
||||
Message: "hello world",
|
||||
User: user,
|
||||
},
|
||||
Exception: nil,
|
||||
}
|
||||
|
||||
logSentryEventScenario(t, "Should log received message event", messageEvent,
|
||||
func(sc *scenarioContext, logs map[string]interface{}, sourceMapReads []SourceMapReadRecord) {
|
||||
assert.Equal(t, http.StatusAccepted, sc.resp.Code)
|
||||
assert.Len(t, logs, 10)
|
||||
assertContextContains(t, logs, "logger", "frontend")
|
||||
assertContextContains(t, logs, "msg", "hello world")
|
||||
assertContextContains(t, logs, level.Key().(string), level.InfoValue())
|
||||
assertContextContains(t, logs, "logger", "frontend")
|
||||
assertContextContains(t, logs, "url", messageEvent.Request.URL)
|
||||
assertContextContains(t, logs, "user_agent", messageEvent.Request.Headers["User-Agent"])
|
||||
assertContextContains(t, logs, "event_id", messageEvent.EventID)
|
||||
assertContextContains(t, logs, "original_timestamp", messageEvent.Timestamp)
|
||||
assert.NotContains(t, logs, "stacktrace")
|
||||
assert.NotContains(t, logs, "context")
|
||||
assertContextContains(t, logs, "user_email", user.Email)
|
||||
assertContextContains(t, logs, "user_id", user.ID)
|
||||
})
|
||||
|
||||
eventWithContext := frontendlogging.FrontendSentryEvent{
|
||||
Event: &sentry.Event{
|
||||
EventID: "123",
|
||||
Level: sentry.LevelInfo,
|
||||
Request: &request,
|
||||
Timestamp: ts,
|
||||
Message: "hello world",
|
||||
User: user,
|
||||
Contexts: map[string]interface{}{
|
||||
"foo": map[string]interface{}{
|
||||
"one": "two",
|
||||
"three": 4,
|
||||
},
|
||||
"bar": "baz",
|
||||
},
|
||||
},
|
||||
Exception: nil,
|
||||
}
|
||||
|
||||
logSentryEventScenario(t, "Should log event context", eventWithContext,
|
||||
func(sc *scenarioContext, logs map[string]interface{}, sourceMapReads []SourceMapReadRecord) {
|
||||
assert.Equal(t, http.StatusAccepted, sc.resp.Code)
|
||||
assertContextContains(t, logs, "context_foo_one", "two")
|
||||
assertContextContains(t, logs, "context_foo_three", "4")
|
||||
assertContextContains(t, logs, "context_bar", "baz")
|
||||
})
|
||||
|
||||
errorEventForSourceMapping := frontendlogging.FrontendSentryEvent{
|
||||
Event: &event,
|
||||
Exception: &frontendlogging.FrontendSentryException{
|
||||
Values: []frontendlogging.FrontendSentryExceptionValue{
|
||||
{
|
||||
Type: "UserError",
|
||||
Value: "Please replace user and try again",
|
||||
Stacktrace: sentry.Stacktrace{
|
||||
Frames: []sentry.Frame{
|
||||
{
|
||||
Function: "foofn",
|
||||
Filename: "http://localhost:3000/public/build/moo/foo.js", // source map found and mapped, core
|
||||
Lineno: 2,
|
||||
Colno: 5,
|
||||
},
|
||||
{
|
||||
Function: "foofn",
|
||||
Filename: "http://localhost:3000/public/plugins/telepathic/foo.js", // plugin, source map found and mapped
|
||||
Lineno: 3,
|
||||
Colno: 10,
|
||||
},
|
||||
{
|
||||
Function: "explode",
|
||||
Filename: "http://localhost:3000/public/build/error.js", // reading source map throws error
|
||||
Lineno: 3,
|
||||
Colno: 10,
|
||||
},
|
||||
{
|
||||
Function: "wat",
|
||||
Filename: "http://localhost:3000/public/build/bar.js", // core, but source map not found on fs
|
||||
Lineno: 3,
|
||||
Colno: 10,
|
||||
},
|
||||
{
|
||||
Function: "nope",
|
||||
Filename: "http://localhost:3000/baz.js", // not core or plugin, wont even attempt to get source map
|
||||
Lineno: 3,
|
||||
Colno: 10,
|
||||
},
|
||||
{
|
||||
Function: "fake",
|
||||
Filename: "http://localhost:3000/public/build/../../secrets.txt", // path will be sanitized
|
||||
Lineno: 3,
|
||||
Colno: 10,
|
||||
},
|
||||
{
|
||||
Function: "cdn",
|
||||
Filename: "https://storage.googleapis.com/grafana-static-assets/grafana-oss/pre-releases/7.5.0-11925pre/public/build/foo.js", // source map found and mapped
|
||||
Lineno: 3,
|
||||
Colno: 10,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
logSentryEventScenario(t, "Should load sourcemap and transform stacktrace line when possible",
|
||||
errorEventForSourceMapping, func(sc *scenarioContext, logs map[string]interface{}, sourceMapReads []SourceMapReadRecord) {
|
||||
assert.Equal(t, http.StatusAccepted, sc.resp.Code)
|
||||
assert.Len(t, logs, 9)
|
||||
assertContextContains(t, logs, "stacktrace", `UserError: Please replace user and try again
|
||||
at ? (core|webpack:///./some_source.ts:2:2)
|
||||
at ? (telepathic|webpack:///./some_source.ts:3:2)
|
||||
at explode (http://localhost:3000/public/build/error.js:3:10)
|
||||
at wat (http://localhost:3000/public/build/bar.js:3:10)
|
||||
at nope (http://localhost:3000/baz.js:3:10)
|
||||
at fake (http://localhost:3000/public/build/../../secrets.txt:3:10)
|
||||
at ? (core|webpack:///./some_source.ts:3:2)`)
|
||||
assert.Len(t, sourceMapReads, 6)
|
||||
assert.Equal(t, "/staticroot", sourceMapReads[0].dir)
|
||||
assert.Equal(t, "build/moo/foo.js.map", sourceMapReads[0].path)
|
||||
assert.Equal(t, "/usr/local/telepathic-panel", sourceMapReads[1].dir)
|
||||
assert.Equal(t, "/foo.js.map", sourceMapReads[1].path)
|
||||
assert.Equal(t, "/staticroot", sourceMapReads[2].dir)
|
||||
assert.Equal(t, "build/error.js.map", sourceMapReads[2].path)
|
||||
assert.Equal(t, "/staticroot", sourceMapReads[3].dir)
|
||||
assert.Equal(t, "build/bar.js.map", sourceMapReads[3].path)
|
||||
assert.Equal(t, "/staticroot", sourceMapReads[4].dir)
|
||||
assert.Equal(t, "secrets.txt.map", sourceMapReads[4].path)
|
||||
assert.Equal(t, "/staticroot", sourceMapReads[5].dir)
|
||||
assert.Equal(t, "build/foo.js.map", sourceMapReads[5].path)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestFrontendLoggingEndpointGrafanaJavascriptAgent(t *testing.T) {
|
||||
ts, err := time.Parse("2006-01-02T15:04:05.000Z", "2020-10-22T06:29:29.078Z")
|
||||
require.NoError(t, err)
|
||||
@@ -536,13 +252,13 @@ func TestFrontendLoggingEndpointGrafanaJavascriptAgent(t *testing.T) {
|
||||
func(sc *scenarioContext, logs map[string]interface{}, sourceMapReads []SourceMapReadRecord) {
|
||||
assert.Equal(t, http.StatusAccepted, sc.resp.Code)
|
||||
assertContextContains(t, logs, "stacktrace", `UserError: Please replace user and try again
|
||||
at ? (webpack:///./some_source.ts:2:2)
|
||||
at ? (webpack:///./some_source.ts:3:2)
|
||||
at ? (core|webpack:///./some_source.ts:2:2)
|
||||
at ? (telepathic|webpack:///./some_source.ts:3:2)
|
||||
at explode (http://localhost:3000/public/build/error.js:3:10)
|
||||
at wat (http://localhost:3000/public/build/bar.js:3:10)
|
||||
at nope (http://localhost:3000/baz.js:3:10)
|
||||
at fake (http://localhost:3000/public/build/../../secrets.txt:3:10)
|
||||
at ? (webpack:///./some_source.ts:3:2)`)
|
||||
at ? (core|webpack:///./some_source.ts:3:2)`)
|
||||
assert.Len(t, sourceMapReads, 6)
|
||||
assert.Equal(t, "/staticroot", sourceMapReads[0].dir)
|
||||
assert.Equal(t, "build/moo/foo.js.map", sourceMapReads[0].path)
|
||||
|
||||
Reference in New Issue
Block a user