Merge pull request #80 from iron-io/stdin

Streams stderr from user functions and outputs a standard format for …
This commit is contained in:
Travis Reeder
2016-08-30 13:57:15 -07:00
committed by GitHub
5 changed files with 45 additions and 8 deletions

View File

@@ -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": {

37
api/runner/logger.go Normal file
View File

@@ -0,0 +1,37 @@
package runner
import (
"bufio"
"io"
"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
}
func NewFuncLogger(appName, path, function, requestID string) io.Writer {
r, w := io.Pipe()
funcLogger := &FuncLogger{
r: r,
w: w,
}
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() {
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)
}

View File

@@ -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,
@@ -147,7 +149,7 @@ func handleRunner(c *gin.Context) {
ID: reqID,
AppName: appName,
Stdout: &stdout,
Stderr: &stderr,
Stderr: stderr,
Env: envVars,
}
@@ -162,7 +164,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)
}
}

View File

@@ -7,7 +7,7 @@ import (
)
// Version of IronFunctions
var Version = "0.0.2"
var Version = "0.0.31"
func handleVersion(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"version": Version})

View File

@@ -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']