frog

package module
v0.8.1 Latest Latest
Warning

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

Go to latest
Published: Aug 29, 2022 License: MIT Imports: 12 Imported by: 7

README

frog

Overview

Frog is a package for logging output.

When connected to a terminal, Frog allows lines to be anchored to the bottom of the output. This allows progress bars and other UX that is only meant for human consumption, which are not included when logging to a file or pipe.

Windows Users: Frog uses ANSI/VT-100 commands to change colors and move the cursor, and for this to display properly, you must be using Windows 10 build 1511 (circa 2016) or newer, or be using a third-party terminal application like ConEmu/Cmdr or mintty. There's no planned supoprt for the native command prompts of earlier versions of Windows.

animated gif of frog in action

Features

  • Multiple logging levels
  • Anchoring of one or more lines for progress bars and real-time status displays
    • disabled if not connected terminal
  • Colorized output
    • disabled if not connected terminal
    • disabled if NO_COLOR is set
  • Use of standard io.Writer interface allows easy retargetting of logs to files, buffers, etc
  • Customizable line style via Printer interface
    • built in styles for lines in plain text or JSON
  • Loggers can be written to target other loggers (see TeeLogger)

Usage

The quickest way to get started is to create one of the default Loggers via a call to frog.New:

  log := frog.New(frog.Auto)
  defer log.Close()

  log.Info("Example log line")
  log.Warning("Example warning")

  status := frog.AddAnchor(log)
  for i := 0; i <= 100; i++ {
    status.Transient(" + complete", frog.Int("percent", n))
    time.Sleep(time.Duration(10) * time.Millisecond)
  }
  status.Info("Done", n)

The parameter frog.Auto tells New to autodetect if there's a terminal on stdout, and if so, to enable support for anchored lines and colors. There are other default styles you can pass to New as well, like frog.Basic and frog.JSON.

frog.JSON will output each log line as a single JSON object. This allows structured data to be easily consumed by a log parser that supports it (ie filebeat). A JSON logger created in this way doesn't support anchored lines, and by default will not output Transient level lines. Note that you can still call AddAnchor and Transient on such a logger, as the API remains consistent and valid, but nothing changes in the output as a result of these calls.

You can also build a custom Logger, if you prefer. See the implementation of the New function in frog.go for examples.

Here's a complete list of Frog's log levels, and their intended uses:

level description
Transient Output that is safe to ignore (like progress bars and estimated time remaining).
Verbose Output for debugging (disabled most of the time).
Info Normal log lines (usually enabled).
Warning Unusual events.
Error Something went wrong.

TODO

  • go doc pass
  • test on linux and mac
  • make some benchmarks, maybe do a pass on performance

Known Issues

  • A single log line will print out all given fields, even if multiple fields use the same name. When outputting JSON, this can result in a JSON object that has multiple fields with the same name. This is not necessarily considered invalid, but it can result in ambiguous behavior.
    • Frog will output the field names in the same order as they are passed to Log/Transient/Verbose/Info/Warning/Error (even when outputting JSON).
    • When there are parent/child relationships, the outermost parent adds their fields first, then the next outermost parent, etc.

Release Notes

0.8.0 (in development)
  • Re-worked printer options to be algebraic data types (see printeroptions.go and printer.go)
  • Allow overriding printer options per log line (see changes to the Printer's Render method and Logger's Log method).
  • frog.WithFields(parent, fields...) allows creating a logger that is a pass-through to parent, but always adds the specified fields to each log line.
  • frog.WithPrinterOptions(parent, opts...) allows creating a logger is a pass-through to parent, but always sets the specified PrinterOptions on each log line.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var POFieldsLeftMsgRight poFieldsLeftMsgRight
View Source
var POMsgLeftFieldsRight poMsgLeftFieldsRight

Functions

func HasTerminal added in v0.4.1

func HasTerminal(w io.Writer) bool

HasTerminal returns true if the passed writer is connected to a terminal

func POFieldIndent added in v0.8.0

