log

package module
v0.0.0-...-c1787fa Latest Latest
Warning

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

Go to latest
Published: Nov 11, 2024 License: MIT Imports: 11 Imported by: 0

README

UltraLogger

Logo

Go Reference

Overview

UltraLogger is a versatile, flexible, and efficient logging library for Go that supports multiple log levels, custom formatting, and output destinations. It is designed to be easy to use while providing advanced features such as colorized output, customizable log levels, and detailed error handling.

UltraLogger only uses the stdlib and is written in pure Go.

Features

  • Multiple Log Levels: DEBUG, INFO, WARN, ERROR, PANIC, and FATAL levels.
  • Concurrent-Safe Logging: Supports logging from multiple goroutines, and provides asynchronous logging when writing to file or network writers.
  • Flexible Formatting: Multiple build-in field types, extensible interface for custom field types.
  • Custom Formatting: Flexible formatting options including custom date/time formats, tag padding, and bracket types.
  • Colorization: Configurable colorization can change the color of terminal output based on severity level for better visibility.
  • Output Redirection: Supports writing logs to various io.Writer destinations such as files or standard output using a single logger.
  • Silent Mode: Allows disabling all logging when set.
  • Error Handling: Implements robust error handling and fallback mechanisms for logging errors.

Installation

To install UltraLogger, use go get:

go get github.com/fmdunlap/ultralogger

Usage

Here's a basic example of how to use UltraLogger:

package main

import (
    "os"
    "github.com/fmdunlap/ultralogger"
)

func main() {
    logger := ultralogger.NewUltraLogger(os.Stdout)
    
    logger.Info("This is an info message.")  // Output: 2006-01-02 15:04:05 <INFO> This is an info message.
    logger.Debug("This is a debug message.") // Output: 2006-01-02 15:04:05 <DEBUG> This is a debug message.
    logger.Warn("This is a warning message.") // Output: 2006-01-02 15:04:05 <WARN> This is a warning message.
    
    logger.Infof("This is an info message with %s!", "formatting") // Output: 2006-01-02 15:04:05 <INFO> This is an info message with formatting!
}

Configuration

Ultralogger provides various configuration options to customize logging behaviour.

Minimum Log Level
logger := ultralogger.NewUltraLogger(os.Stdout).MinLogLevel(ultralogger.LogLevelDebug)
Tags
logger.SetTag("MyTag")
logger.Info("Message")   // -> 2006-01-02 15:04:05 [MyTag] <INFO> Message

logger.SetTag("Another")
logger.Infof("Ultralogger is %s!", "super cool") // -> 2006-01-02 15:04:05 [Another] <INFO> Ultralogger is super cool!
Formatting
Date and Time
logger.SetDateFormat("01/02/2006")
logger.ShowTime(false)

logger.Info("Message") // -> 01/02/2006 <INFO> Message

_, err := logger.ShowTime(true).SetTimeFormat("15|04|05")
if err != nil {
    // Handle error if the time format is invalid
}

logger.Info("Message") // -> 01/02/2006 15|04|05 <INFO> Message

logger.SetDateTimeSeparator("@")
logger.Info("Message") // -> 01/02/2006@15|04|05 <INFO> Message
Tag Padding
// Many style config funcs can be chained together. This is just an example.
logger.SetTag("MyTag").EnabledTagPadding(true).SetTagPadSize(10)

logger.Info("Message") // -> 2006-01-02 15:04:05 [MyTag]   <INFO> Message
logger.Error("Error!") // -> 2006-01-02 15:04:05 [MyTag]   <ERROR> Warning!
Tag Bracket Type
logger.SetTag("MyTag").SetTagBracketType(ultralogger.BracketTypeSquare)
logger.Info("Message") // -> 2006-01-02 15:04:05 [MyTag] <INFO> Message
Log Bracket Type
logger.SetLogBracketType(ultralogger.BracketTypeRound)
logger.Info("Message") // -> 2006-01-02 15:04:05 (INFO) Message
Bracket Types
ultralogger.BracketTypeNone // "tag"
ultralogger.BracketTypeSquare // "[tag]"
ultralogger.BracketTypeRound // "(tag)"
ultralogger.BracketTypeCurly // "{tag}"
ultralogger.BracketTypeAngle // "<tag>"
Terminal Colorization
logger := ultralogger.NewStdoutLogger()
logger.SetMinLevel(ultralogger.DebugLevel)
logger.SetColorize(true)

logger.Debug("Debug")
logger.Info("Message")
logger.Warn("Warning")
logger.Error("Error!")
logger.Panic("Panic!")

Colorized Output

You can also set custom colors for each log level!

logger := ultralogger.NewStdoutLogger()
logger.SetMinLevel(ultralogger.DebugLevel)
logger.SetColorize(true)

// Set custom colors for each log level
logger.SetLevelColor(ultralogger.DebugLevel, ultralogger.ColorCyan)
logger.Debug("Cyan is peaceful. Like the messages ad the debug level!")

// Set custom colors for all log levels
logger.SetLevelColors(map[ultralogger.Level]ultralogger.Color{
    ultralogger.WarnLevel: ultralogger.ColorGreen,
    ultralogger.ErrorLevel: ultralogger.ColorBlue,
    ultralogger.PanicLevel: ultralogger.ColorRed,
})

logger.Warn("Green might not be the best warning color...")
logger.Error("I'll be blue if I see this error!")
logger.Panic("RED IS THE BEST PANIC COLOR!")

Custom Colors

Output Destinations
// Files
logger := ultralogger.NewFileLogger("somefile.log")

// Stdout
logger := ultralogger.NewStdoutLogger()

// ByteBuffer
buf := new(bytes.Buffer)
logger := ultralogger.NewUltraLogger(buf)

logger.Info("Debug to byte buffer")

fmt.Printf("Buffer: %s\n", buf.String()) // Buffer: 2006-01-02 15:04:05 <INFO> Debug to byte buffer
Silent Mode
logger := ultralogger.NewStdoutLogger()
logger.SetMinLevel(ultralogger.WarnLevel)

logger.Info("Message") // -> 2006-01-02 15:04:05 <INFO> Message
logger.Warn("Message") // -> Nothing will be printed to the output
PanicOnPanicLevel Mode
logger := ultralogger.NewStdoutLogger()
logger.SetMinLevel(ultralogger.WarnLevel)
logger.SetPanicOnPanicLevel(true)

logger.Panic("Panic!") // -> 2006-01-02 15:04:05 <PANIC> Panic! (and then panics)

