diff --git a/go.mod b/go.mod index 974cc27..63bab4d 100644 --- a/go.mod +++ b/go.mod @@ -19,7 +19,7 @@ require ( require ( github.com/dcilke/gu v0.1.0 - github.com/dcilke/heron v0.1.0 + github.com/dcilke/heron v0.2.0 github.com/kylelemons/godebug v1.1.0 // indirect github.com/mattn/go-isatty v0.0.14 // indirect golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6 // indirect diff --git a/go.sum b/go.sum index 094b383..10d9cb4 100644 --- a/go.sum +++ b/go.sum @@ -8,8 +8,8 @@ github.com/dcilke/golden v0.1.0 h1:5TRihP8pdy/h5I++ypFGKXT6CrI1y1Jn+2Nw/7qc9Ko= github.com/dcilke/golden v0.1.0/go.mod h1:KxQFVmzRGf7A9jPbCMXIDr9kQxwnZZ7i07wWyihuhNU= github.com/dcilke/gu v0.1.0 h1:oxkaeVJ+AzC992otWFqt2gku4U/VyzO62ZscWOUbQ9M= github.com/dcilke/gu v0.1.0/go.mod h1:8lZQPS+FeUGA7Lc3YAaG+cEYA0VAUYBKBGACsCkpgzI= -github.com/dcilke/heron v0.1.0 h1:/t9SOiESJbBrpxkkRhcOQTEdqRtW/vcGW9w6K66lxcc= -github.com/dcilke/heron v0.1.0/go.mod h1:f9h5pFjBLvwc8tJfrbejvI9yOm3KEx2f6HOXLf/NWRw= +github.com/dcilke/heron v0.2.0 h1:PNiaekqB4wspS85/f5CJzUBhmxVsBglFwx91Ve174Bk= +github.com/dcilke/heron v0.2.0/go.mod h1:f9h5pFjBLvwc8tJfrbejvI9yOm3KEx2f6HOXLf/NWRw= github.com/jessevdk/go-flags v1.5.0 h1:1jKYvbxEjfUl0fmqTCOfonvskHHXMjBySTLW4y9LFvc= github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= diff --git a/integration/cli_test.go b/integration/cli_test.go index cd16617..7be5d91 100644 --- a/integration/cli_test.go +++ b/integration/cli_test.go @@ -7,7 +7,7 @@ import ( "github.com/stretchr/testify/require" ) -var filecases = []string{"strings", "ndjson", "pretty", "array"} +var filecases = []string{"strings", "ndjson", "pretty", "array", "mixed"} var levels = []string{"trace", "debug", "info", "warn", "error", "fatal", "panic"} func TestCLI(t *testing.T) { diff --git a/integration/testdata/golden/TestCLI/mixed b/integration/testdata/golden/TestCLI/mixed new file mode 100644 index 0000000..7ab8f5e --- /dev/null +++ b/integration/testdata/golden/TestCLI/mixed @@ -0,0 +1,11 @@ +servicea 12:34:25 TRC yup module=http +servicea 12:34:25 DBG yeah module=http +servicea 12:34:26 INF here module=http +serviceb 12:34:26 WRN warning, something is suspicious module=grpc +servicea 12:34:27 ERR hit module=http +serviceb 12:34:27 WRN this shouldn't happen module=grpc +servicea 12:34:28 WRN seriously?!? module=grpc +serviceb 12:34:28 FTL fatal module=http +servicea 12:34:29 PNC panic! module=http +serviceb 12:34:29 DBG wat module=search +servicea 12:34:29 DBG request elapsed=8.268013 method=GET module=search statusCode=200 url={"domain":"localhost","full":"www.example.com","original":"https://original.url","path":"/yo","port":80,"scheme":"http"} diff --git a/integration/testdata/golden/TestCLI/strings b/integration/testdata/golden/TestCLI/strings index 3b26f16..ab69ebe 100644 --- a/integration/testdata/golden/TestCLI/strings +++ b/integration/testdata/golden/TestCLI/strings @@ -11,5 +11,6 @@ msg 10 42.42 2015-01-01T00:00:00.000Z + a b c d e f g h i j k l m n o p q r s t u v w x y z tabs tabs tabs diff --git a/integration/testdata/golden/TestCLI_Level/mixed/debug b/integration/testdata/golden/TestCLI_Level/mixed/debug new file mode 100644 index 0000000..b17e6c4 --- /dev/null +++ b/integration/testdata/golden/TestCLI_Level/mixed/debug @@ -0,0 +1,11 @@ +servicea +servicea 12:34:25 DBG yeah module=http +servicea +serviceb +servicea +serviceb +servicea +serviceb +servicea +serviceb 12:34:29 DBG wat module=search +servicea 12:34:29 DBG request elapsed=8.268013 method=GET module=search statusCode=200 url={"domain":"localhost","full":"www.example.com","original":"https://original.url","path":"/yo","port":80,"scheme":"http"} diff --git a/integration/testdata/golden/TestCLI_Level/mixed/error b/integration/testdata/golden/TestCLI_Level/mixed/error new file mode 100644 index 0000000..6994a05 --- /dev/null +++ b/integration/testdata/golden/TestCLI_Level/mixed/error @@ -0,0 +1,11 @@ +servicea +servicea +servicea +serviceb +servicea 12:34:27 ERR hit module=http +serviceb +servicea +serviceb +servicea +serviceb +servicea diff --git a/integration/testdata/golden/TestCLI_Level/mixed/fatal b/integration/testdata/golden/TestCLI_Level/mixed/fatal new file mode 100644 index 0000000..8b6e18b --- /dev/null +++ b/integration/testdata/golden/TestCLI_Level/mixed/fatal @@ -0,0 +1,11 @@ +servicea +servicea +servicea +serviceb +servicea +serviceb +servicea +serviceb 12:34:28 FTL fatal module=http +servicea +serviceb +servicea diff --git a/integration/testdata/golden/TestCLI_Level/mixed/info b/integration/testdata/golden/TestCLI_Level/mixed/info new file mode 100644 index 0000000..5320f98 --- /dev/null +++ b/integration/testdata/golden/TestCLI_Level/mixed/info @@ -0,0 +1,11 @@ +servicea +servicea +servicea 12:34:26 INF here module=http +serviceb +servicea +serviceb +servicea +serviceb +servicea +serviceb +servicea diff --git a/integration/testdata/golden/TestCLI_Level/mixed/panic b/integration/testdata/golden/TestCLI_Level/mixed/panic new file mode 100644 index 0000000..70c2d43 --- /dev/null +++ b/integration/testdata/golden/TestCLI_Level/mixed/panic @@ -0,0 +1,11 @@ +servicea +servicea +servicea +serviceb +servicea +serviceb +servicea +serviceb +servicea 12:34:29 PNC panic! module=http +serviceb +servicea diff --git a/integration/testdata/golden/TestCLI_Level/mixed/trace b/integration/testdata/golden/TestCLI_Level/mixed/trace new file mode 100644 index 0000000..f879fe5 --- /dev/null +++ b/integration/testdata/golden/TestCLI_Level/mixed/trace @@ -0,0 +1,11 @@ +servicea 12:34:25 TRC yup module=http +servicea +servicea +serviceb +servicea +serviceb +servicea +serviceb +servicea +serviceb +servicea diff --git a/integration/testdata/golden/TestCLI_Level/mixed/warn b/integration/testdata/golden/TestCLI_Level/mixed/warn new file mode 100644 index 0000000..ff0873c --- /dev/null +++ b/integration/testdata/golden/TestCLI_Level/mixed/warn @@ -0,0 +1,11 @@ +servicea +servicea +servicea +serviceb 12:34:26 WRN warning, something is suspicious module=grpc +servicea +serviceb 12:34:27 WRN this shouldn't happen module=grpc +servicea 12:34:28 WRN seriously?!? module=grpc +serviceb +servicea +serviceb +servicea diff --git a/integration/testdata/golden/TestCLI_Level/strings/debug b/integration/testdata/golden/TestCLI_Level/strings/debug index 3b26f16..ab69ebe 100644 --- a/integration/testdata/golden/TestCLI_Level/strings/debug +++ b/integration/testdata/golden/TestCLI_Level/strings/debug @@ -11,5 +11,6 @@ msg 10 42.42 2015-01-01T00:00:00.000Z + a b c d e f g h i j k l m n o p q r s t u v w x y z tabs tabs tabs diff --git a/integration/testdata/golden/TestCLI_Level/strings/error b/integration/testdata/golden/TestCLI_Level/strings/error index 3b26f16..ab69ebe 100644 --- a/integration/testdata/golden/TestCLI_Level/strings/error +++ b/integration/testdata/golden/TestCLI_Level/strings/error @@ -11,5 +11,6 @@ msg 10 42.42 2015-01-01T00:00:00.000Z + a b c d e f g h i j k l m n o p q r s t u v w x y z tabs tabs tabs diff --git a/integration/testdata/golden/TestCLI_Level/strings/fatal b/integration/testdata/golden/TestCLI_Level/strings/fatal index 3b26f16..ab69ebe 100644 --- a/integration/testdata/golden/TestCLI_Level/strings/fatal +++ b/integration/testdata/golden/TestCLI_Level/strings/fatal @@ -11,5 +11,6 @@ msg 10 42.42 2015-01-01T00:00:00.000Z + a b c d e f g h i j k l m n o p q r s t u v w x y z tabs tabs tabs diff --git a/integration/testdata/golden/TestCLI_Level/strings/info b/integration/testdata/golden/TestCLI_Level/strings/info index 3b26f16..ab69ebe 100644 --- a/integration/testdata/golden/TestCLI_Level/strings/info +++ b/integration/testdata/golden/TestCLI_Level/strings/info @@ -11,5 +11,6 @@ msg 10 42.42 2015-01-01T00:00:00.000Z + a b c d e f g h i j k l m n o p q r s t u v w x y z tabs tabs tabs diff --git a/integration/testdata/golden/TestCLI_Level/strings/panic b/integration/testdata/golden/TestCLI_Level/strings/panic index 3b26f16..ab69ebe 100644 --- a/integration/testdata/golden/TestCLI_Level/strings/panic +++ b/integration/testdata/golden/TestCLI_Level/strings/panic @@ -11,5 +11,6 @@ msg 10 42.42 2015-01-01T00:00:00.000Z + a b c d e f g h i j k l m n o p q r s t u v w x y z tabs tabs tabs diff --git a/integration/testdata/golden/TestCLI_Level/strings/trace b/integration/testdata/golden/TestCLI_Level/strings/trace index 3b26f16..ab69ebe 100644 --- a/integration/testdata/golden/TestCLI_Level/strings/trace +++ b/integration/testdata/golden/TestCLI_Level/strings/trace @@ -11,5 +11,6 @@ msg 10 42.42 2015-01-01T00:00:00.000Z + a b c d e f g h i j k l m n o p q r s t u v w x y z tabs tabs tabs diff --git a/integration/testdata/golden/TestCLI_Level/strings/warn b/integration/testdata/golden/TestCLI_Level/strings/warn index 3b26f16..ab69ebe 100644 --- a/integration/testdata/golden/TestCLI_Level/strings/warn +++ b/integration/testdata/golden/TestCLI_Level/strings/warn @@ -11,5 +11,6 @@ msg 10 42.42 2015-01-01T00:00:00.000Z + a b c d e f g h i j k l m n o p q r s t u v w x y z tabs tabs tabs diff --git a/integration/testdata/golden/TestCLI_Strict/mixed b/integration/testdata/golden/TestCLI_Strict/mixed new file mode 100644 index 0000000..8529345 --- /dev/null +++ b/integration/testdata/golden/TestCLI_Strict/mixed @@ -0,0 +1,11 @@ +12:34:25 TRC yup module=http +12:34:25 DBG yeah module=http +12:34:26 INF here module=http +12:34:26 WRN warning, something is suspicious module=grpc +12:34:27 ERR hit module=http +12:34:27 WRN this shouldn't happen module=grpc +12:34:28 WRN seriously?!? module=grpc +12:34:28 FTL fatal module=http +12:34:29 PNC panic! module=http +12:34:29 DBG wat module=search +12:34:29 DBG request elapsed=8.268013 method=GET module=search statusCode=200 url={"domain":"localhost","full":"www.example.com","original":"https://original.url","path":"/yo","port":80,"scheme":"http"} diff --git a/integration/testdata/samples/mixed b/integration/testdata/samples/mixed new file mode 100644 index 0000000..6a9c121 --- /dev/null +++ b/integration/testdata/samples/mixed @@ -0,0 +1,11 @@ +servicea {"module":"http","time":"2022-08-03T12:34:25.142900417Z","log":{"level":"trace"},"message":"yup"} +servicea {"module":"http","time":"2022-08-03T12:34:25.605701107Z","log":{"level":"debug"},"message":"yeah"} +servicea {"module":"http","time":"2022-08-03T12:34:26.143015538Z","log":{"level":"info"},"message":"here"} +serviceb {"module":"grpc","time":"2022-08-03T12:34:26.543649596Z","log":{"level":"warn"},"message":"warning, something is suspicious"} +servicea {"module":"http","time":"2022-08-03T12:34:27.142783759Z","log":{"level":"error"},"message":"hit"} +serviceb {"module":"grpc","time":"2022-08-03T12:34:27.428810856Z","log":{"level":"warn"},"message":"this shouldn't happen"} +servicea {"module":"grpc","time":"2022-08-03T12:34:28.119661968Z","log":{"level":"warn"},"message":"seriously?!?"} +serviceb {"module":"http","time":"2022-08-03T12:34:28.142497379Z","log":{"level":"fatal"},"message":"fatal"} +servicea {"module":"http","time":"2022-08-03T12:34:29.142768807Z","log":{"level":"panic"},"message":"panic!"} +serviceb {"module":"search","time":"2022-08-03T12:34:29.157192604Z","log":{"level":"debug"},"message":"wat"} +servicea {"module":"search","method":"GET","url":{"full":"www.example.com","original":"https://original.url","domain":"localhost","path":"/yo","port":80,"scheme":"http"},"statusCode":200,"elapsed":8.268013,"time":"2022-08-03T12:34:29.165763321Z","log":{"level":"debug"},"message":"request"} diff --git a/main.go b/main.go index 93fcc0e..e188034 100644 --- a/main.go +++ b/main.go @@ -10,6 +10,10 @@ import ( "github.com/jessevdk/go-flags" ) +const ( + newline = "\n" +) + type Cmd struct { Strict bool `short:"s" long:"strict" description:"strict mode"` Level []string `short:"l" long:"level" description:"only output lines at this level"` @@ -36,19 +40,26 @@ func main() { w := writer.New( writer.WithLevelFilters(cmd.Level), ) + // didnl is used to prevent double newlines since we want to ensure each JSON + // objects is on its own line but we want to preserve as much of the output + // as possible + didnl := true h := heron.New( heron.WithBufSize(bufSize), heron.WithJSON(func(a any) { s, _ := w.WriteAny(a) if s > 0 { + didnl = true w.Println() } }), heron.WithBytes(func(b []byte) { - s, _ := w.Print(string(b)) - if s > 0 { - w.Println() + sb := string(b) + if sb == newline && didnl { + return } + didnl = false + _, _ = w.Print(sb) }), heron.WithError(func(err error) { fmt.Fprint(os.Stderr, fmt.Errorf("extractor error: %w", err))