Skip to content

Commit 1f02c43

Browse files
committed
Offer unlimited log buffer size when scanning handler logs
Some users have complained that they cannot log lines longer than 16KB. A 16KB log line seems excessive, but this has been requested at least 2-3 times over the years. To enable the feature, set log_buffer_size to -1. This is not a default, because it is not as efficient as using a pre- determined buffer size. Tested by running curl with --data-binary and sending a 6.7M Go binary into a function with the 16KB maximum log line size set. That produced the error, when the size was set to -1, the output was written, albeit quite slowly. Signed-off-by: Alex Ellis (OpenFaaS Ltd) <[email protected]>
1 parent ef933c8 commit 1f02c43

File tree

2 files changed

+41
-15
lines changed

2 files changed

+41
-15
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ Environmental variables:
201201
| `jwt_auth` | For OpenFaaS for Enterprises customers only. When set to `true`, the watchdog will require a JWT token to be passed as a Bearer token in the Authorization header. This token can only be obtained through the OpenFaaS gateway using a token exchange using the `http://gateway.openfaas:8080` address as the authority. |
202202
| `jwt_auth_debug` | Print out debug messages from the JWT authentication process (OpenFaaS for Enterprises only). |
203203
| `jwt_auth_local` | When set to `true`, the watchdog will attempt to validate the JWT token using a port-forwarded or local gateway running at `http://127.0.0.1:8080` instead of attempting to reach it via an in-cluster service name (OpenFaaS for Enterprises only). |
204-
| `log_buffer_size` | The amount of bytes to read from stderr/stdout for log lines. When exceeded, the user will see an "bufio.Scanner: token too long" error. The default value is `bufio.MaxScanTokenSize` |
204+
| `log_buffer_size` | The amount of bytes to read from stderr/stdout for log lines. When exceeded, the user will see an "bufio.Scanner: token too long" error. The default value is `bufio.MaxScanTokenSize`. To turn off buffering for unlimited log line lengths, set this value to `-1` and `bufio.Reader` will be used which does not allocate a buffer. |
205205
| `log_call_id` | In HTTP mode, when printing a response code, content-length and timing, include the X-Call-Id header at the end of the line in brackets i.e. `[079d9ff9-d7b7-4e37-b195-5ad520e6f797]` or `[none]` when it's empty. Default: `false` |
206206
| `max_inflight` | Limit the maximum number of requests in flight, and return a HTTP status 429 when exceeded |
207207
| `mode` | The mode which of-watchdog operates in, Default `streaming` [see doc](#3-streaming-fork-modestreaming---default). Options are [http](#1-http-modehttp), [serialising fork](#2-serializing-fork-modeserializing), [streaming fork](#3-streaming-fork-modestreaming---default), [static](#4-static-modestatic) |

executor/logging.go

+40-14
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,6 @@ import (
1313
func bindLoggingPipe(name string, pipe io.Reader, output io.Writer, logPrefix bool, maxBufferSize int) {
1414
log.Printf("Started logging: %s from function.", name)
1515

16-
scanner := bufio.NewScanner(pipe)
17-
18-
buffer := make([]byte, maxBufferSize)
19-
scanner.Buffer(buffer, maxBufferSize)
20-
2116
logFlags := log.Flags()
2217
prefix := log.Prefix()
2318
if logPrefix == false {
@@ -27,16 +22,47 @@ func bindLoggingPipe(name string, pipe io.Reader, output io.Writer, logPrefix bo
2722

2823
logger := log.New(output, prefix, logFlags)
2924

30-
go func() {
31-
for scanner.Scan() {
32-
if logPrefix {
33-
logger.Printf("%s: %s", name, scanner.Text())
34-
} else {
35-
logger.Print(scanner.Text())
25+
if maxBufferSize >= 0 {
26+
go pipeBuffered(name, pipe, logger, logPrefix, maxBufferSize)
27+
} else {
28+
go pipeUnbuffered(name, pipe, logger, logPrefix)
29+
}
30+
}
31+
32+
func pipeBuffered(name string, pipe io.Reader, logger *log.Logger, logPrefix bool, maxBufferSize int) {
33+
buf := make([]byte, maxBufferSize)
34+
scanner := bufio.NewScanner(pipe)
35+
scanner.Buffer(buf, maxBufferSize)
36+
37+
for scanner.Scan() {
38+
if logPrefix {
39+
logger.Printf("%s: %s", name, scanner.Text())
40+
} else {
41+
logger.Print(scanner.Text())
42+
}
43+
}
44+
if err := scanner.Err(); err != nil {
45+
log.Printf("Error reading %s: %s", name, err)
46+
}
47+
}
48+
49+
func pipeUnbuffered(name string, pipe io.Reader, logger *log.Logger, logPrefix bool) {
50+
51+
r := bufio.NewReader(pipe)
52+
53+
for {
54+
line, err := r.ReadString('\n')
55+
if err != nil {
56+
if err != io.EOF {
57+
log.Printf("Error reading %s: %s", name, err)
3658
}
59+
break
3760
}
38-
if err := scanner.Err(); err != nil {
39-
log.Printf("Error scanning %s: %s", name, err.Error())
61+
if logPrefix {
62+
logger.Printf("%s: %s", name, line)
63+
} else {
64+
logger.Print(line)
4065
}
41-
}()
66+
}
67+
4268
}

0 commit comments

Comments
 (0)