logger.SetPanicOnPanicLevel(false)
logger.Panic("Panic!") // -> 2006-01-02 15:04:05 <PANIC> Panic! (and then does not panic)

TODO

  • Improve Color handling. Colors are currently using ASNI color cods, which isn' the most modern way to do this.
  • Optimize logging speed.
  • Make logging fields configurable (ability to add fields, change content, change field color, change field order,etc.)
  • Add the ability to pass option funcs to the constructors to allow for more flexibility.
  • Custom bracket types!
  • OnLogLevel handlers to allow for more advanced logging.

License

MIT. See LICENSE for more details.

But also, it's MIT. Go nuts.

Contributing

Feel free to open an issue or PR if you have any suggestions or improvements!

Documentation

Index

Examples

Constants

This section is empty.

Variables

View Source
var BackgroundColors = struct {
	Black   ColorAnsiBackground
	Red     ColorAnsiBackground
	Green   ColorAnsiBackground
	Yellow  ColorAnsiBackground
	Blue    ColorAnsiBackground
	Magenta ColorAnsiBackground
	Cyan    ColorAnsiBackground
	White   ColorAnsiBackground
}{
	Black:   ColorAnsiBackground("40"),
	Red:     ColorAnsiBackground("41"),
	Green:   ColorAnsiBackground("42"),
	Yellow:  ColorAnsiBackground("43"),
	Blue:    ColorAnsiBackground("44"),
	Magenta: ColorAnsiBackground("45"),
	Cyan:    ColorAnsiBackground("46"),
	White:   ColorAnsiBackground("47"),
}

BackgroundColors are the default backgrounds supported by Ultralogger. All of these colors are the 3-bit ANSI colors supported by *most* terminals They can be used in a ColorizedFormatter to colorize log lines by level.

Note: These colors are not interchangeable with normal Color Ansi colors. They are only used for background colors because Colorization must be applied in a specific order.

See https://en.wikipedia.org/wiki/ANSI_escape_code#3-bit_and_4-bit for more info on ANSI colors.

View Source
var Brackets = struct {
	Angle  Bracket
	Square Bracket
	Round  Bracket
	Curly  Bracket
	None   Bracket
}{
	Angle:  SimpleBracket{"<", ">"},
	Square: SimpleBracket{"[", "]"},
	Round:  SimpleBracket{"(", ")"},
	Curly:  SimpleBracket{"{", "}"},
	None:   SimpleBracket{"", ""},
}
View Source
var ColorSettings = struct {
	Bold          AnsiSetting
	Dim           AnsiSetting
	Italic        AnsiSetting
	Underline     AnsiSetting
	Blink         AnsiSetting
	Strikethrough AnsiSetting
}{
	Bold:          AnsiSetting("1"),
	Dim:           AnsiSetting("2"),
	Italic:        AnsiSetting("3"),
	Underline:     AnsiSetting("4"),
	Blink:         AnsiSetting("5"),
	Strikethrough: AnsiSetting("9"),
}

ColorSettings are the default Settings supported by Ultralogger. These Settings have a mixed support environment, and are only supported by some terminals. They can be used in a ColorizedFormatter to colorize log lines by level.

See https://en.wikipedia.org/wiki/ANSI_escape_code#3-bit_and_4-bit for more info on ANSI Settings.

View Source
var Colors = struct {
	Black   ColorAnsi
	Red     ColorAnsi
	Green   ColorAnsi
	Yellow  ColorAnsi
	Blue    ColorAnsi
	Magenta ColorAnsi
	Cyan    ColorAnsi
	White   ColorAnsi
	Default ColorAnsi
}{
	Black:   ColorAnsi{Code: []byte("30")},
	Red:     ColorAnsi{Code: []byte("31")},
	Green:   ColorAnsi{Code: []byte("32")},
	Yellow:  ColorAnsi{Code: []byte("33")},
	Blue:    ColorAnsi{Code: []byte("34")},
	Magenta: ColorAnsi{Code: []byte("35")},
	Cyan:    ColorAnsi{Code: []byte("36")},
	White:   ColorAnsi{Code: []byte("37")},
	Default: ColorAnsi{Code: []byte("39")},
}

Colors are the default colors supported by Ultralogger. All of these colors are the 3-bit ANSI colors supported by *most* terminals. They can be used in a ColorizedFormatter to colorize log lines by level.

See https://en.wikipedia.org/wiki/ANSI_escape_code#3-bit_and_4-bit for more info on ANSI colors.

View Source
var ErrorEmptyFieldName = errors.New("field name cannot be empty")
View Source
var ErrorFileNotSpecified = errors.New("filename not provided to NewFileLogger")
View Source
var ErrorNilFormatter = errors.New("formatter cannot be nil")

Functions

This section is empty.

Types

type AnsiSetting

type AnsiSetting = []byte

AnsiSetting is a type that represents an ANSI setting. It can be applied to arbitrary []byte content through the ColorAnsi.SetSetting() method.

type Bracket

type Bracket interface {
	Open() string
	Close() string
	Wrap(content string) string
}

Bracket is a type that represents a bracket type. You can use this to wrap log fields if they accept it as an option.

type Color

type Color interface {
	Colorize(str []byte) []byte
}

Color is a type that represents a color. It can be used to colorize arbitrary []byte content.

type ColorAnsi

type ColorAnsi struct {
	// Code is the ANSI code that represents the foreground color of a string of text. Colors are typically multi-byte
	// codes, depending on the color. For example, the code for the Red color is "31", but an RGB color is a specially
	// formatted code that looks like "38;2;{R};{G};{B}" where {R}, {G}, and {B} are the 0-255 values for the red,
	// green, and blue components of the color, respectively.
	Code []byte

	// Background is the ANSI code that represents the background color. It is applied to the []byte content after
	// the foreground color is applied.
	Background ColorAnsiBackground

	// Settings are the ANSI Settings that are applied to the color. For example, Bold, Dim, Italic, Underline,
	// SlowBlink, and Strikethrough are Settings that can be applied to a color.
	Settings []AnsiSetting
}

ColorAnsi is a type that represents an ANSI color. It can be used to colorize arbitrary []byte content.

func ColorAnsiRGB

func ColorAnsiRGB(r, g, b int) ColorAnsi

ColorAnsiRGB returns a ColorAnsi that represents an RGB color.

func (ColorAnsi) Bold

func (ac ColorAnsi) Bold() ColorAnsi

Bold returns a new ColorAnsi with the Bold setting applied.

func (ColorAnsi) Colorize

func (ac ColorAnsi) Colorize(content []byte) []byte

Colorize returns the []byte content with the ANSI color applied.

If the content is empty, an empty []byte is returned.

A colorized byte array will not have the same length as the original byte array; it will be longer. This is because the colorized byte array will have the ANSI escape codes added to it, and the length of the escape codes will be different than the length of the original byte array.

Colorization is always applied in the following order: ControlSequenceInitializer, Settings, Background, Code, AnsiEnd, CONTENT, AnsiResetSequence. Each section of the colorization is separated by the ansiCSSeparator byte (almost always a semicolon). Effectively, we're prefixing the content with the ANSI escape codes, and then resetting the ANSI escape codes after the content.

Example
// Colorize a string of text with the Red color.
red := Colors.Red
colorizedBytes := red.Colorize([]byte("This is red!"))

// \033[31mThis is red!\033[0m
fmt.Println(colorizedBytes)
Output:

[27 91 51 49 109 84 104 105 115 32 105 115 32 114 101 100 33 27 91 48 109]
Example (Multiple)
// Colorize a string of text with the Red color, the Bold setting, and a yellow background.
redBoldYellowBackground := Colors.Red.Bold().SetBackground(BackgroundColors.Yellow)
colorizedBytes := redBoldYellowBackground.Colorize([]byte("This is BOLD red with a yellow background!"))

// \033[1;48;2;255;255;0;31mThis is BOLD red with a yellow background!\033[0m
fmt.Println(colorizedBytes)
Output:

[27 91 49 59 52 51 59 51 49 109 84 104 105 115 32 105 115 32 66 79 76 68 32 114 101 100 32 119 105 116 104 32 97 32 121 101 108 108 111 119 32 98 97 99 107 103 114 111 117 110 100 33 27 91 48 109]
Example (Rgb)
// Colorize a string of text with an RGB color and an RGB background.
redForegroundGreenBackground := ColorAnsiRGB(255, 0, 0).SetBackground(BackgroundRGB(0, 255, 0))
colorized := redForegroundGreenBackground.Colorize([]byte("This is red text on a green background!"))

// \033[48;2;0;255;0;38;2;255;0;0mThis is red text on a green background!\033[0m
fmt.Println(colorized)
Output:

[27 91 52 56 59 50 59 48 59 50 53 53 59 48 59 51 56 59 50 59 50 53 53 59 48 59 48 109 84 104 105 115 32 105 115 32 114 101 100 32 116 101 120 116 32 111 110 32 97 32 103 114 101 101 110 32 98 97 99 107 103 114 111 117 110 100 33 27 91 48 109]

func (ColorAnsi) Dim

func (ac ColorAnsi) Dim() ColorAnsi

Dim returns a new ColorAnsi with the Dim setting applied.

func (ColorAnsi) Italic

func (ac ColorAnsi) Italic() ColorAnsi

Italic returns a new ColorAnsi with the Italic setting applied.

func (ColorAnsi) SetBackground

func (ac ColorAnsi) SetBackground(background ColorAnsiBackground) ColorAnsi

SetBackground returns a new ColorAnsi with the specified background color.

func (ac ColorAnsi) SlowBlink() ColorAnsi

SlowBlink returns a new ColorAnsi with the SlowBlink setting applied.

func (ColorAnsi) Underline

func (ac ColorAnsi) Underline() ColorAnsi

Underline returns a new ColorAnsi with the Underline setting applied.

type ColorAnsiBackground

type ColorAnsiBackground = []byte

func BackgroundRGB

func BackgroundRGB(r, g, b int) ColorAnsiBackground

BackgroundRGB returns a ColorAnsiBackground that represents an RGB background color.

type ColorizedFormatter

type ColorizedFormatter struct {
	BaseFormatter LogLineFormatter
	LevelColors   map[Level]Color
}

ColorizedFormatter colorizes the bytes of the base formatter using the provided colors.

func NewColorizedFormatter

func NewColorizedFormatter(baseFormatter LogLineFormatter, levelColors map[Level]Color) *ColorizedFormatter

NewColorizedFormatter returns a new ColorizedFormatter that formats the provided base formatter with the provided colors.

func (*ColorizedFormatter) FormatLogLine

func (f *ColorizedFormatter) FormatLogLine(args LogLineArgs, data any) FormatResult

FormatLogLine formats the log line using the provided data and returns a FormatResult which contains the formatted log line and any errors that may have occurred.

type ErrorAmbiguousDestination

type ErrorAmbiguousDestination struct{}

func (*ErrorAmbiguousDestination) Error

func (e *ErrorAmbiguousDestination) Error() string

type ErrorFieldFormatterInit

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

func (*ErrorFieldFormatterInit) Error

func (e *ErrorFieldFormatterInit) Error() string

func (*ErrorFieldFormatterInit) Unwrap

func (e *ErrorFieldFormatterInit) Unwrap() error

type ErrorFileNotFound

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

func (*ErrorFileNotFound) Error

func (e *ErrorFileNotFound) Error() string

type ErrorInvalidFieldDataType

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

func (*ErrorInvalidFieldDataType) Error

func (e *ErrorInvalidFieldDataType) Error() string

type ErrorInvalidOutput

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

func (*ErrorInvalidOutput) Error

func (e *ErrorInvalidOutput) Error() string

type ErrorLevelParsing

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

func (*ErrorLevelParsing) Error

func (e *ErrorLevelParsing) Error() string

type ErrorLoggerInitialization

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

func (*ErrorLoggerInitialization) Error

func (e *ErrorLoggerInitialization) Error() string

func (*ErrorLoggerInitialization) Unwrap

func (e *ErrorLoggerInitialization) Unwrap() error

type ErrorMissingLevelColor

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

func (*ErrorMissingLevelColor) Error

func (e *ErrorMissingLevelColor) Error() string

type Field

type Field interface {
	// NewFieldFormatter returns a FieldFormatter, and an error if an error occurs while creating the FieldFormatter.
	NewFieldFormatter() (FieldFormatter, error)
}

Field is an individual piece of data that is added to a log line. It can be a simple value, or an object.

Most interaction with Fields should be done through the NewObjectField function.

Example
formatter, _ := NewFormatter(OutputFormatText, []Field{
	NewLevelField(Brackets.Angle),
	NewMessageField(),
})

// Note: were setting WithAsync(false) here just to ensure that the output is synchronous in the example.
// In a real application, you *could* do this, but it will make your logging block the main thread until the log
// has been written to the output.
logger, _ := NewLoggerWithOptions(WithDestination(os.Stdout, formatter), WithAsync(false))

logger.Info("This is an info message.")
Output:

<INFO> This is an info message.
Example (JSON)
formatter, _ := NewFormatter(OutputFormatJSON, []Field{
	NewLevelField(Brackets.Angle),
	NewMessageField(),
})

// Note: were setting WithAsync(false) here just to ensure that the output is synchronous in the example.
// In a real application, you *could* do this, but it will make your logging block the main thread until the log
// has been written to the output.
logger, _ := NewLoggerWithOptions(WithDestination(os.Stdout, formatter), WithAsync(false))

logger.Info("This is an info message.")
Output:

{"level":"INFO","message":"This is an info message."}

func NewArrayField

func NewArrayField[T any](name string, formatter ObjectFieldFormatter[T]) (Field, error)

NewArrayField returns a new Field that formats a slice of type T into a slice of any. The field will format each element of the slice using the provided formatter.

If the name is empty or the formatter is nil, an error is returned.

OutputFormats:

  • OutputFormatText => slice is formatted into a string with square brackets and comma separated elements. Each element is formatted using the formatter. If the slice is empty, an empty string is returned. If the slice has only one element, the element is returned in brackets.
  • OutputFormatJSON => slice is formatted as a slice.
Example
type Person struct {
	Name string
	Age  int
}

stringArrayField, _ := NewArrayField[Person](
	"people",
	func(args LogLineArgs, data Person) any {
		if args.OutputFormat == OutputFormatText {
			return fmt.Sprintf("%s:%d", data.Name, data.Age)
		}
		return data
	},
)

formatter, _ := NewFormatter(OutputFormatText, []Field{
	NewLevelField(Brackets.Angle),
	stringArrayField,
})

// Note: were setting WithAsync(false) here just to ensure that the output is synchronous in the example.
// In a real application, you *could* do this, but it will make your logging block the main thread until the log
// has been written to the output.
logger, _ := NewLoggerWithOptions(WithDestination(os.Stdout, formatter), WithAsync(false))

logger.Info([]Person{Person{"John", 25}, Person{"Jane", 30}})
Output:

<INFO> [John:25, Jane:30]
Example (JSON)
type Person struct {
	Name string
	Age  int
}

stringArrayField, _ := NewArrayField[Person](
	"people",
	func(args LogLineArgs, data Person) any {
		if args.OutputFormat == OutputFormatText {
			return fmt.Sprintf("%s:%d", data.Name, data.Age)
		}
		return data
	},
)

formatter, _ := NewFormatter(OutputFormatJSON, []Field{
	NewLevelField(Brackets.Angle),
	stringArrayField,
})

// Note: were setting WithAsync(false) here just to ensure that the output is synchronous in the example.
// In a real application, you *could* do this, but it will make your logging block the main thread until the log
// has been written to the output.
logger, _ := NewLoggerWithOptions(WithDestination(os.Stdout, formatter), WithAsync(false))

logger.Info([]Person{Person{"John", 25}, Person{"Jane", 30}})
Output:

{"level":"INFO","people":[{"Name":"John","Age":25},{"Name":"Jane","Age":30}]}

func NewBoolField

func NewBoolField(name string) (Field, error)

NewBoolField returns a new Field that formats a bool into a string. The field will format the bool using the Format() method of the bool.

If the name is empty, an error is returned.

OutputFormats:

  • OutputFormatText => bool is formatted as a string with the format %v.
  • OutputFormatJSON => bool is formatted as a bool.

func NewCurrentTimeField

func NewCurrentTimeField(name, format string) (Field, error)

NewCurrentTimeField returns a new Field that formats the current time into a string. The field will format the time using the provided format string.

If the name is empty or the format is empty, an error is returned.

OutputFormats:

  • OutputFormatText => time is formatted as a string with the format provided in the format argument.
  • OutputFormatJSON => time is formatted as a time.Time.

func NewDefaultTagField

func NewDefaultTagField() Field

NewDefaultTagField returns a new tag field with the default settings.

The default settings are square brackets, and no padding.

func NewDurationField

func NewDurationField(name string) (Field, error)

NewDurationField returns a new Field that formats a time.Duration.

If the name is empty, an error is returned.

OutputFormats:

  • OutputFormatText => time.Duration is formatted as a string with the format %s.
  • OutputFormatJSON => time.Duration is formatted as a time.Duration.

func NewErrorField

func NewErrorField(name string) (Field, error)

NewErrorField returns a new Field that formats an error into a string. The field will format the error using the Error() method of the error.

If the name is empty, an error is returned.

OutputFormats:

  • OutputFormatText => error is formatted as a string with the format %v.
  • OutputFormatJSON => error is formatted as a error.

func NewFloatField

func NewFloatField(name string) (Field, error)

NewFloatField returns a new Field that formats a float64.

If the name is empty, an error is returned.

OutputFormats:

  • OutputFormatText => float64 is formatted as a string with the format '%f'.
  • OutputFormatJSON => float64 is formatted as a float64.

func NewIntField

func NewIntField(name string) (Field, error)

NewIntField returns a new Field that formats an int.

If the name is empty, an error is returned.

OutputFormats:

  • OutputFormatText => int is formatted as a string with the format %d using strconv.Itoa().
  • OutputFormatJSON => int is formatted as a int.

func NewLevelField

func NewLevelField(bracket Bracket) Field

NewLevelField returns a new Field that formats a level into a string. The field will format the level using the String() method of the level.

name: "level"

If the bracket type is empty, the default bracket type is used.

OutputFormats:

  • OutputFormatText => level is formatted as a string with the format %v and wrapped in the bracket type.
  • OutputFormatJSON => level is formatted as a level. Not wrapped in the bracket type.

TODO: May want different behavior when serializing to non-text output formats. Currently we're returning the string

value of the Level. Do we want to keep the brackets? Or maybe we want to output the integer value of the level?
Maybe we just want to make the whole thing configurable? ¯\_(ツ)_/¯

func NewMapField

func NewMapField[K comparable, V any](name string, keyFormatter ObjectFieldFormatter[K], valueFormatter ObjectFieldFormatter[V]) (Field, error)

NewMapField returns a new Field that formats a map of type K and V into a map of K and V. The field will format each key and value of the map using the provided formatters.

If the name is empty or the formatters are nil, an error is returned.

OutputFormats:

  • OutputFormatText => map is formatted into a string with curly brackets and comma separated key-value pairs. Each key-value pair is formatted using the keyFormatter and valueFormatter. If the map is empty, an empty string is returned. If the map has only one key-value pair, the key-value pair is returned in brackets.
  • OutputFormatJSON => map is formatted as a map.

func NewMessageField

func NewMessageField() Field

NewMessageField returns a new Field that formats a message into a string. The field will format the message using the String() method of the message.

