frog

package module
v0.4.1 Latest Latest
Warning

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

Go to latest
Published: Oct 13, 2019 License: MIT Imports: 10 Imported by: 7

README

frog

Status

category summary details
Windows works great My primary development OS at the moment.
Linux untested -
macOS untested -
API close to final As of v0.4.0, I feel like I'm done making big changes, so unless a big new use case comes in and upsets everything, it is probably safe to start using the API.
Maturity young I'm the only user as far as I know, and I've only used it in a single project so far.
Performance untested -

Overview

Frog is a package for logging output.

When connected to a terminal, Frog allows lines to be fixed to the bottom of the output, allowing for display of data that would be surperfluous in a log file, but is really nice to have when watching the output in a terminal.

Frog uses ANSI/VT-100 commands to change colors and move the cursor. For this to work in Windows, you must either 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
  • Fixing one or more lines in place for progress bars and real-time status displays (via ANSI commands)
  • Colorized output (via ANSI commands)
  • Detects if there's a connected terminal, and disables ANSI-based output as needed
  • Loggers target the io.Writer interface, allowing your logs to be easily sent to files, buffers, etc
  • Customizable line style, with built in styles for lines in plain text or JSON
    • Alternatively, you can write your own Printer that can generate your own custom style
  • Loggers can be written to target other loggers (see TeeLogger), allowing a single logger to target multiple outputs and/or styles simultaneously (ie plain text w/ fixed lines on stdout, while also sending json to a file on disk).

Usage

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

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

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

  status := frog.AddFixedLine(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)

frog.Auto will use a Buffered Logger, but will only use ANSI if there's a detected terminal, and only displays color if ANSI is supported and if there's no NO_COLOR environment variable.

The implementation of the New func shows a couple of different examlpes of how to create customized versions of the built-in Loggers, and is a good reference. See frog.go.

Another value you can pass to New is frog.JSON, which uses an Unbuffered Logger that formats each log line as a single JSON object. Switching the previous code example is as simple as changing the first line:

  log := frog.New(frog.JSON)
  ⋮

Notice that when you run this second example, all the Transient level log lines are not output. Transient lines are by default only output when sent to a fixed line, and if called on a Logger that does not currently represent a fixed line, then those lines are dropped.

Also notice that when we want to create a fixed line, we make a call on the frog package, and not directly to our Logger. Similarly, if you want to remove a fixed line, you call frog.RemoveFixedLine on the fixed line logger. Both calls are safe to call on Loggers that do not support fixed lines, and in that case will just return the passed Logger. The intent with this API is that you can write your code to always assume fixed line support, and it will just work when there isn't fixed line support present at runtime.

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.
Fatal After displaying this log line, halt the entire app.

TODO

  • Write to two Loggers simultaneously
  • JSON Printer
  • rework how fixed lines are released
  • structured logging
  • use colors to make difference betwen fields and msg more obvious
  • go doc pass
  • run it on other platforms
  • make some benchmarks, maybe do a pass on performance

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

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 RemoveFixedLine added in v0.3.0

func RemoveFixedLine(log Logger)

Types

type Buffered

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

func NewBuffered

func NewBuffered(cfg Config, prn Printer) *Buffered

func (*Buffered) AddFixedLine

func (l *Buffered) AddFixedLine() Logger

AddFixedLine creates a Logger that, when connected to a terminal, draws over itself. 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(format string, a ...Fielder) Logger

func (*Buffered) Fatal added in v0.4.0

func (l *Buffered) Fatal(format string, a ...Fielder)

func (*Buffered) Info added in v0.4.0

func (l *Buffered) Info(format string, a ...Fielder) Logger

func (*Buffered) Log added in v0.4.0

func (l *Buffered) Log(level Level, format string, fields ...Fielder) Logger

func (*Buffered) SetMinLevel

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

func (*Buffered) Transient added in v0.4.0

func (l *Buffered) Transient(format string, a ...Fielder) Logger

func (*Buffered) Verbose added in v0.4.0

func (l *Buffered) Verbose(format string, a ...Fielder) Logger

func (*Buffered) Warning added in v0.4.0

func (l *Buffered) Warning(format string, a ...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 Config

type Config struct {
	Writer   io.Writer
	UseAnsi  bool
	UseColor bool
}

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
}

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 FixedLine

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

FixedLine is a Logger that attempts to overwrite the same line in the terminal, allowing progress bars and other simple UI for the human to consume.

If the Printer's CanUseAnsi is false, then it simply redirects to the normal behavior of the parent Buffered Logger.

If the Printer's CanUseAnsi is true, then the Transient level is always printed, regardless of the MinLevel. This allows progress bars that do not pollute logs with garbage when not connected to a terminal.

func (*FixedLine) Close

func (l *FixedLine) Close()

func (*FixedLine) Error added in v0.4.0

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

func (*FixedLine) Fatal added in v0.4.0

func (l *FixedLine) Fatal(msg string, fields ...Fielder)

func (*FixedLine) Info added in v0.4.0

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

func (*FixedLine) Log added in v0.4.0

func (l *FixedLine) Log(level Level, msg string, fields ...Fielder) Logger

func (*FixedLine) Parent added in v0.2.0

func (l *FixedLine) Parent() Logger

func (*FixedLine) RemoveFixedLine added in v0.3.0

func (l *FixedLine) RemoveFixedLine()

func (*FixedLine) SetMinLevel

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

func (*FixedLine) Transient added in v0.4.0

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

func (*FixedLine) Verbose added in v0.4.0

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

func (*FixedLine) Warning added in v0.4.0

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

type FixedLineAdder added in v0.3.0

type FixedLineAdder interface {
	AddFixedLine() Logger
}

FixedLineAdder is the interface for loggers that support fixing a line in place, for progress bars or other transient status messages.

type FixedLineRemover added in v0.3.0

type FixedLineRemover interface {
	RemoveFixedLine()
}

FixedLineRemover is the interface that a fixed line logger must implement in order for the fixed line to be removed before app end.

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(useAnsi bool, useColor bool, level Level, msg string, fields ...Fielder) string

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
	Fatal                  // stop everything right now

)

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, format string, a ...Fielder) Logger

	// Transient et al are just shortcuts for calling Log with specific levels.
	// Note that Fatal will never return, as it flushes any buffers then calls os.Exit(-1).
	Transient(format string, a ...Fielder) Logger
	Verbose(format string, a ...Fielder) Logger
	Info(format string, a ...Fielder) Logger
	Warning(format string, a ...Fielder) Logger
	Error(format string, a ...Fielder) Logger
	Fatal(format string, a ...Fielder)
}

func AddFixedLine added in v0.2.0

func AddFixedLine(log Logger) Logger

AddFixedLine adds a new logger on a fixed line, if supported. Else, returns passed in Logger.

func New

func New(t NewLogger) Logger

New creates a Buffered logger that writes to os.Stdout, and autodetects any attached Terminal on stdout to decide if ANSI should be used. The caller is responsible for calling Close() before the process ends.

func Parent added in v0.2.0

func Parent(log Logger) Logger

func ParentOrSelf added in v0.2.0

func ParentOrSelf(log Logger) Logger

type NewLogger added in v0.2.0

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

type Printer

type Printer interface {
	Render(useAnsi bool, useColor bool, level Level, format string, fields ...Fielder) string
}

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) AddFixedLine added in v0.2.0

func (l *TeeLogger) AddFixedLine() 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) Fatal added in v0.4.0

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

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, msg string, fields ...Fielder) Logger

func (*TeeLogger) RemoveFixedLine added in v0.3.0

func (l *TeeLogger) RemoveFixedLine()

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 {
	PrintTime  bool
	PrintLevel bool
}

func (*TextPrinter) Render added in v0.2.1

func (p *TextPrinter) Render(useAnsi bool, useColor bool, level Level, msg string, fields ...Fielder) string

type Unbuffered added in v0.2.0

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

func NewUnbuffered added in v0.2.0

func NewUnbuffered(w 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) Fatal added in v0.4.0

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

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, 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
example command
example2 command

Jump to

Keyboard shortcuts

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