func POFieldIndent(indent int) poFieldIndent

func POLevel added in v0.8.0

func POLevel(visible bool) poLevel

func POTime added in v0.8.0

func POTime(visible bool) poTime

func RemoveAnchor added in v0.7.1

func RemoveAnchor(log Logger)

Types

type AnchorAdder added in v0.7.1

type AnchorAdder interface {
	AddAnchor() Logger
}

AnchorAdder is the interface for loggers that support anchoring a line to the bottom of the output, for progress bars or other transient status messages.

type AnchorRemover added in v0.7.1

type AnchorRemover interface {
	RemoveAnchor()
}

AnchorRemover is the interface that an anchor logger must implement in order for the anchor to be removed before app end.

type AnchoredLogger added in v0.7.1

type AnchoredLogger struct {
	// contains filtered or unexported fields
}

AnchoredLogger is a Logger that treats Transient level log data in a special way: - Transient level is never ignored, and always overwrites the same output line. - Non-Transient level is sent to the parent logger.

func (*AnchoredLogger) Close added in v0.7.1

func (l *AnchoredLogger) Close()

func (*AnchoredLogger) Error added in v0.7.1

func (l *AnchoredLogger) Error(msg string, fields ...Fielder) Logger

func (*AnchoredLogger) Info added in v0.7.1

func (l *AnchoredLogger) Info(msg string, fields ...Fielder) Logger

func (*AnchoredLogger) Log added in v0.7.1

func (l *AnchoredLogger) Log(level Level, opts []PrinterOption, msg string, fields []Fielder) Logger

func (*AnchoredLogger) Parent added in v0.7.1

func (l *AnchoredLogger) Parent() Logger

func (*AnchoredLogger) RemoveAnchor added in v0.7.1

func (l *AnchoredLogger) RemoveAnchor()

func (*AnchoredLogger) SetMinLevel added in v0.7.1

func (l *AnchoredLogger) SetMinLevel(level Level) Logger

func (*AnchoredLogger) Transient added in v0.7.1

func (l *AnchoredLogger) Transient(msg string, fields ...Fielder) Logger

func (*AnchoredLogger) Verbose added in v0.7.1

func (l *AnchoredLogger) Verbose(msg string, fields ...Fielder) Logger

func (*AnchoredLogger) Warning added in v0.7.1

func (l *AnchoredLogger) Warning(msg string, fields ...Fielder) Logger

type Buffered

type Buffered struct {
	// contains filtered or unexported fields
}

func NewBuffered

func NewBuffered(writer io.Writer, prn Printer) *Buffered

func (*Buffered) AddAnchor added in v0.7.1

func (l *Buffered) AddAnchor() Logger

AddAnchor creates a Logger that is "achored" to the bottom of the output. This "anchoring" is achieved by using ANSI to re-draw the anchored line at the bottom as the output scrolls up. Thread safe.

func (*Buffered) Close

func (l *Buffered) Close()

Close should be called before the app exits, to ensure any buffered output is flushed. Thread safe.

func (*Buffered) Error added in v0.4.0

func (l *Buffered) Error(msg string, fields ...Fielder) Logger

func (*Buffered) Info added in v0.4.0

func (l *Buffered) Info(msg string, fields ...Fielder) Logger

func (*Buffered) Log added in v0.4.0

func (l *Buffered) Log(level Level, opts []PrinterOption, msg string, fields []Fielder) Logger

func (*Buffered) Printer added in v0.8.0

func (l *Buffered) Printer() Printer

func (*Buffered) SetMinLevel

func (l *Buffered) SetMinLevel(level Level) Logger

func (*Buffered) Transient added in v0.4.0

func (l *Buffered) Transient(msg string, fields ...Fielder) Logger

func (*Buffered) Verbose added in v0.4.0

func (l *Buffered) Verbose(msg string, fields ...Fielder) Logger

func (*Buffered) Warning added in v0.4.0

func (l *Buffered) Warning(msg string, fields ...Fielder) Logger

type ChildLogger added in v0.2.0

type ChildLogger interface {
	// Parent returns the parent Logger, or nil if it has no parent.
	Parent() Logger
}

ChildLogger is the interface for loggers that feed back to a parent.

type CustomizerLogger added in v0.8.0

type CustomizerLogger struct {
	// contains filtered or unexported fields
}

CustomizerLogger is a Logger that adds specific fields and/or sets specific printer options for each line it logs

func (*CustomizerLogger) Close added in v0.8.0

func (l *CustomizerLogger) Close()

func (*CustomizerLogger) Error added in v0.8.0

func (l *CustomizerLogger) Error(msg string, fields ...Fielder) Logger

func (*CustomizerLogger) Info added in v0.8.0

func (l *CustomizerLogger) Info(msg string, fields ...Fielder) Logger

func (*CustomizerLogger) Log added in v0.8.0

func (l *CustomizerLogger) Log(level Level, opts []PrinterOption, msg string, fields []Fielder) Logger

func (*CustomizerLogger) Parent added in v0.8.0

func (l *CustomizerLogger) Parent() Logger

func (*CustomizerLogger) SetMinLevel added in v0.8.0

func (l *CustomizerLogger) SetMinLevel(level Level) Logger

func (*CustomizerLogger) Transient added in v0.8.0

func (l *CustomizerLogger) Transient(msg string, fields ...Fielder) Logger

func (*CustomizerLogger) Verbose added in v0.8.0

func (l *CustomizerLogger) Verbose(msg string, fields ...Fielder) Logger

func (*CustomizerLogger) Warning added in v0.8.0

func (l *CustomizerLogger) Warning(msg string, fields ...Fielder) Logger

type Field added in v0.4.0

type Field struct {
	IsJSONString bool // if true, the string in Value should be bookended by double quotes to be valid JSON
	IsJSONSafe   bool // if true, this string only contains alpha-numerics, spaces, and safe punctuation
	Name         string
	Value        string
	Raw          interface{}
}

type FieldBool added in v0.4.0

type FieldBool struct {
	Name  string
	Value bool
}

func Bool added in v0.4.0

func Bool(name string, value bool) FieldBool

Bool adds a field whose value will be true or false

func (FieldBool) Field added in v0.4.0

func (f FieldBool) Field() Field

type FieldDuration added in v0.4.0

type FieldDuration struct {
	Name  string
	Value time.Duration
}

func Dur added in v0.4.0

func Dur(name string, value time.Duration) FieldDuration

Dur adds a time.Duration field

func Duration added in v0.4.0

func Duration(name string, value time.Duration) FieldDuration

Duration adds a time.Duration field

func (FieldDuration) Field added in v0.4.0

func (f FieldDuration) Field() Field

type FieldError added in v0.4.0

type FieldError struct {
	Name  string
	Value error
}

func Err added in v0.4.0

func Err(value error) FieldError

Err adds an error field named "error"

func (FieldError) Field added in v0.4.0

func (f FieldError) Field() Field

type FieldFloat64 added in v0.4.0

type FieldFloat64 struct {
	Name  string
	Value float64
}

func Float32 added in v0.4.0

func Float32(name string, value float32) FieldFloat64

Float32 adds a 32-bit floating point number field

func Float64 added in v0.4.0

func Float64(name string, value float64) FieldFloat64

Float64 adds a 64-bit floating point number field

func (FieldFloat64) Field added in v0.4.0

func (f FieldFloat64) Field() Field

type FieldInt64 added in v0.4.0

type FieldInt64 struct {
	Name  string
	Value int64
}

func Int added in v0.4.0

func Int(name string, value int) FieldInt64

Int adds a signed integer field

func Int8 added in v0.4.0

func Int8(name string, value int8) FieldInt64

Int8 adds an 8-bit signed integer field

func Int16 added in v0.4.0

func Int16(name string, value int16) FieldInt64

Int16 adds a 16-bit signed integer field

func Int32 added in v0.4.0

func Int32(name string, value int32) FieldInt64

Int32 adds a 32-bit signed integer field

func Int64 added in v0.4.0

func Int64(name string, value int64) FieldInt64

Int64 adds a 64-bit signed integer field

func (FieldInt64) Field added in v0.4.0

func (f FieldInt64) Field() Field

type FieldString added in v0.4.0

type FieldString struct {
	Name  string
	Value string
}

func String added in v0.4.0

func String(name string, value string) FieldString

String adds an escaped and quoted string field

func (FieldString) Field added in v0.4.0

func (f FieldString) Field() Field

type FieldTimeFormat added in v0.4.0

type FieldTimeFormat struct {
	Name   string
	Value  time.Time
	Format string
}

func Time added in v0.4.0

func Time(name string, value time.Time) FieldTimeFormat

Time adds a time.Time field that will output a string formatted using RFC 3339 (ISO 8601)

func TimeNano added in v0.4.0

func TimeNano(name string, value time.Time) FieldTimeFormat

TimeNano adds a time.Time field that will output a string formatted using RFC 3339 with nanosecond precision

func (FieldTimeFormat) Field added in v0.4.0

func (f FieldTimeFormat) Field() Field

type FieldTimeUnix added in v0.4.0

type FieldTimeUnix struct {
	Name  string
	Value time.Time
	Nano  bool
}

func TimeUnix added in v0.4.0

func TimeUnix(name string, value time.Time) FieldTimeUnix

TimeUnix adds a time.Time field that outputs as a unix epoch (unsigned integer)

func TimeUnixNano added in v0.4.0

func TimeUnixNano(name string, value time.Time) FieldTimeUnix

TimeUnixNano adds a time.Time field that outputs as a unix epoch with nanosecond precision (unsigned integer)

func (FieldTimeUnix) Field added in v0.4.0

func (f FieldTimeUnix) Field() Field

type FieldUint64 added in v0.4.0

type FieldUint64 struct {
	Name  string
	Value uint64
}

func Byte added in v0.4.0

func Byte(name string, value byte) FieldUint64

Byte adds an 8-bit unsigned integer field

func Uint added in v0.4.0

func Uint(name string, value uint) FieldUint64

Uint adds an unsigned integer field

func Uint8 added in v0.4.0

func Uint8(name string, value uint8) FieldUint64

Uint8 adds an 8-bit unsigned integer field

func Uint16 added in v0.4.0

func Uint16(name string, value uint16) FieldUint64

Uint16 adds a 16-bit unsigned integer field

func Uint32 added in v0.4.0

func Uint32(name string, value uint32) FieldUint64

Uint32 adds a 32-bit unsigned integer field

func Uint64 added in v0.4.0

func Uint64(name string, value uint64) FieldUint64

Uint64 adds a 64-bit unsigned integer field

func (FieldUint64) Field added in v0.4.0

func (f FieldUint64) Field() Field

type Fielder added in v0.4.0

type Fielder interface {
	Field() Field
}

Fielder is an interface used to add structured logging to calls to Logger methods

type JSONPrinter added in v0.2.1

type JSONPrinter struct {
	TimeOverride time.Time
}

func (*JSONPrinter) Render added in v0.2.1

func (p *JSONPrinter) Render(level Level, opts []PrinterOption, msg string, fields []Fielder) string

func (*JSONPrinter) SetOptions added in v0.8.0

func (p *JSONPrinter) SetOptions(opts ...PrinterOption) Printer

type Level

type Level byte
const (
	Transient Level = iota // strictly unimportant, ie progress bars, real-time byte counts, estimated time remaining, etc
	Verbose                // debugging info
	Info                   // normal message
	Warning                // something unusual happened
	Error                  // something bad happened

)

func (Level) String added in v0.2.1

func (l Level) String() string

type Logger

type Logger interface {
	// Close ensures any buffers are flushed and any resources released.
	// It is safe to call Close more than once (but consecutive calls do nothing).
	Close()

	// SetMinLevel sets the lowest Level that will be logged.
	SetMinLevel(level Level) Logger

	// Log is how all log lines are added.
	Log(level Level, opts []PrinterOption, msg string, fields []Fielder) Logger

	// Transient et al are just shortcuts for calling Log with specific levels.
	Transient(msg string, fields ...Fielder) Logger
	Verbose(msg string, fields ...Fielder) Logger
	Info(msg string, fields ...Fielder) Logger
	Warning(msg string, fields ...Fielder) Logger
	Error(msg string, fields ...Fielder) Logger
}

func AddAnchor added in v0.7.1

func AddAnchor(log Logger) Logger

AddAnchor adds a new logger on an anchored line, if supported. Else, returns passed in Logger.

func New

func New(t NewLogger, opts ...PrinterOption) Logger

New creates a Logger that writes to os.Stdout, depending on the NewLogger type passed to it: - Auto - if terminal detected on stdout, then colors and anchored lines are supported (else, uses Basic) - Basic - no colors or anchored lines, no buffering - JSON - no colors or anchored lines, no buffering, and each line is a valid JSON object Resulting Logger can be modified by including 1 or more NewOpts after the NewLogger type. The caller is responsible for calling Close() when done with the returned Logger.

func Parent added in v0.2.0

func Parent(log Logger) Logger

func ParentOrSelf added in v0.2.0

func ParentOrSelf(log Logger) Logger

func WithFields added in v0.8.0

func WithFields(log Logger, fields ...Fielder) Logger

WithFields creates a new Logger that will always include the specified fields

func WithOptions added in v0.8.0

func WithOptions(log Logger, opts ...PrinterOption) Logger

WithOptions creates a new Logger that will always include the specified fields

func WithOptionsAndFields added in v0.8.0

func WithOptionsAndFields(log Logger, opts []PrinterOption, fields []Fielder) Logger

WithOptionsAndFields creates a new Logger that will always include the specified fields

type NewLogger added in v0.2.0

type NewLogger byte
const (
	Auto NewLogger = iota
	Basic
	JSON
)

type NullLogger added in v0.6.0

type NullLogger struct {
}

func (*NullLogger) Close added in v0.6.0

func (n *NullLogger) Close()

func (*NullLogger) Error added in v0.6.0

func (n *NullLogger) Error(format string, a ...Fielder) Logger

func (*NullLogger) Info added in v0.6.0

func (n *NullLogger) Info(format string, a ...Fielder) Logger

func (*NullLogger) Log added in v0.6.0

func (n *NullLogger) Log(level Level, opts []PrinterOption, msg string, fields []Fielder) Logger

func (*NullLogger) SetMinLevel added in v0.6.0

func (n *NullLogger) SetMinLevel(level Level) Logger

func (*NullLogger) Transient added in v0.6.0

func (n *NullLogger) Transient(format string, a ...Fielder) Logger

func (*NullLogger) Verbose added in v0.6.0

func (n *NullLogger) Verbose(format string, a ...Fielder) Logger

func (*NullLogger) Warning added in v0.6.0

func (n *NullLogger) Warning(format string, a ...Fielder) Logger

type Palette added in v0.8.0

type Palette byte
const (
	PalNone Palette = iota
	PalColor
	PalDark
)

type Printer

type Printer interface {
	Render(Level, []PrinterOption, string, []Fielder) string
	SetOptions(...PrinterOption) Printer
}

type PrinterOption added in v0.8.0

type PrinterOption interface {
	String() string
	// contains filtered or unexported methods
}

func POPalette added in v0.8.0

func POPalette(pal Palette) PrinterOption

type Printerer added in v0.8.0

type Printerer interface {
	Printer() Printer
}

Printerer is an interface that exposes one's Printer

type TeeLogger added in v0.2.0

type TeeLogger struct {
	Primary   Logger
	Secondary Logger
}

TeeLogger directs all traffic to both a primary and secondary logger

func (*TeeLogger) AddAnchor added in v0.7.1

func (l *TeeLogger) AddAnchor() Logger

func (*TeeLogger) Close added in v0.2.0

func (l *TeeLogger) Close()

func (*TeeLogger) Error added in v0.4.0

func (l *TeeLogger) Error(msg string, fields ...Fielder) Logger

func (*TeeLogger) Info added in v0.4.0

func (l *TeeLogger) Info(msg string, fields ...Fielder) Logger

func (*TeeLogger) Log added in v0.4.0

func (l *TeeLogger) Log(level Level, opts []PrinterOption, msg string, fields []Fielder) Logger

func (*TeeLogger) RemoveAnchor added in v0.7.1

func (l *TeeLogger) RemoveAnchor()

func (*TeeLogger) SetMinLevel added in v0.2.0

func (l *TeeLogger) SetMinLevel(level Level) Logger

func (*TeeLogger) Transient added in v0.4.0

func (l *TeeLogger) Transient(msg string, fields ...Fielder) Logger

func (*TeeLogger) Verbose added in v0.4.0

func (l *TeeLogger) Verbose(msg string, fields ...Fielder) Logger

func (*TeeLogger) Warning added in v0.4.0

func (l *TeeLogger) Warning(msg string, fields ...Fielder) Logger

type TextPrinter added in v0.2.1

type TextPrinter struct {
	Palette    Palette
	PrintTime  bool
	PrintLevel bool
	// FieldIndent controls where the first field begins rendering, compared to the message.
	// Note that the first field will always be at least 3 spaces from the end of the message,
	// and always be aligned with an offset that is a multiple of 5
	// For example:
	//   [nfo] a long message that overflows the first field indent   fieldIndent=40
	//   [nfo] short message                           fieldIndent=40
	//   [nfo] short message                 fieldIndent=30
	//   [nfo] short message       fieldIndent=20
	//   [nfo] short message       fieldIndent=10
	//   [nfo] short     fieldIndent=10
	//   [nfo] short     fieldIndent=0
	//   [nfo] sh   fieldIndent=0
	FieldIndent int
	// PrintMessageLast will cause the message to display after the fields, instead of before
	// For example:
	//   [nfo] fieldIndent=40                          short message
	//   [nfo] fieldIndent=10      something  a long message that overflows the first field indent
	PrintMessageLast bool
}

func (*TextPrinter) Render added in v0.2.1

func (p *TextPrinter) Render(level Level, opts []PrinterOption, msg string, fields []Fielder) string

func (*TextPrinter) SetOptions added in v0.8.0

func (p *TextPrinter) SetOptions(opts ...PrinterOption) Printer

type Unbuffered added in v0.2.0

type Unbuffered struct {
	// contains filtered or unexported fields
}

func NewUnbuffered added in v0.2.0

func NewUnbuffered(writer io.Writer, prn Printer) *Unbuffered

func (*Unbuffered) Close added in v0.2.0

func (l *Unbuffered) Close()

func (*Unbuffered) Error added in v0.4.0

func (l *Unbuffered) Error(msg string, fields ...Fielder) Logger

func (*Unbuffered) Info added in v0.4.0

func (l *Unbuffered) Info(msg string, fields ...Fielder) Logger

func (*Unbuffered) Log added in v0.4.0

func (l *Unbuffered) Log(level Level, opts []PrinterOption, msg string, fields []Fielder) Logger

func (*Unbuffered) SetMinLevel added in v0.2.0

func (l *Unbuffered) SetMinLevel(level Level) Logger

func (*Unbuffered) Transient added in v0.4.0

func (l *Unbuffered) Transient(msg string, fields ...Fielder) Logger

func (*Unbuffered) Verbose added in v0.4.0

func (l *Unbuffered) Verbose(msg string, fields ...Fielder) Logger

func (*Unbuffered) Warning added in v0.4.0

func (l *Unbuffered) Warning(msg string, fields ...Fielder) Logger

Directories

Path Synopsis
cmd
colortest command
example command
example2 command

Jump to

Keyboard shortcuts

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