name: "message"

OutputFormats:

  • OutputFormatText => message is formatted as a string with the format %v.
  • OutputFormatJSON => message is formatted as a message.

func NewRequestField

func NewRequestField(name string, settings RequestFieldSettings) (Field, error)

NewRequestField returns a new Field that formats an http.Request into a string. The field will format the request using the provided settings RequestFieldSettings.

If the name is empty or the settings are nil, an error is returned.

OutputFormats:

  • OutputFormatText => request is formatted as a string. Http request fields are included based on the settings RequestFieldSettings. Included fields are returned as a space separated string with key=value elements. Returns an empty string if RequestFieldSettings has no true fields.
  • OutputFormatJSON => RequestLogEntry.

func NewResponseField

func NewResponseField(name string, settings ResponseFieldSettings) (Field, error)

NewResponseField returns a new Field that formats an http.Response into a string. The field will format the response using the provided settings ResponseFieldSettings.

An error is returned if the name is empty or the settings are nil.

OutputFormats:

  • OutputFormatText => response is formatted as a string. http.Response fields are included based on the settings ResponseFieldSettings. Included fields are returned as a space separated string with key=value elements. Returns an empty string if RequestFieldSettings has no true fields.
  • OutputFormatJSON => ResponseLogEntry.

func NewStringField

func NewStringField(name string) (Field, error)

NewStringField returns a new Field that formats a string into a string. The field will format the string using the String() method of the string.

If the name is empty, an error is returned.

Output Formats:

  • All OutputFormats => remains unchanged.

func NewTagField

func NewTagField(bracket Bracket, padSettings *TagPadSettings) Field

NewTagField returns a new tag field with the provided settings.

func NewTimeField

func NewTimeField(name, format string) (Field, error)

NewTimeField returns a new Field that formats a time.Time into a string. The field will format the time using the Format() method of the time.Time.

If the name is empty or the format is empty, an error is returned.

OutputFormats:

  • OutputFormatText => time.Time is formatted as a string with the format provided in the format argument.
  • OutputFormatJSON => time.Time is formatted as a time.Time.

type FieldFormatter

type FieldFormatter func(
	args LogLineArgs,
	data any,
) (FieldResult, error)

FieldFormatter is a function that formats a field. It takes a LogLineArgs and the data to be formatted, and returns a FieldResult.

type FieldResult

type FieldResult struct {
	Name string
	Data any
}

FieldResult is the result of formatting a field. It is used by the logger to annotate entries with metadata, such as the name of the field.

type FormatResult

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

FormatResult is a struct that contains the formatted log line and any errors that may have occurred.

type FormatterOption

type FormatterOption func(f LogLineFormatter) LogLineFormatter

FormatterOption is a function that takes a LogLineFormatter and returns a new LogLineFormatter that has an option applied to it. This is useful for creating custom formatters that have additional options.

func WithColorization

func WithColorization(colors map[Level]Color) FormatterOption

WithColorization enables colorization for the formatter with the provided colors.

colors is a map of level to color. If a level is not present in the map, the default color for that level will be used.

func WithDefaultColorization

func WithDefaultColorization() FormatterOption

WithDefaultColorization enables colorization for the formatter with the default colors.

The default colors are ANSI 3-bit colors, and are compatible with most/virtually all terminals. See https://en.wikipedia.org/wiki/ANSI_escape_code#3-bit_and_4-bit for more information.

Example
formatter, _ := NewFormatter(OutputFormatText, []Field{
	NewLevelField(Brackets.Angle),
	NewMessageField(),
}, WithDefaultColorization())

buf := &bytes.Buffer{}
logger, _ := NewLoggerWithOptions(WithDestination(buf, formatter), WithAsync(false))

logger.Warn("This is an info message.")

// NOTE: Colorization breaks Golang's default output formatting, so you'll need to run this example in a terminal
// that supports ANSI colors.

fmt.Println(buf.Bytes())
Output:

[27 91 51 51 109 60 87 65 82 78 62 32 84 104 105 115 32 105 115 32 97 110 32 105 110 102 111 32 109 101 115 115 97 103 101 46 27 91 48 109 10]

type JSONFormatter

type JSONFormatter struct {
	Fields []Field
	// contains filtered or unexported fields
}

JSONFormatter is a formatter that formats log lines as JSON.

func (*JSONFormatter) FormatLogLine

func (f *JSONFormatter) FormatLogLine(args LogLineArgs, data any) FormatResult

FormatLogLine formats the log line using the provided data and returns a FormatResult which contains the formatted log line and any errors that may have occurred.

type Level

type Level int

Level is a type representing the level of a log message.

It can be one of the following:

  • Debug
  • Info
  • Warn
  • Error
  • Panic

Levels determine the priority of a log message, and can be hidden if a logger's minimum level is set to a higher level than the message's level.

For example, if a logger's minimum level is set to Warn, then a message with a level of Info will not be written to the output.

const (
	Debug Level = iota
	Info
	Warn
	Error
	Panic
)

func AllLevels

func AllLevels() []Level

AllLevels returns a slice of all available levels.

func ParseLevel

func ParseLevel(levelStr string) (Level, error)

ParseLevel parses a string into a Level. Returns an error if the string is not a valid Level.

func (Level) String

func (l Level) String() string

type LogLineArgs

type LogLineArgs struct {
	Level        Level
	Tag          string
	OutputFormat OutputFormat
}

LogLineArgs are the arguments that are passed to the FormatLogLine function of a LogLineFormatter, and further to the FieldFormatter function of a Field. Args are any format-level contextual information that may be needed to format a log field or log line.

type LogLineFormatter

type LogLineFormatter interface {
	// FormatLogLine formats the log line using the provided data and returns a FormatResult which contains the
	// formatted log line and any errors that may have occurred.
	FormatLogLine(args LogLineArgs, data any) FormatResult
}

LogLineFormatter is an interface that defines a formatter for a log line. Implement this interface to create a custom formatter for your log lines if you need a specific format, or want to use ultralogger for a datatype that isn't built-in.

func NewFormatter

func NewFormatter(outputFormat OutputFormat, fields []Field, opts ...FormatterOption) (LogLineFormatter, error)
Example
formatter, _ := NewFormatter(OutputFormatText, []Field{
	NewLevelField(Brackets.Angle),
	NewMessageField(),
})

logger, _ := NewLoggerWithOptions(WithDestination(os.Stdout, formatter), WithAsync(false))

logger.Info("This is an info message.")
Output:

