prettyconsole

package module
v0.5.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 23, 2024 License: MIT Imports: 20 Imported by: 13

README

⚡ 💅 zap-prettyconsole - Pretty Console Output For Zap

An encoder for Uber's zap logger that makes complex structured log output easily readable by humans. It prioritises displaying information in a clean and easy-to-understand way.

You get good-looking, colourised output like this: singleLine

When your log output contains structured data, it looks like this: simple

I personally feel the above is much more readable than the default "development" logger that comes with zap, which looks like this: zap_console

The above example was generated using:

package main

import (
	"go.uber.org/zap"
	"github.com/thessem/zap-prettyconsole"
)

func main() {
	// Instead of zap.NewDevelopment()
	logger := prettyconsole.NewLogger(zap.DebugLevel)

	// I normally use the un-sugared logger. I like the type-safety.
	// You can use logger.Sugar() if you prefer though!
	logger.Info("doesn't this look nice",
		zap.Complex64("nice_level", 12i-14),
		zap.Time("the_time", time.Now()),
		zap.Bools("nice_enough", []bool{true, false}),
		zap.Namespace("an_object"),
		zap.String("field_1", "value_1"),
		zap.String("field_2", "value_2"),
	)
}

This is intended as a tool for local development, and not for running in production. In production I reccomend you use zap's built in JSON mode. Your logs in production will be getting parsed by computers, not humans, after-all. Take a look at the zap advanced configuration example to configure zap to output "human" output locally, and "machine" output in production.

This package takes particular care to represent structural information with indents and newlines (slightly YAML style), hopefully making it easy to figure out what each key-value belongs to: object which is the output of

type User struct {
	Name    string
	Age     int
	Address UserAddress
	Friend  *User
}

type UserAddress struct {
	Street string
	City   string
}

func (u *User) MarshalLogObject(e zapcore.ObjectEncoder) error {
	e.AddString("name", u.Name)
	e.AddInt("age", u.Age)
	e.OpenNamespace("address")
	e.AddString("street", u.Address.Street)
	e.AddString("city", u.Address.City)
	if u.Friend != nil {
		_ = e.AddObject("friend", u.Friend)
	}
	return nil
}

func main() {
	logger, _ := prettyconsole.NewConfig().Build()
	sugarLogger := logger.Sugar()

	u := &User{
		Name: "Big Bird",
		Age:  18,
		Address: UserAddress{
			Street: "Sesame Street",
			City:   "New York",
		},
		Friend: &User{
			Name: "Oscar the Grouch",
			Age:  31,
			Address: UserAddress{
				Street: "Wallaby Way",
				City:   "Sydney",
			},
		},
	}

	sugarLogger.Infow("Asking a Question",
		"question", "how do you get to sesame street?",
		"answer", "unsatisfying",
		"user", u,
	)
}

This encoder was inspired by trying to parse multiple github.com/pkg/errors/ errors, each with their own stacktraces. I am a big fan of error wrapping and error stacktraces, I am not a fan of needing to copy text out of my terminal to see what happened. errors

When objects that do not satisfy ObjectMarshaler are logged, zap-prettyconsole will use reflection (via the delightful dd library) to print it instead: reflection

Strings passed to the logger will have their formatting printed and colourised, but you can opt out of this and print the raw strings.

formatting

Generated using:

logger := prettyconsole.NewLogger(zap.DebugLevel)
// Non-sugared version
logger = logger.With(prettyconsole.FormattedString("sql", "SELECT * FROM\n\tusers\nWHERE\n\tname = 'James'"))
sugar := logger.Sugar()
mdb := "db.users.find({\n\tname: \"\x1b[31mJames\x1b[0m\"\n});"
sugar.Debugw("string formatting",
	zap.Namespace("mdb"),
	// Sugared version
	"formatted", prettyconsole.FormattedStringValue(mdb),
	"unformatted", mdb,
)

This encoder respects all the normal encoder configuration settings. You can change your separator character, newline characters, add caller/function information and add stacktraces if you like.

configuration

Performance

Whilst this library is described as "development mode" it is still coded to be as performant as possible, saving your CPU cycles for running lots of IDE plugins.

The main performance overhead introduced with this encoder is because of the stable field ordering, we sort every structured log field alphabetically. Although the relative overhead is high, the absolute overhead is still quite small, and probably wont matter for development logging anyway!

Log a message and 10 fields:

Package Time Time % to zap Objects Allocated
⚡ zap 570 ns/op +0% 5 allocs/op
⚡ zap (sugared) 861 ns/op +51% 10 allocs/op
⚡ 💅 zap-prettyconsole 2050 ns/op +260% 11 allocs/op
⚡ 💅 zap-prettyconsole (sugared) 2484 ns/op +336% 16 allocs/op

Log a message with a logger that already has 10 fields of context:

Package Time Time % to zap Objects Allocated
⚡ zap 57 ns/op +0% 0 allocs/op
⚡ zap (sugared) 67 ns/op +18% 1 allocs/op
⚡ 💅 zap-prettyconsole 1705 ns/op +2891% 6 allocs/op
⚡ 💅 zap-prettyconsole (sugared) 1712 ns/op +2904% 7 allocs/op

Log a static string, without any context or printf-style templating:

Package Time Time % to zap Objects Allocated
⚡ 💅 zap-prettyconsole 39 ns/op -11% 0 allocs/op
⚡ zap 44 ns/op +0% 0 allocs/op
⚡ zap (sugared) 60 ns/op +36% 1 allocs/op
⚡ 💅 zap-prettyconsole (sugared) 62 ns/op +41% 1 allocs/op

Released under the MIT License

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func DefaultTimeEncoder

func DefaultTimeEncoder(format string) func(time.Time, zapcore.PrimitiveArrayEncoder)

func FormattedString added in v0.4.0

func FormattedString(key string, value string) zap.Field

FormattedString is similar to zap.String() but it does not escape the printed value. This is useful for users who have formatted strings they want to preserve when they are logged.

This is for use with a non-sugared logger. For a wrapper designed for use with a sugar logger, see FormattedStringValue().

func FormattedStringValue added in v0.4.0

func FormattedStringValue(value string) formattedString

FormattedStringValue is similar to zap.String() but it does not escape the printed value. This is useful for users who have formatted strings they want to preserve when they are logged.

This is for use with a sugared logger. For a wrapper designed for use with a non-sugar logger, see FormattedStringValue().

func NewConfig

func NewConfig() zap.Config

func NewEncoder

func NewEncoder(cfg zapcore.EncoderConfig) zapcore.Encoder

func NewEncoderConfig

func NewEncoderConfig() zapcore.EncoderConfig

func NewLogger

func NewLogger(lvl zapcore.Level) *zap.Logger

Types

This section is empty.

Directories

Path Synopsis
internal

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL