Skip to content

Commit 2ba4ea1

Browse files
aybabtmeAntoine Grondin
authored andcommitted
extract prettyprinting
1 parent 651e674 commit 2ba4ea1

16 files changed

+398
-421
lines changed

cmd/humanlog/main.go

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"github.com/fatih/color"
1111
"github.com/humanlogio/humanlog"
1212
"github.com/humanlogio/humanlog/internal/pkg/config"
13+
"github.com/humanlogio/humanlog/internal/pkg/sink"
1314
"github.com/mattn/go-colorable"
1415
"github.com/urfave/cli"
1516
)
@@ -92,7 +93,7 @@ func newApp() *cli.App {
9293
timeFormat := cli.StringFlag{
9394
Name: "time-format",
9495
Usage: "output time format, see https://golang.org/pkg/time/ for details",
95-
Value: humanlog.DefaultOptions.TimeFormat,
96+
Value: sink.DefaultStdioOpts.TimeFormat,
9697
}
9798

9899
ignoreInterrupts := cli.BoolFlag{
@@ -224,10 +225,17 @@ func newApp() *cli.App {
224225
fatalf(c, "can only use one of %q and %q", skipFlag.Name, keepFlag.Name)
225226
}
226227

227-
opts := humanlog.HandlerOptionsFrom(*cfg)
228+
sinkOpts, errs := sink.StdioOptsFrom(*cfg)
229+
if len(errs) > 0 {
230+
for _, err := range errs {
231+
log.Printf("config error: %v", err)
232+
}
233+
}
234+
sink := sink.NewStdio(colorable.NewColorableStdout(), sinkOpts)
235+
handlerOpts := humanlog.HandlerOptionsFrom(*cfg)
228236

229237
log.Print("reading stdin...")
230-
if err := humanlog.Scanner(os.Stdin, colorable.NewColorableStdout(), opts); err != nil {
238+
if err := humanlog.Scanner(os.Stdin, sink, handlerOpts); err != nil {
231239
log.Fatalf("scanning caught an error: %v", err)
232240
}
233241
return nil

docker_compose_handler.go

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ package humanlog
22

33
import (
44
"regexp"
5+
6+
"github.com/humanlogio/humanlog/internal/pkg/model"
57
)
68

79
// dcLogsPrefixRe parses out a prefix like 'web_1 | ' from docker-compose
@@ -14,23 +16,26 @@ import (
1416
var dcLogsPrefixRe = regexp.MustCompile("^(?:\x1b\\[\\d+m)?(?P<service_name>[a-zA-Z0-9._-]+)\\s+\\|(?:\x1b\\[0m)? (?P<rest_of_line>.*)$")
1517

1618
type handler interface {
17-
TryHandle([]byte) bool
18-
setField(key, val []byte)
19+
TryHandle([]byte, *model.Structured) bool
1920
}
2021

21-
func tryDockerComposePrefix(d []byte, nextHandler handler) bool {
22+
func tryDockerComposePrefix(d []byte, ev *model.Structured, nextHandler handler) bool {
2223
matches := dcLogsPrefixRe.FindSubmatch(d)
2324
if matches != nil {
24-
if nextHandler.TryHandle(matches[2]) {
25-
nextHandler.setField([]byte(`service`), matches[1])
25+
if nextHandler.TryHandle(matches[2], ev) {
26+
ev.KVs = append(ev.KVs, model.KV{
27+
Key: "service", Value: string(matches[1]),
28+
})
2629
return true
2730
}
2831
// The Zap Development handler is only built for `JSONHandler`s so
2932
// short-circuit calls for LogFmtHandlers
3033
switch h := nextHandler.(type) {
3134
case *JSONHandler:
32-
if tryZapDevDCPrefix(matches[2], h) {
33-
h.setField([]byte(`service`), matches[1])
35+
if tryZapDevDCPrefix(matches[2], ev, h) {
36+
ev.KVs = append(ev.KVs, model.KV{
37+
Key: "service", Value: string(matches[1]),
38+
})
3439
return true
3540
}
3641
}

e2e_test.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"testing"
1010

1111
"github.com/humanlogio/humanlog/internal/pkg/config"
12+
"github.com/humanlogio/humanlog/internal/pkg/sink"
1213
)
1314

1415
func TestHarness(t *testing.T) {
@@ -40,9 +41,13 @@ func TestHarness(t *testing.T) {
4041
if err := json.Unmarshal(cfgjson, &cfg); err != nil {
4142
t.Fatalf("unmarshaling config: %v", err)
4243
}
43-
opts := HandlerOptionsFrom(cfg)
4444
gotw := bytes.NewBuffer(nil)
45-
err = Scanner(bytes.NewReader(input), gotw, opts)
45+
sinkOpts, errs := sink.StdioOptsFrom(cfg)
46+
if len(errs) > 1 {
47+
t.Fatalf("errs=%v", errs)
48+
}
49+
s := sink.NewStdio(gotw, sinkOpts)
50+
err = Scanner(bytes.NewReader(input), s, HandlerOptionsFrom(cfg))
4651
if err != nil {
4752
t.Fatalf("scanning input: %v", err)
4853
}

handler.go

Lines changed: 0 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
package humanlog
22

33
import (
4-
"log"
5-
"time"
6-
74
"github.com/humanlogio/humanlog/internal/pkg/config"
85
"github.com/kr/logfmt"
96
)
@@ -16,47 +13,21 @@ type Handler interface {
1613
}
1714

1815
var DefaultOptions = &HandlerOptions{
19-
SortLongest: true,
20-
SkipUnchanged: true,
21-
Truncates: true,
22-
LightBg: false,
23-
TruncateLength: 15,
24-
TimeFormat: time.Stamp,
25-
2616
TimeFields: []string{"time", "ts", "@timestamp", "timestamp"},
2717
MessageFields: []string{"message", "msg"},
2818
LevelFields: []string{"level", "lvl", "loglevel", "severity"},
29-
30-
Palette: DefaultPalette,
3119
}
3220

3321
type HandlerOptions struct {
34-
Skip map[string]struct{}
35-
Keep map[string]struct{}
36-
3722
TimeFields []string
3823
MessageFields []string
3924
LevelFields []string
40-
41-
SortLongest bool
42-
SkipUnchanged bool
43-
Truncates bool
44-
LightBg bool
45-
TruncateLength int
46-
TimeFormat string
47-
Palette Palette
4825
}
4926

5027
var _ = HandlerOptionsFrom(config.DefaultConfig) // ensure it's valid
5128

5229
func HandlerOptionsFrom(cfg config.Config) *HandlerOptions {
5330
opts := DefaultOptions
54-
if cfg.Skip != nil {
55-
opts.Skip = sliceToSet(cfg.Skip)
56-
}
57-
if cfg.Keep != nil {
58-
opts.Keep = sliceToSet(cfg.Keep)
59-
}
6031
if cfg.TimeFields != nil {
6132
opts.TimeFields = *cfg.TimeFields
6233
}
@@ -66,65 +37,5 @@ func HandlerOptionsFrom(cfg config.Config) *HandlerOptions {
6637
if cfg.LevelFields != nil {
6738
opts.LevelFields = *cfg.LevelFields
6839
}
69-
if cfg.SortLongest != nil {
70-
opts.SortLongest = *cfg.SortLongest
71-
}
72-
if cfg.SkipUnchanged != nil {
73-
opts.SkipUnchanged = *cfg.SkipUnchanged
74-
}
75-
if cfg.Truncates != nil {
76-
opts.Truncates = *cfg.Truncates
77-
}
78-
if cfg.LightBg != nil {
79-
opts.LightBg = *cfg.LightBg
80-
}
81-
if cfg.TruncateLength != nil {
82-
opts.TruncateLength = *cfg.TruncateLength
83-
}
84-
if cfg.TimeFormat != nil {
85-
opts.TimeFormat = *cfg.TimeFormat
86-
}
87-
if cfg.Palette != nil {
88-
pl, err := PaletteFrom(*cfg.Palette)
89-
if err != nil {
90-
log.Printf("invalid palette, using default one: %v", err)
91-
} else {
92-
opts.Palette = *pl
93-
}
94-
}
9540
return opts
9641
}
97-
98-
func (h *HandlerOptions) shouldShowKey(key string) bool {
99-
if len(h.Keep) != 0 {
100-
if _, keep := h.Keep[key]; keep {
101-
return true
102-
}
103-
}
104-
if len(h.Skip) != 0 {
105-
if _, skip := h.Skip[key]; skip {
106-
return false
107-
}
108-
}
109-
return true
110-
}
111-
112-
func (h *HandlerOptions) shouldShowUnchanged(key string) bool {
113-
if len(h.Keep) != 0 {
114-
if _, keep := h.Keep[key]; keep {
115-
return true
116-
}
117-
}
118-
return false
119-
}
120-
121-
func sliceToSet(arr *[]string) map[string]struct{} {
122-
if arr == nil {
123-
return nil
124-
}
125-
out := make(map[string]struct{})
126-
for _, key := range *arr {
127-
out[key] = struct{}{}
128-
}
129-
return out
130-
}

internal/pkg/model/types.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package model
2+
3+
import "time"
4+
5+
type KV struct {
6+
Key string
7+
Value string
8+
}
9+
10+
type Structured struct {
11+
Time time.Time
12+
Level string
13+
Msg string
14+
KVs []KV
15+
}
16+
17+
type Event struct {
18+
Raw []byte
19+
Structured *Structured
20+
}

internal/pkg/sink/sink.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package sink
2+
3+
import "github.com/humanlogio/humanlog/internal/pkg/model"
4+
5+
type Sink interface {
6+
Receive(*model.Event) error
7+
}

0 commit comments

Comments
 (0)