<INFO> This is an info message.
Example (JSON)
formatter, _ := NewFormatter(OutputFormatJSON, []Field{
	NewLevelField(Brackets.Angle),
	NewMessageField(),
})

logger, _ := NewLoggerWithOptions(WithDestination(os.Stdout, formatter), WithAsync(false))

logger.Info("This is an info message.")
Output:

{"level":"INFO","message":"This is an info message."}

type Logger

type Logger interface {
	// Log logs at the specified level without formatting.
	Log(level Level, data any)

	// Debug logs a debug-level message.
	Debug(data any)

	// Info logs an info-level message.
	Info(data any)

	// Warn logs a warning-level message.
	Warn(data any)

	// Error logs an error-level message.
	Error(data any)

	// Panic logs a panic-level message and then panics.
	Panic(data any)

	// SetMinLevel sets the minimum logging level that will be output.
	SetMinLevel(level Level)

	// SetTag sets the tag for the logger.
	SetTag(tag string)

	Silence(enable bool)
}

Logger defines the interface for a structured ultraLogger in Go.

This interface is useful for either creating your own logger or for using an existing logger, and preventing changes to the loggers formatting Settings.

func NewFileLogger

func NewFileLogger(filename string, outputFormat OutputFormat) (Logger, error)

NewFileLogger returns a new Logger that writes to a file.

If the filename is empty, ErrorFileNotSpecified is returned. If the file does not exist, ErrorFileNotFound is returned.

func NewLogger

func NewLogger() Logger

NewLogger returns a new Logger that writes to stdout with the default text output format.

func NewLoggerWithOptions

func NewLoggerWithOptions(opts ...LoggerOption) (Logger, error)

type LoggerOption

type LoggerOption func(l *ultraLogger) error

LoggerOption is a function that takes a Logger and returns a new Logger that has an option applied to it. This is useful for creating custom loggers that have additional options.

func WithAsync

func WithAsync(async bool) LoggerOption

WithAsync enables async logging. Default=true.

If async is true, the logger will write logs asynchronously. This is useful when writing to a file or a network connection, as it allows the logger to continue writing logs while

func WithCustomColorization

func WithCustomColorization(writer io.Writer, colors map[Level]Color) LoggerOption

WithCustomColorization enables colorization for the formatter with the default colors.

The default formatter will be used if no formatter has been set for the provided writer.

The default colors are ANSI 3-bit colors, and are compatible with most/virtually all terminals. See https://en.wikipedia.org/wiki/ANSI_escape_code#3-bit_and_4-bit for more information.

Example
testColors := map[Level]Color{
	Debug: ColorAnsiRGB(235, 216, 52),
	Info:  ColorAnsiRGB(12, 240, 228),
	Warn:  ColorAnsiRGB(237, 123, 0),
	Error: ColorAnsiRGB(237, 0, 0),
	Panic: ColorAnsiRGB(237, 0, 0),
}

formatter, _ := NewFormatter(OutputFormatText, []Field{NewLevelField(Brackets.Angle), NewMessageField()}, WithColorization(testColors))

buf := &bytes.Buffer{}

// Note: were setting WithAsync(false) here just to ensure that the output is synchronous in the example.
// In a real application, you *could* do this, but it will make your logging block the main thread until the log
// has been written to the output.
logger, err := NewLoggerWithOptions(WithDestination(buf, formatter), WithMinLevel(Debug), WithAsync(false))
if err != nil {
	panic(err)
}

logger.Debug("Debug")
logger.Info("Info")
logger.Warn("Warn")
logger.Error("Error")

fmt.Println(buf.Bytes())

// NOTE: Colorization breaks Golang's default output formatting, so you'll need to use the following to see the
// colors:
//
// go test -v -run TestFormatter_customColors
//
// <DEBUG> Debug // Yellowish
// <INFO> Info // Cyanish
// <WARN> Warn // Orangish
// <ERROR> Error // Reddish
Output:

[27 91 51 56 59 50 59 50 51 53 59 50 49 54 59 53 50 109 60 68 69 66 85 71 62 32 68 101 98 117 103 27 91 48 109 10 27 91 51 56 59 50 59 49 50 59 50 52 48 59 50 50 56 109 60 73 78 70 79 62 32 73 110 102 111 27 91 48 109 10 27 91 51 56 59 50 59 50 51 55 59 49 50 51 59 48 109 60 87 65 82 78 62 32 87 97 114 110 27 91 48 109 10 27 91 51 56 59 50 59 50 51 55 59 48 59 48 109 60 69 82 82 79 82 62 32 69 114 114 111 114 27 91 48 109 10]

func WithDefaultColorizationEnabled

func WithDefaultColorizationEnabled(writer io.Writer) LoggerOption

WithDefaultColorizationEnabled enables colorization for the formatter with the default colors.

The default formatter will be used if no formatter has been set for the provided writer.

The default colors are ANSI 3-bit colors, and are compatible with most/virtually all terminals. See https://en.wikipedia.org/wiki/ANSI_escape_code#3-bit_and_4-bit for more information.

Example

ExampleWithDefaultColorizationEnabled shows how to use WithDefaultColorizationEnabled to enable colorization for the default formatter.

buf := &bytes.Buffer{}
// Note: were setting WithAsync(false) here just to ensure that the output is synchronous in the example.
// In a real application, you *could* do this, but it will make your logging block the main thread until the log
// has been written to the output.
logger, _ := NewLoggerWithOptions(
	WithFields(buf, []Field{NewLevelField(Brackets.Angle), NewMessageField()}),
	WithDefaultColorizationEnabled(buf),
	WithAsync(false),
)

logger.Info("This is an info message.")

fmt.Print(buf.Bytes())
Output:

[27 91 51 55 109 60 73 78 70 79 62 32 84 104 105 115 32 105 115 32 97 110 32 105 110 102 111 32 109 101 115 115 97 103 101 46 27 91 48 109 10]

func WithDestination

func WithDestination(destination io.Writer, formatter LogLineFormatter) LoggerOption

WithDestination sets the destination for the logger. If the formatter is nil, the destination will be ignored. If the logger already has destinations, this will overwrite them.

Example

ExampleWithDestination shows how to use WithDestination to log to multiple writers with different formatters

bufOne := &bytes.Buffer{}
bufTwo := &bytes.Buffer{}

formatterOne, err := NewFormatter(OutputFormatText, []Field{NewLevelField(Brackets.Angle), NewMessageField()})
if err != nil {
	panic(err)
}

formatterTwo, err := NewFormatter(OutputFormatJSON, []Field{NewTagField(Brackets.Square, nil), NewMessageField()})
if err != nil {
	panic(err)
}

