diff --git a/js/console.go b/js/console.go index 3a34ac4d650..e5dfac5fd18 100644 --- a/js/console.go +++ b/js/console.go @@ -23,7 +23,7 @@ package js import ( "context" "os" - "strconv" + "strings" "github.com/dop251/goja" "github.com/sirupsen/logrus" @@ -31,17 +31,17 @@ import ( // console represents a JS console implemented as a logrus.Logger. type console struct { - Logger *logrus.Logger + logger logrus.FieldLogger } // Creates a console with the standard logrus logger. func newConsole() *console { - return &console{logrus.StandardLogger()} + return &console{logrus.StandardLogger().WithField("source", "console")} } // Creates a console logger with its output set to the file at the provided `filepath`. func newFileConsole(filepath string) (*console, error) { - f, err := os.OpenFile(filepath, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0644) + f, err := os.OpenFile(filepath, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0644) //nolint:gosec if err != nil { return nil, err } @@ -49,7 +49,7 @@ func newFileConsole(filepath string) (*console, error) { l := logrus.New() l.SetOutput(f) - //TODO: refactor to not rely on global variables, albeit external ones + // TODO: refactor to not rely on global variables, albeit external ones l.SetFormatter(logrus.StandardLogger().Formatter) return &console{l}, nil @@ -64,21 +64,25 @@ func (c console) log(ctx *context.Context, level logrus.Level, msgobj goja.Value } } - fields := make(logrus.Fields) - for i, arg := range args { - fields[strconv.Itoa(i)] = arg.String() + msg := msgobj.String() + if len(args) > 0 { + strs := make([]string, 1+len(args)) + strs[0] = msg + for i, v := range args { + strs[i+1] = v.String() + } + + msg = strings.Join(strs, " ") } - msg := msgobj.ToString() - e := c.Logger.WithFields(fields) - switch level { + switch level { //nolint:exhaustive case logrus.DebugLevel: - e.Debug(msg) + c.logger.Debug(msg) case logrus.InfoLevel: - e.Info(msg) + c.logger.Info(msg) case logrus.WarnLevel: - e.Warn(msg) + c.logger.Warn(msg) case logrus.ErrorLevel: - e.Error(msg) + c.logger.Error(msg) } } diff --git a/js/console_test.go b/js/console_test.go index 159e329f1ae..9d6d8619ac8 100644 --- a/js/console_test.go +++ b/js/console_test.go @@ -70,6 +70,7 @@ func TestConsoleContext(t *testing.T) { assert.Equal(t, "b", entry.Message) } } + func getSimpleRunner(filename, data string, opts ...interface{}) (*Runner, error) { var ( fs = afero.NewMemMapFs() @@ -93,6 +94,16 @@ func getSimpleRunner(filename, data string, opts ...interface{}) (*Runner, error ) } +func extractLogger(fl logrus.FieldLogger) *logrus.Logger { + switch e := fl.(type) { + case *logrus.Entry: + return e.Logger + case *logrus.Logger: + return e + } + return nil +} + func TestConsole(t *testing.T) { levels := map[string]logrus.Level{ "log": logrus.InfoLevel, @@ -105,10 +116,10 @@ func TestConsole(t *testing.T) { Message string Data logrus.Fields }{ - `"string"`: {Message: "string"}, - `"string","a","b"`: {Message: "string", Data: logrus.Fields{"0": "a", "1": "b"}}, - `"string",1,2`: {Message: "string", Data: logrus.Fields{"0": "1", "1": "2"}}, - `{}`: {Message: "[object Object]"}, + `"string"`: {Message: "string", Data: logrus.Fields{"source": "console"}}, + `"string","a","b"`: {Message: "string a b", Data: logrus.Fields{"source": "console"}}, + `"string",1,2`: {Message: "string 1 2", Data: logrus.Fields{"source": "console"}}, + `{}`: {Message: "[object Object]", Data: logrus.Fields{"source": "console"}}, } for name, level := range levels { name, level := name, level @@ -130,10 +141,11 @@ func TestConsole(t *testing.T) { defer cancel() vu := initVU.Activate(&lib.VUActivationParams{RunContext: ctx}) - logger, hook := logtest.NewNullLogger() + logger := extractLogger(vu.(*ActiveVU).Console.logger) + + logger.Out = ioutil.Discard logger.Level = logrus.DebugLevel - jsVU := vu.(*ActiveVU) - jsVU.Console.Logger = logger + hook := logtest.NewLocal(logger) err = vu.RunOnce() assert.NoError(t, err) @@ -168,10 +180,10 @@ func TestFileConsole(t *testing.T) { Message string Data logrus.Fields }{ - `"string"`: {Message: "string"}, - `"string","a","b"`: {Message: "string", Data: logrus.Fields{"0": "a", "1": "b"}}, - `"string",1,2`: {Message: "string", Data: logrus.Fields{"0": "1", "1": "2"}}, - `{}`: {Message: "[object Object]"}, + `"string"`: {Message: "string", Data: logrus.Fields{}}, + `"string","a","b"`: {Message: "string a b", Data: logrus.Fields{}}, + `"string",1,2`: {Message: "string 1 2", Data: logrus.Fields{}}, + `{}`: {Message: "[object Object]", Data: logrus.Fields{}}, } preExisting = map[string]bool{ "log exists": false, @@ -186,11 +198,11 @@ func TestFileConsole(t *testing.T) { // whether the file is existed before logging for msg, deleteFile := range preExisting { t.Run(msg, func(t *testing.T) { - var f, err = ioutil.TempFile("", "") + f, err := ioutil.TempFile("", "") if err != nil { t.Fatalf("Couldn't create temporary file for testing: %s", err) } - var logFilename = f.Name() + logFilename := f.Name() defer os.Remove(logFilename) // close it as we will want to reopen it and maybe remove it if deleteFile { @@ -200,8 +212,8 @@ func TestFileConsole(t *testing.T) { } } else { // TODO: handle case where the string was no written in full ? - _, err := f.WriteString(preExistingText) - f.Close() + _, err = f.WriteString(preExistingText) + _ = f.Close() if err != nil { t.Fatalf("Error while writing text to preexisting logfile: %s", err) } @@ -226,9 +238,10 @@ func TestFileConsole(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() vu := initVU.Activate(&lib.VUActivationParams{RunContext: ctx}) - jsVU := vu.(*ActiveVU) - jsVU.Console.Logger.Level = logrus.DebugLevel - hook := logtest.NewLocal(jsVU.Console.Logger) + logger := extractLogger(vu.(*ActiveVU).Console.logger) + + logger.Level = logrus.DebugLevel + hook := logtest.NewLocal(logger) err = vu.RunOnce() assert.NoError(t, err) @@ -259,13 +272,12 @@ func TestFileConsole(t *testing.T) { fileContent, err := ioutil.ReadAll(f) assert.NoError(t, err) - var expectedStr = entryStr + expectedStr := entryStr if !deleteFile { expectedStr = preExistingText + expectedStr } assert.Equal(t, expectedStr, string(fileContent)) } - }) } }) diff --git a/lib/executor/helpers.go b/lib/executor/helpers.go index 46fdf3c432d..108b1b32963 100644 --- a/lib/executor/helpers.go +++ b/lib/executor/helpers.go @@ -97,7 +97,9 @@ func getIterationRunner( default: if err != nil { if s, ok := err.(fmt.Stringer); ok { - logger.Error(s.String()) + // TODO better detection for stack traces + // TODO don't count this as a full iteration? + logger.WithField("source", "stacktrace").Error(s.String()) } else { logger.Error(err.Error()) } diff --git a/lib/netext/httpext/httpdebug_transport.go b/lib/netext/httpext/httpdebug_transport.go index 8cd37026e17..eab3b67f8cf 100644 --- a/lib/netext/httpext/httpdebug_transport.go +++ b/lib/netext/httpext/httpdebug_transport.go @@ -21,7 +21,7 @@ package httpext import ( - "fmt" + "bytes" "net/http" "net/http/httputil" @@ -29,9 +29,9 @@ import ( ) type httpDebugTransport struct { - //TODO: get the state and log to its Logger originalTransport http.RoundTripper httpDebugOption string + logger logrus.FieldLogger } // RoundTrip prints passing HTTP requests and received responses @@ -50,17 +50,17 @@ func (t httpDebugTransport) RoundTrip(req *http.Request) (*http.Response, error) func (t httpDebugTransport) debugRequest(req *http.Request) { dump, err := httputil.DumpRequestOut(req, t.httpDebugOption == "full") if err != nil { - logrus.Error(err) + t.logger.Error(err) } - fmt.Printf("Request:\n%s\n", dump) //TODO: fix... + t.logger.Infof("Request:\n%s\n", bytes.ReplaceAll(dump, []byte("\r\n"), []byte{'\n'})) } func (t httpDebugTransport) debugResponse(res *http.Response) { if res != nil { dump, err := httputil.DumpResponse(res, t.httpDebugOption == "full") if err != nil { - logrus.Error(err) + t.logger.Error(err) } - fmt.Printf("Response:\n%s\n", dump) //TODO: fix... + t.logger.Infof("Response:\n%s\n", bytes.ReplaceAll(dump, []byte("\r\n"), []byte{'\n'})) } } diff --git a/lib/netext/httpext/request.go b/lib/netext/httpext/request.go index 6e814429164..2f1f8076a4d 100644 --- a/lib/netext/httpext/request.go +++ b/lib/netext/httpext/request.go @@ -261,6 +261,7 @@ func MakeRequest(ctx context.Context, preq *ParsedHTTPRequest) (*Response, error transport = httpDebugTransport{ originalTransport: transport, httpDebugOption: state.Options.HTTPDebug.String, + logger: state.Logger.WithField("source", "http-debug"), } }