Documentation
¶
Index ¶
- Variables
- type AnsiSetting
- type Bracket
- type Color
- type ColorAnsi
- func (ac ColorAnsi) Bold() ColorAnsi
- func (ac ColorAnsi) Colorize(content []byte) []byte
- func (ac ColorAnsi) Dim() ColorAnsi
- func (ac ColorAnsi) Italic() ColorAnsi
- func (ac ColorAnsi) SetBackground(background ColorAnsiBackground) ColorAnsi
- func (ac ColorAnsi) SlowBlink() ColorAnsi
- func (ac ColorAnsi) Underline() ColorAnsi
- type ColorAnsiBackground
- type ColorizedFormatter
- type ErrorAmbiguousDestination
- type ErrorFieldFormatterInit
- type ErrorFileNotFound
- type ErrorInvalidFieldDataType
- type ErrorInvalidOutput
- type ErrorLevelParsing
- type ErrorLoggerInitialization
- type ErrorMissingLevelColor
- type Field
- func NewArrayField[T any](name string, formatter ObjectFieldFormatter[T]) (Field, error)
- func NewBoolField(name string) (Field, error)
- func NewCurrentTimeField(name, format string) (Field, error)
- func NewDefaultTagField() Field
- func NewDurationField(name string) (Field, error)
- func NewErrorField(name string) (Field, error)
- func NewFloatField(name string) (Field, error)
- func NewIntField(name string) (Field, error)
- func NewLevelField(bracket Bracket) Field
- func NewMapField[K comparable, V any](name string, keyFormatter ObjectFieldFormatter[K], ...) (Field, error)
- func NewMessageField() Field
- func NewRequestField(name string, settings RequestFieldSettings) (Field, error)
- func NewResponseField(name string, settings ResponseFieldSettings) (Field, error)
- func NewStringField(name string) (Field, error)
- func NewTagField(bracket Bracket, padSettings *TagPadSettings) Field
- func NewTimeField(name, format string) (Field, error)
- type FieldFormatter
- type FieldResult
- type FormatResult
- type FormatterOption
- type JSONFormatter
- type Level
- type LogLineArgs
- type LogLineFormatter
- type Logger
- type LoggerOption
- func WithAsync(async bool) LoggerOption
- func WithCustomColorization(writer io.Writer, colors map[Level]Color) LoggerOption
- func WithDefaultColorizationEnabled(writer io.Writer) LoggerOption
- func WithDestination(destination io.Writer, formatter LogLineFormatter) LoggerOption
- func WithDestinations(destinations map[io.Writer]LogLineFormatter) LoggerOption
- func WithFallbackEnabled(fallback bool) LoggerOption
- func WithFields(writer io.Writer, fields []Field) LoggerOption
- func WithMinLevel(level Level) LoggerOption
- func WithPanicOnPanicLevel(panicOnPanicLevel bool) LoggerOption
- func WithSilent(silent bool) LoggerOption
- func WithStdoutFormatter(formatter LogLineFormatter) LoggerOption
- func WithTag(tag string) LoggerOption
- type ObjectField
- type ObjectFieldFormatter
- type OutputFormat
- type RequestFieldSettings
- type RequestLogEntry
- type ResponseFieldSettings
- type ResponseLogEntry
- type SimpleBracket
- type TagPadSettings
- type TextFormatter
Examples ¶
- ColorAnsi.Colorize
- ColorAnsi.Colorize (Multiple)
- ColorAnsi.Colorize (Rgb)
- Field
- Field (JSON)
- NewArrayField
- NewArrayField (JSON)
- NewFormatter
- NewFormatter (JSON)
- NewObjectField
- SimpleBracket
- SimpleBracket.Close
- SimpleBracket.Open
- SimpleBracket.Wrap
- WithCustomColorization
- WithDefaultColorization
- WithDefaultColorizationEnabled
- WithDestination
- WithDestination (SharedFormatter)
- WithDestinations
- WithFields
- WithMinLevel
- WithSilent
- WithTag
Constants ¶
This section is empty.
Variables ¶
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.
var Brackets = struct { Angle Bracket Square Bracket Round Bracket Curly Bracket None Bracket }{ Angle: SimpleBracket{"<", ">"}, Square: SimpleBracket{"[", "]"}, Round: SimpleBracket{"(", ")"}, Curly: SimpleBracket{"{", "}"}, None: SimpleBracket{"", ""}, }
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.
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.
var ErrorEmptyFieldName = errors.New("field name cannot be empty")
var ErrorFileNotSpecified = errors.New("filename not provided to NewFileLogger")
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 ¶
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 ¶
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 ¶
ColorAnsiRGB returns a ColorAnsi that represents an RGB color.
func (ColorAnsi) Colorize ¶
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) SetBackground ¶
func (ac ColorAnsi) SetBackground(background ColorAnsiBackground) ColorAnsi
SetBackground returns a new ColorAnsi with the specified background color.
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 ¶
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 ¶
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 ¶
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 ¶
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 ¶
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 ¶
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 ¶
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 ¶
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 ¶
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 ¶
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.
func ParseLevel ¶
ParseLevel parses a string into a Level. Returns an error if the string is not a valid Level.
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"}
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 ¶
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 ¶
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: <
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 ¶
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.