// Note: were setting WithAsync(false) here just to ensure that the output is synchronous in the example.
// In a real application, you *could* do this, but it will make your logging block the main thread until the log
// has been written to the output.
logger, _ := NewLoggerWithOptions(
	WithDestination(bufOne, formatterOne),
	WithDestination(bufTwo, formatterTwo),
	WithTag("TAG"),
	WithAsync(false),
)

logger.Info("This is an info message.")

fmt.Print(bufOne.String())
fmt.Print(bufTwo.String())
Output:

<INFO> This is an info message.
{"message":"This is an info message.","tag":"TAG"}
Example (SharedFormatter)

ExampleWithDestination_sharedFormatter shows how to use WithDestination to log to multiple writers using a single formatter. Note that changes to teh formatter will be reflected in all destinations.

bufOne := bytes.NewBufferString("")
bufTwo := bytes.NewBufferString("")

formatter, err := NewFormatter(OutputFormatText, []Field{
	NewTagField(Brackets.Square, nil),
	NewLevelField(Brackets.Angle),
	NewMessageField(),
})
if err != nil {
	panic(err)
}

// Note: were setting WithAsync(false) here just to ensure that the output is synchronous in the example.
// In a real application, you *could* do this, but it will make your logging block the main thread until the log
// has been written to the output.
logger, _ := NewLoggerWithOptions(
	WithDestination(bufOne, formatter),
	WithDestination(bufTwo, formatter),
	WithTag("TAG"),
	WithAsync(false),
)

logger.Info("This is an info message.")

fmt.Print(bufOne.String())
fmt.Print(bufTwo.String())
Output:

[TAG] <INFO> This is an info message.
[TAG] <INFO> This is an info message.

func WithDestinations

func WithDestinations(destinations map[io.Writer]LogLineFormatter) LoggerOption

WithDestinations sets the destinations for the logger. If the formatter is nil, the destination will be ignored. If the logger already has destinations, this will overwrite them.

Example

ExampleWithDestinations shows how to use WithDestinations to log to multiple writers with different formatters

bufOne := &bytes.Buffer{}
bufTwo := &bytes.Buffer{}

formatterOne, err := NewFormatter(OutputFormatText, []Field{NewLevelField(Brackets.Angle), NewMessageField()})
if err != nil {
	panic(err)
}

formatterTwo, err := NewFormatter(OutputFormatJSON, []Field{NewTagField(Brackets.Square, nil), NewMessageField()})
if err != nil {
	panic(err)
}

destinations := map[io.Writer]LogLineFormatter{
	bufOne: formatterOne,
	bufTwo: formatterTwo,
}

// Note: were setting WithAsync(false) here just to ensure that the output is synchronous in the example.
// In a real application, you *could* do this, but it will make your logging block the main thread until the log
// has been written to the output.
logger, _ := NewLoggerWithOptions(
	WithDestinations(destinations),
	WithTag("TAG"),
	WithAsync(false),
)

logger.Info("This is an info message.")

fmt.Print(bufOne.String())

fmt.Print(bufTwo.String())
Output:

<INFO> This is an info message.
{"message":"This is an info message.","tag":"TAG"}

func WithFallbackEnabled

func WithFallbackEnabled(fallback bool) LoggerOption

WithFallbackEnabled enables fallback to writing to os.Stdout.

func WithFields

func WithFields(writer io.Writer, fields []Field) LoggerOption

WithFields sets the fields for the logger.

Example
// Note: were setting WithAsync(false) here just to ensure that the output is synchronous in the example.
// In a real application, you *could* do this, but it will make your logging block the main thread until the log
// has been written to the output.
logger, _ := NewLoggerWithOptions(
	WithFields(os.Stdout, []Field{NewLevelField(Brackets.Angle), NewMessageField()}),
	WithAsync(false),
	WithAsync(false),
)

logger.Debug("This is a debug message.") // Below min level, won't be output.
logger.Info("This is an info message.")
logger.Warn("This is a warning message.")
logger.Error("This is an error message.")
logger.Panic("This is a panic message.")
Output:

<INFO> This is an info message.
<WARN> This is a warning message.
<ERROR> This is an error message.
<PANIC> This is a panic message.

func WithMinLevel

func WithMinLevel(level Level) LoggerOption

WithMinLevel sets the minimum log level that will be output.

Example
// Note: were setting WithAsync(false) here just to ensure that the output is synchronous in the example.
// In a real application, you *could* do this, but it will make your logging block the main thread until the log
// has been written to the output.
logger, _ := NewLoggerWithOptions(WithFields(os.Stdout, []Field{NewLevelField(Brackets.Angle), NewMessageField()}), WithMinLevel(Warn), WithAsync(false))

logger.Info("This is an info message.")
logger.Debug("This is a debug message.")
logger.Warn("This is a warning message.")
logger.Error("This is an error message.")
logger.Panic("This is a panic message.")
Output:

<WARN> This is a warning message.
<ERROR> This is an error message.
<PANIC> This is a panic message.

func WithPanicOnPanicLevel

func WithPanicOnPanicLevel(panicOnPanicLevel bool) LoggerOption

WithPanicOnPanicLevel enables panic on panic level.

func WithSilent

func WithSilent(silent bool) LoggerOption

WithSilent enables silent mode.

Example
buf := &bytes.Buffer{}
// Note: were setting WithAsync(false) here just to ensure that the output is synchronous in the example.
// In a real application, you *could* do this, but it will make your logging block the main thread until the log
// has been written to the output.
logger, _ := NewLoggerWithOptions(
	WithFields(buf, []Field{NewLevelField(Brackets.Angle), NewMessageField()}),
	WithSilent(true),
	WithAsync(false),
)

logger.Info("This is an info message.")

fmt.Print(buf.String())
Output:

func WithStdoutFormatter

func WithStdoutFormatter(formatter LogLineFormatter) LoggerOption

WithStdoutFormatter sets the formatter to use for stdout. Note: This will not overwrite existing, non-stdout destinations, if any.

func WithTag

func WithTag(tag string) LoggerOption

WithTag sets the tag for the logger.

Example

ExampleWithTag shows how to use WithTag to set the tag for the logger.

buf := &bytes.Buffer{}
logger, _ := NewLoggerWithOptions(
	WithFields(buf, []Field{NewTagField(Brackets.Square, nil), NewLevelField(Brackets.Angle), NewMessageField()}),
	WithTag("TAG"),
	WithAsync(false),
)

logger.Info("This is an info message.")

fmt.Print(buf.String())
Output:

[TAG] <INFO> This is an info message.

