1
1
package executor
2
2
3
3
import (
4
+ "bufio"
4
5
"bytes"
5
6
"encoding/json"
6
7
"fmt"
@@ -77,17 +78,18 @@ type proxyJSONLogger struct {
77
78
logProxyHookJSON bool
78
79
}
79
80
80
- func (pj * proxyJSONLogger ) Write (p []byte ) (n int , err error ) {
81
- pj .buf = append (pj .buf , p ... )
82
-
81
+ func (pj * proxyJSONLogger ) Write (p []byte ) (int , error ) {
83
82
if ! pj .logProxyHookJSON {
84
- pj .Entry . Log ( log . InfoLevel , strings . TrimSpace ( string ( pj . buf )) )
83
+ pj .writerScanner ( p )
85
84
86
85
return len (p ), nil
87
86
}
88
87
88
+ // join all parts of json
89
+ pj .buf = append (pj .buf , p ... )
90
+
89
91
var line interface {}
90
- err = json .Unmarshal (pj .buf , & line )
92
+ err : = json .Unmarshal (pj .buf , & line )
91
93
if err != nil {
92
94
if err .Error () == "unexpected end of JSON input" {
93
95
return len (p ), nil
@@ -107,15 +109,67 @@ func (pj *proxyJSONLogger) Write(p []byte) (n int, err error) {
107
109
logMap [k ] = v
108
110
}
109
111
110
- logLine , _ := json .Marshal (logMap )
112
+ logLineRaw , _ := json .Marshal (logMap )
113
+
114
+ logLine := string (logLineRaw )
111
115
112
116
logEntry := pj .WithField (app .ProxyJsonLogKey , true )
113
117
118
+ if len (logLine ) > 10000 {
119
+ logLine = fmt .Sprintf ("%s:truncated" , string (logLine [:10000 ]))
120
+
121
+ truncatedLog , _ := json .Marshal (map [string ]string {
122
+ "truncated" : logLine ,
123
+ })
124
+
125
+ logEntry .Log (log .FatalLevel , string (truncatedLog ))
126
+ }
127
+
114
128
logEntry .Log (log .FatalLevel , string (logLine ))
115
129
116
130
return len (p ), nil
117
131
}
118
132
133
+ func (pj * proxyJSONLogger ) writerScanner (p []byte ) {
134
+ scanner := bufio .NewScanner (bytes .NewReader (p ))
135
+
136
+ // Set the buffer size to the maximum token size to avoid buffer overflows
137
+ scanner .Buffer (make ([]byte , bufio .MaxScanTokenSize ), bufio .MaxScanTokenSize )
138
+
139
+ // Define a split function to split the input into chunks of up to 64KB
140
+ chunkSize := bufio .MaxScanTokenSize // 64KB
141
+ splitFunc := func (data []byte , atEOF bool ) (int , []byte , error ) {
142
+ if len (data ) >= chunkSize {
143
+ return chunkSize , data [:chunkSize ], nil
144
+ }
145
+
146
+ return bufio .ScanLines (data , atEOF )
147
+ }
148
+
149
+ // Use the custom split function to split the input
150
+ scanner .Split (splitFunc )
151
+
152
+ // Scan the input and write it to the logger using the specified print function
153
+ for scanner .Scan () {
154
+ // prevent empty logging
155
+ str := strings .TrimSpace (scanner .Text ())
156
+ if str == "" {
157
+ continue
158
+ }
159
+
160
+ if len (str ) > 10000 {
161
+ str = fmt .Sprintf ("%s:truncated" , str [:10000 ])
162
+ }
163
+
164
+ pj .Entry .Info (str )
165
+ }
166
+
167
+ // If there was an error while scanning the input, log an error
168
+ if err := scanner .Err (); err != nil {
169
+ pj .Entry .Errorf ("Error while reading from Writer: %s" , err )
170
+ }
171
+ }
172
+
119
173
func Output (cmd * exec.Cmd ) (output []byte , err error ) {
120
174
// TODO context: hook name, hook phase, hook binding
121
175
// TODO observability
0 commit comments