Skip to content

Commit

Permalink
extract prettyprinting
Browse files Browse the repository at this point in the history
  • Loading branch information
aybabtme authored and Antoine Grondin committed Sep 15, 2022
1 parent 651e674 commit 2ba4ea1
Show file tree
Hide file tree
Showing 16 changed files with 398 additions and 421 deletions.
14 changes: 11 additions & 3 deletions cmd/humanlog/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"github.com/fatih/color"
"github.com/humanlogio/humanlog"
"github.com/humanlogio/humanlog/internal/pkg/config"
"github.com/humanlogio/humanlog/internal/pkg/sink"
"github.com/mattn/go-colorable"
"github.com/urfave/cli"
)
Expand Down Expand Up @@ -92,7 +93,7 @@ func newApp() *cli.App {
timeFormat := cli.StringFlag{
Name: "time-format",
Usage: "output time format, see https://golang.org/pkg/time/ for details",
Value: humanlog.DefaultOptions.TimeFormat,
Value: sink.DefaultStdioOpts.TimeFormat,
}

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

opts := humanlog.HandlerOptionsFrom(*cfg)
sinkOpts, errs := sink.StdioOptsFrom(*cfg)
if len(errs) > 0 {
for _, err := range errs {
log.Printf("config error: %v", err)
}
}
sink := sink.NewStdio(colorable.NewColorableStdout(), sinkOpts)
handlerOpts := humanlog.HandlerOptionsFrom(*cfg)

log.Print("reading stdin...")
if err := humanlog.Scanner(os.Stdin, colorable.NewColorableStdout(), opts); err != nil {
if err := humanlog.Scanner(os.Stdin, sink, handlerOpts); err != nil {
log.Fatalf("scanning caught an error: %v", err)
}
return nil
Expand Down
19 changes: 12 additions & 7 deletions docker_compose_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package humanlog

import (
"regexp"

"github.com/humanlogio/humanlog/internal/pkg/model"
)

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

type handler interface {
TryHandle([]byte) bool
setField(key, val []byte)
TryHandle([]byte, *model.Structured) bool
}

func tryDockerComposePrefix(d []byte, nextHandler handler) bool {
func tryDockerComposePrefix(d []byte, ev *model.Structured, nextHandler handler) bool {
matches := dcLogsPrefixRe.FindSubmatch(d)
if matches != nil {
if nextHandler.TryHandle(matches[2]) {
nextHandler.setField([]byte(`service`), matches[1])
if nextHandler.TryHandle(matches[2], ev) {
ev.KVs = append(ev.KVs, model.KV{
Key: "service", Value: string(matches[1]),
})
return true
}
// The Zap Development handler is only built for `JSONHandler`s so
// short-circuit calls for LogFmtHandlers
switch h := nextHandler.(type) {
case *JSONHandler:
if tryZapDevDCPrefix(matches[2], h) {
h.setField([]byte(`service`), matches[1])
if tryZapDevDCPrefix(matches[2], ev, h) {
ev.KVs = append(ev.KVs, model.KV{
Key: "service", Value: string(matches[1]),
})
return true
}
}
Expand Down
9 changes: 7 additions & 2 deletions e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"testing"

"github.com/humanlogio/humanlog/internal/pkg/config"
"github.com/humanlogio/humanlog/internal/pkg/sink"
)

func TestHarness(t *testing.T) {
Expand Down Expand Up @@ -40,9 +41,13 @@ func TestHarness(t *testing.T) {
if err := json.Unmarshal(cfgjson, &cfg); err != nil {
t.Fatalf("unmarshaling config: %v", err)
}
opts := HandlerOptionsFrom(cfg)
gotw := bytes.NewBuffer(nil)
err = Scanner(bytes.NewReader(input), gotw, opts)
sinkOpts, errs := sink.StdioOptsFrom(cfg)
if len(errs) > 1 {
t.Fatalf("errs=%v", errs)
}
s := sink.NewStdio(gotw, sinkOpts)
err = Scanner(bytes.NewReader(input), s, HandlerOptionsFrom(cfg))
if err != nil {
t.Fatalf("scanning input: %v", err)
}
Expand Down
89 changes: 0 additions & 89 deletions handler.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
package humanlog

import (
"log"
"time"

"github.com/humanlogio/humanlog/internal/pkg/config"
"github.com/kr/logfmt"
)
Expand All @@ -16,47 +13,21 @@ type Handler interface {
}

var DefaultOptions = &HandlerOptions{
SortLongest: true,
SkipUnchanged: true,
Truncates: true,
LightBg: false,
TruncateLength: 15,
TimeFormat: time.Stamp,

TimeFields: []string{"time", "ts", "@timestamp", "timestamp"},
MessageFields: []string{"message", "msg"},
LevelFields: []string{"level", "lvl", "loglevel", "severity"},

Palette: DefaultPalette,
}

type HandlerOptions struct {
Skip map[string]struct{}
Keep map[string]struct{}

TimeFields []string
MessageFields []string
LevelFields []string

SortLongest bool
SkipUnchanged bool
Truncates bool
LightBg bool
TruncateLength int
TimeFormat string
Palette Palette
}

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

func HandlerOptionsFrom(cfg config.Config) *HandlerOptions {
opts := DefaultOptions
if cfg.Skip != nil {
opts.Skip = sliceToSet(cfg.Skip)
}
if cfg.Keep != nil {
opts.Keep = sliceToSet(cfg.Keep)
}
if cfg.TimeFields != nil {
opts.TimeFields = *cfg.TimeFields
}
Expand All @@ -66,65 +37,5 @@ func HandlerOptionsFrom(cfg config.Config) *HandlerOptions {
if cfg.LevelFields != nil {
opts.LevelFields = *cfg.LevelFields
}
if cfg.SortLongest != nil {
opts.SortLongest = *cfg.SortLongest
}
if cfg.SkipUnchanged != nil {
opts.SkipUnchanged = *cfg.SkipUnchanged
}
if cfg.Truncates != nil {
opts.Truncates = *cfg.Truncates
}
if cfg.LightBg != nil {
opts.LightBg = *cfg.LightBg
}
if cfg.TruncateLength != nil {
opts.TruncateLength = *cfg.TruncateLength
}
if cfg.TimeFormat != nil {
opts.TimeFormat = *cfg.TimeFormat
}
if cfg.Palette != nil {
pl, err := PaletteFrom(*cfg.Palette)
if err != nil {
log.Printf("invalid palette, using default one: %v", err)
} else {
opts.Palette = *pl
}
}
return opts
}

func (h *HandlerOptions) shouldShowKey(key string) bool {
if len(h.Keep) != 0 {
if _, keep := h.Keep[key]; keep {
return true
}
}
if len(h.Skip) != 0 {
if _, skip := h.Skip[key]; skip {
return false
}
}
return true
}

func (h *HandlerOptions) shouldShowUnchanged(key string) bool {
if len(h.Keep) != 0 {
if _, keep := h.Keep[key]; keep {
return true
}
}
return false
}

func sliceToSet(arr *[]string) map[string]struct{} {
if arr == nil {
return nil
}
out := make(map[string]struct{})
for _, key := range *arr {
out[key] = struct{}{}
}
return out
}
20 changes: 20 additions & 0 deletions internal/pkg/model/types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package model

import "time"

type KV struct {
Key string
Value string
}

type Structured struct {
Time time.Time
Level string
Msg string
KVs []KV
}

type Event struct {
Raw []byte
Structured *Structured
}
7 changes: 7 additions & 0 deletions internal/pkg/sink/sink.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package sink

import "github.com/humanlogio/humanlog/internal/pkg/model"

type Sink interface {
Receive(*model.Event) error
}
Loading

0 comments on commit 2ba4ea1

Please sign in to comment.