type ObjectField

type ObjectField[T any] struct {
	// contains filtered or unexported fields
}

ObjectField is a field that provides a formatter for a struct of type T.

func NewObjectField

func NewObjectField[T any](name string, formatter ObjectFieldFormatter[T]) (ObjectField[T], error)

NewObjectField returns a new ObjectField with the specified name and formatter. If the name is empty, an error is returned. If the formatter is nil, an error is returned.

The formatter is a function that takes a LogLineArgs and a T, and returns a FieldResult. The FieldResult contains the name of the field and the formatted data that the logger will use to create the log line.

Example

ExampleNewObjectField demonstrates how to create a custom field that formats a struct into a different struct before logging it. This is particularly useful if you need to manipulate a struct before collecting it into logs, or if you want to log only a subset of fields on a struct.

type Person struct {
	Name string
	Age  int
}

// This is the struct that will be logged. It contains a description of the person.
// Note: when using a marshalled output formatter like JSON, output will follow standard marshalling rules. That
// means that field tags are supported, and the logged struct must export its fields.
type PersonLogData struct {
	Description string `json:"description"`
}

// This is the field that actually formats the Person struct into a PersonLogData struct.
personDescriptionField, _ := NewObjectField[Person](
	"person", // The name of the field in the resulting log line.
	func(args LogLineArgs, data Person) any {
		description := fmt.Sprintf("%s is %d years old", data.Name, data.Age)
		if args.OutputFormat == OutputFormatText {
			return description
		}
		return PersonLogData{
			Description: description,
		}
	},
)

formatter, _ := NewFormatter(OutputFormatJSON, []Field{NewLevelField(Brackets.None), personDescriptionField})

// Note: We're setting WithAsync(false) here just to ensure that the output is synchronous in the example.
// In a real application, you *could* do this, but it will make your logging block the main thread until the log
// has been written to the output.
logger, _ := NewLoggerWithOptions(WithDestination(os.Stdout, formatter), WithAsync(false))

john := Person{
	Name: "John",
	Age:  25,
}

logger.Info(john)
Output:

{"level":"INFO","person":{"description":"John is 25 years old"}}

func (ObjectField[T]) NewFieldFormatter

func (f ObjectField[T]) NewFieldFormatter() (FieldFormatter, error)

NewFieldFormatter returns the FieldFormatter for the ObjectField. Typically, the FieldFormatter is computed when we create a new ObjectField with NewObjectField, but a custom implementation can create the FieldFormatter at any time.

type ObjectFieldFormatter

type ObjectFieldFormatter[T any] func(
	args LogLineArgs,
	data T,
) any

ObjectFieldFormatter is a function that formats a struct of type T and returns the formatted data. Note that this does not (presently) return a FieldResult, but it may in the future.

type OutputFormat

type OutputFormat string

OutputFormat is a type representing the output format of a formatter.

It can be one of the following:

  • JSON
  • Text

TODO: Add more output formats [YAML, XML, etc.]

const (
	OutputFormatJSON OutputFormat = "json"
	OutputFormatText OutputFormat = "text"
)

type RequestFieldSettings

type RequestFieldSettings struct {
	// TimeFormat is the format to use for the ReceivedAt field.
	TimeFormat string

	// LogReceivedAt determines whether to include the ReceivedAt field in the formatted output.
	LogReceivedAt bool
	// LogMethod determines whether to include the Method field in the formatted output.
	LogMethod bool
	// LogPath determines whether to include the Path field in the formatted output.
	LogPath bool
	// LogSourceIP determines whether to include the SourceIP field in the formatted output.
	LogSourceIP bool
}

RequestFieldSettings is a struct that contains settings for the RequestField.

The settings are used to determine which fields of the http.Request struct to include in the formatted output, as well as the format to use for the fields.

If the time format is empty, the default time format is used.

type RequestLogEntry

type RequestLogEntry struct {
	ReceivedAt time.Time
	Method     string
	Path       string
	SourceIP   string
}

RequestLogEntry is a struct that represents a formatted http.Request.

func (*RequestLogEntry) String

func (r *RequestLogEntry) String(timeFmt string) string

type ResponseFieldSettings

type ResponseFieldSettings struct {
	// LogStatus determines whether to include the http.Response.Status field in the formatted output.
	LogStatus bool
	// LogStatusCode determines whether to include the http.Response.StatusCode field in the formatted output.
	LogStatusCode bool
	// LogPath determines whether to include the associated http.Request.URL.Path field in the formatted output.
	LogPath bool
}

type ResponseLogEntry

type ResponseLogEntry struct {
	StatusCode int
	Status     string
	Path       string
}

func (*ResponseLogEntry) String

func (r *ResponseLogEntry) String() string

type SimpleBracket

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

SimpleBracket is a simple bracket type that can be used to create custom bracket types.

Example
myBracket := SimpleBracket{"!=", "=!"}
fmt.Println(myBracket.Wrap("test"))
Output:

!=test=!

func (SimpleBracket) Close

func (sb SimpleBracket) Close() string

Close returns the closing bracket for the bracket type.

Example
b := SimpleBracket{"<", ">"}
fmt.Println(b.Close())
Output:

>

func (SimpleBracket) Open

func (sb SimpleBracket) Open() string

Open returns the opening bracket for the bracket type.

Example
b := SimpleBracket{"<", ">"}
fmt.Println(b.Open())
Output:

<

func (SimpleBracket) Wrap

func (sb SimpleBracket) Wrap(content string) string

Wrap wraps the content in the bracket type.

Example
b := SimpleBracket{"<", ">"}
fmt.Println(b.Wrap("test"))
Output:

<test>

type TagPadSettings

type TagPadSettings struct {
	// PadChar is the character to use for padding. If empty, it will default to a space.
	PadChar string
	// PrefixPadSize is the number of times PadChar will be added before the tag.
	PrefixPadSize int
	// SuffixPadSize is the number of times PadChar will be added after the tag.
	SuffixPadSize int
}

TagPadSettings are the settings for padding a tag field. If PadChar is empty, it will default to a space. Note: for non-text formatters the padding setting may be ignored (it is in the built in JSON formatter).

type TextFormatter

type TextFormatter struct {
	Fields         []Field
	FieldSeparator string
}

TextFormatter is a formatter that formats log lines as text.

func (*TextFormatter) FormatLogLine

func (f *TextFormatter) FormatLogLine(args LogLineArgs, data any) FormatResult

FormatLogLine formats the log line using the provided data and returns a FormatResult which contains the formatted log line and any errors that may have occurred.

Jump to

Keyboard shortcuts

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