From f7d4fed570a407b7ceffb0204377b6162b3b97dc Mon Sep 17 00:00:00 2001 From: Travis Reeder Date: Mon, 29 Aug 2016 22:59:16 -0700 Subject: [PATCH 1/5] Streams stderr from user functions and outputs a standard format for parsing. See #76. --- README.md | 4 +--- api/runner/logger.go | 37 +++++++++++++++++++++++++++++++++++++ api/server/runner.go | 8 +++++--- examples/hello/hello.rb | 2 +- 4 files changed, 44 insertions(+), 7 deletions(-) create mode 100644 api/runner/logger.go diff --git a/README.md b/README.md index 9d8678df5..ab16dfce3 100644 --- a/README.md +++ b/README.md @@ -23,12 +23,10 @@ curl -H "Content-Type: application/json" -X POST -d '{ }' http://localhost:8080/v1/apps ``` -Now that we have an app, we can add routes to functions. +Now that we have an app, we can map routes to functions. ### Add a route to a Function - - ```sh curl -H "Content-Type: application/json" -X POST -d '{ "route": { diff --git a/api/runner/logger.go b/api/runner/logger.go new file mode 100644 index 000000000..29d625e60 --- /dev/null +++ b/api/runner/logger.go @@ -0,0 +1,37 @@ +// This reads STDERR output from a container and outputs it in a parseable structured log format, see: https://github.com/iron-io/functions/issues/76 +package runner + +import ( + "bufio" + "io" + + "github.com/Sirupsen/logrus" +) + +type FuncLogger struct { + r io.Reader + w io.Writer +} + +func NewFuncLogger(appName, path, function, requestID string) io.Writer { + r, w := io.Pipe() + funcLogger := &FuncLogger{ + r: r, + w: w, + } + log := logrus.WithFields(logrus.Fields{"app_name": appName, "path": path, "function": function, "request_id": requestID}) + go func(reader io.Reader) { + scanner := bufio.NewScanner(reader) + for scanner.Scan() { + log.Println(scanner.Text()) + } + if err := scanner.Err(); err != nil { + log.WithError(err).Println("There was an error with the scanner in attached container") + } + }(r) + return funcLogger +} + +func (l *FuncLogger) Write(p []byte) (n int, err error) { + return l.w.Write(p) +} diff --git a/api/server/runner.go b/api/server/runner.go index 3be2d3be7..72f2bf984 100644 --- a/api/server/runner.go +++ b/api/server/runner.go @@ -112,7 +112,9 @@ func handleRunner(c *gin.Context) { log.WithField("routes", routes).Debug("Got routes from datastore") for _, el := range routes { if params, match := matchRoute(el.Path, route); match { - var stdout, stderr bytes.Buffer + + var stdout bytes.Buffer // TODO: should limit the size of this, error if gets too big. akin to: https://golang.org/pkg/io/#LimitReader + stderr := runner.NewFuncLogger(appName, route, el.Image, reqID) envVars := map[string]string{ "METHOD": c.Request.Method, @@ -142,7 +144,7 @@ func handleRunner(c *gin.Context) { ID: reqID, AppName: appName, Stdout: &stdout, - Stderr: &stderr, + Stderr: stderr, Env: envVars, } @@ -157,7 +159,7 @@ func handleRunner(c *gin.Context) { if result.Status() == "success" { c.Data(http.StatusOK, "", stdout.Bytes()) } else { - log.WithFields(logrus.Fields{"app": appName, "route": el, "req_id": reqID}).Debug(stderr.String()) + // log.WithFields(logrus.Fields{"app": appName, "route": el, "req_id": reqID}).Debug(stderr.String()) c.AbortWithStatus(http.StatusInternalServerError) } } diff --git a/examples/hello/hello.rb b/examples/hello/hello.rb index 71ec89bba..f171f4b03 100644 --- a/examples/hello/hello.rb +++ b/examples/hello/hello.rb @@ -6,7 +6,7 @@ name = "World" # or using env vars: ENV['PAYLOAD'] payload = ENV['PAYLOAD'] -puts 'ARGF: ' + payload.inspect +STDERR.puts 'payload: ' + payload.inspect if payload != "" payload = JSON.parse(payload) name = payload['name'] From 45f5354d8bab7bfa71ace2fe8a6793f020a596a7 Mon Sep 17 00:00:00 2001 From: Travis Reeder Date: Mon, 29 Aug 2016 23:00:36 -0700 Subject: [PATCH 2/5] Updated comment. --- api/runner/logger.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/runner/logger.go b/api/runner/logger.go index 29d625e60..41b50778c 100644 --- a/api/runner/logger.go +++ b/api/runner/logger.go @@ -1,4 +1,3 @@ -// This reads STDERR output from a container and outputs it in a parseable structured log format, see: https://github.com/iron-io/functions/issues/76 package runner import ( @@ -8,6 +7,7 @@ import ( "github.com/Sirupsen/logrus" ) +// FuncLogger reads STDERR output from a container and outputs it in a parseable structured log format, see: https://github.com/iron-io/functions/issues/76 type FuncLogger struct { r io.Reader w io.Writer From b5e0887e3740eb166ed1f5c59d7f216873c53688 Mon Sep 17 00:00:00 2001 From: Travis Reeder Date: Mon, 29 Aug 2016 23:53:48 -0700 Subject: [PATCH 3/5] Added user_log=true to user log lines. --- api/runner/logger.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/runner/logger.go b/api/runner/logger.go index 41b50778c..ad8042de4 100644 --- a/api/runner/logger.go +++ b/api/runner/logger.go @@ -19,7 +19,7 @@ func NewFuncLogger(appName, path, function, requestID string) io.Writer { r: r, w: w, } - log := logrus.WithFields(logrus.Fields{"app_name": appName, "path": path, "function": function, "request_id": requestID}) + log := logrus.WithFields(logrus.Fields{"user_log": true, "app_name": appName, "path": path, "function": function, "request_id": requestID}) go func(reader io.Reader) { scanner := bufio.NewScanner(reader) for scanner.Scan() { From 7192b86af2de145eec36333447ef117b3f3794d0 Mon Sep 17 00:00:00 2001 From: Travis Reeder Date: Tue, 30 Aug 2016 01:05:03 -0700 Subject: [PATCH 4/5] functions: 0.0.3 release --- api/server/version.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/server/version.go b/api/server/version.go index da1f285d8..d77da1b91 100644 --- a/api/server/version.go +++ b/api/server/version.go @@ -7,7 +7,7 @@ import ( ) // Version of IronFunctions -var Version = "0.0.2" +var Version = "0.0.3" func handleVersion(c *gin.Context) { c.JSON(http.StatusOK, gin.H{"version": Version}) From 2b486bc235ad492453dca93e93adc95903b337d0 Mon Sep 17 00:00:00 2001 From: Travis Reeder Date: Tue, 30 Aug 2016 01:06:56 -0700 Subject: [PATCH 5/5] functions: 0.0.31 release --- api/server/version.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/server/version.go b/api/server/version.go index d77da1b91..75d08b37d 100644 --- a/api/server/version.go +++ b/api/server/version.go @@ -7,7 +7,7 @@ import ( ) // Version of IronFunctions -var Version = "0.0.3" +var Version = "0.0.31" func handleVersion(c *gin.Context) { c.JSON(http.StatusOK, gin.H{"version": Version})