sypl

package module
v1.1.2 Latest Latest
Warning

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

Go to latest
Published: Jul 13, 2021 License: MIT Imports: 16 Imported by: 3

README

sypl

sypl provides a Simple Yet Powerful Logger built on top of the Golang sypl. A sypl logger can have many Outputs, and each Output is responsible for writing to a specified destination. Each Output can have multiple Processors, which run in isolation manipulating the log message. The order of execution is important, and is according to the registering (add) order. These features allow sypl to fit into many different logging flows.

Install

$ go get github.com/saucelabs/sypl

Specific version

Example:

$ go get github.com/saucelabs/sypl@v1.0.0

Usage

See example/ folder, and sypl_test.go file or run $ make doc

How it works

A picture worth thousand words.

high-level-arch

Development

Check out CONTRIBUTION.

Release

  1. Update CHANGELOG accordingly.
  2. Once changes from MR are merged.
  3. Tag and release.

Roadmap

Check out CHANGELOG.

Documentation

Overview

Package sypl provides a Simple Yet Powerful Logger built on top of the Golang logger. A sypl logger can have many `Output`s, and each `Output` is responsible for writing to a specified destination. Each Output can have multiple `Processor`s, which run in isolation manipulating the log message. The order of execution is according to the registering order. The above features allow sypl to fit into many different logging flows and needs.

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	Red        = color.New(color.FgRed).SprintFunc()
	BoldRed    = color.New(color.FgRed, color.Bold).SprintFunc()
	Green      = color.New(color.FgGreen).SprintFunc()
	BoldGreen  = color.New(color.FgGreen, color.Bold).SprintFunc()
	Yellow     = color.New(color.FgYellow).SprintFunc()
	BoldYellow = color.New(color.FgYellow, color.Bold).SprintFunc()
)

Built-in available colors.

Functions

func OutputsNames

func OutputsNames(outputs []*Output) string

OutputsNames extract the names of the given outputs.

func ProcessorsNames added in v1.1.0

func ProcessorsNames(processors []*Processor) string

ProcessorsNames extract the names of the given processors.

Types

type Casing

type Casing string

Casing definition, e.g.: Upper, Lower, Title, etc.

const (
	// Lowercase casing.
	Lowercase Casing = "lowercase"

	// Uppercase casing.
	Uppercase Casing = "uppercase"
)

type Color

type Color func(a ...interface{}) string

Color specification.

type FileRotationOptions

type FileRotationOptions lumberjack.Logger

FileRotationOptions for the log file.

type Message

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

Message envelops the content storing references of the `Logger`, `Output` and used `Processor`s. The original content is also stored, and can be used - but no changed by `Processor`s.

func NewMessage added in v1.1.0

func NewMessage(sypl *Sypl, output *Output, processor *Processor, level level.Level, ct string) *Message

NewMessage creates a new message.

func (*Message) AddTags added in v1.1.0

func (m *Message) AddTags(tags ...string)

AddTags adds one or more tags.

func (*Message) ContainTag added in v1.1.0

func (m *Message) ContainTag(tag string) bool

ContainTag verifies if `tags` contains the specified `tag`.

func (*Message) DeleteTag added in v1.1.0

func (m *Message) DeleteTag(tag string)

DeleteTag deletes a tag.

func (*Message) GetFlag added in v1.1.0

func (m *Message) GetFlag() flag.Flag

GetFlag returns message's `Flag`.

func (*Message) GetID added in v1.1.0

func (m *Message) GetID() string

GetID returns the message's `id`.

func (*Message) GetLevel added in v1.1.0

func (m *Message) GetLevel() level.Level

GetLevel returns the message's `Level`.

func (*Message) GetOriginalContent added in v1.1.0

func (m *Message) GetOriginalContent() string

GetOriginalContent returns the original, non-modified content.

func (*Message) GetOutput added in v1.1.0

func (m *Message) GetOutput() *Output

GetOutput returns the message's `Output`.

func (*Message) GetProcessedContent added in v1.1.0

func (m *Message) GetProcessedContent() string

GetProcessedContent returns the content to be processed.

func (*Message) GetProcessor added in v1.1.0

func (m *Message) GetProcessor() *Processor

GetProcessor returns the message's `Processor`.

func (*Message) GetSypl added in v1.1.0

func (m *Message) GetSypl() *Sypl

GetSypl returns the message's `Sypl`.

func (*Message) GetTags added in v1.1.0

func (m *Message) GetTags() []string

GetTags retrieves tags.

func (*Message) GetTimestamp added in v1.1.0

func (m *Message) GetTimestamp() time.Time

GetTimestamp returns the message's `timestamp`.

func (*Message) SetFlag added in v1.1.0

func (m *Message) SetFlag(flag flag.Flag)

SetFlag flags message.

func (*Message) SetOutput added in v1.1.0

func (m *Message) SetOutput(output *Output)

SetOutput sets message's `Output`.

func (*Message) SetProcessedContent added in v1.1.0

func (m *Message) SetProcessedContent(content string)

SetProcessedContent sets the processed content.

func (*Message) SetProcessor added in v1.1.0

func (m *Message) SetProcessor(processor *Processor)

SetProcessor sets message's `Processor`.

func (*Message) SetSypl added in v1.1.0

func (m *Message) SetSypl(sypl *Sypl)

SetSypl sets message's `Sypl`.

type Options added in v1.1.0

type Options struct {
	// Flag define behaviors.
	Flag flag.Flag

	// OutputsNames name of the outputs that should be used to print.
	OutputsNames []string

	// ProcessorsNames name of the processors that should be used.
	ProcessorsNames []string

	// Tags are indicators consumed by `Output`s and `Processor`s.
	Tags []string
}

Options extends `PrintX` capabilities.

func NewDefaultOptions added in v1.1.0

func NewDefaultOptions() *Options

NewDefaultOptions creates a new set of options base on default values.

type Output

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

output defines and output that could be a console, a file, or anything that implements io.Writer.

Notes: - Any message with a `level` beyond `maxLevel` will not be written. - Messages are processed according to the order `processors` are added.

func Console

func Console(maxLevel level.Level, processors ...*Processor) *Output

Console is a specialized `output` that outputs to the console (stdout).

func File

func File(path string, maxLevel level.Level, processors ...*Processor) *Output

File is a specialized `output` that outputs to the specified file.

func FileBased

func FileBased(name string, path string, maxLevel level.Level, writer io.Writer, processors ...*Processor) *Output

FileBased is a specialized `output` that outputs to a file. If the usual, and common used "-" is used, it will behave as a Console writing to stdout and named "-".

func FileWithRotation

func FileWithRotation(
	path string,
	maxLevel level.Level,
	options *FileRotationOptions,
	processors ...*Processor,
) *Output

FileWithRotation is a specialized `output` that outputs to the specified file, with rotation.

func NewOutput

func NewOutput(name string, maxLevel level.Level, writer io.Writer, processors ...*Processor) *Output

NewOutput creates a new `output`.

Notes: - The created `output` is enabled by default. - processors can be added here, or later using the `AddProcessor` method. - This method is chainable.

func (*Output) AddProcessor

func (o *Output) AddProcessor(processor *Processor) *Output

AddProcessor adds a processor.

Note: This method is chainable.

func (*Output) GetBuiltinLogger added in v1.1.0

func (o *Output) GetBuiltinLogger() *builtin.Builtin

GetBuiltinLogger returns the output's built-in logger.

func (*Output) GetMaxLevel added in v1.1.0

func (o *Output) GetMaxLevel() level.Level

GetName returns the output's `name`.

func (*Output) GetName added in v1.1.0

func (o *Output) GetName() string

GetName returns the output's `name`.

func (*Output) GetProcessor added in v1.1.0

func (o *Output) GetProcessor(i int) *Processor

GetProcessor returns the specified processor by its index.

func (*Output) GetProcessors added in v1.1.0

func (o *Output) GetProcessors() []*Processor

GetProcessors returns registered processors.

func (*Output) GetStatus

func (o *Output) GetStatus() bool

GetStatus returns if the output is enabled or disabled.

func (*Output) SetStatus

func (o *Output) SetStatus(status bool)

SetStatus allows to enable or disable an output.

type Printer

type Printer interface {
	// Print prints the message.
	Print(level level.Level, args ...interface{}) *Sypl

	// Printf prints the message according with the specified format.
	Printf(level level.Level, format string, args ...interface{}) *Sypl

	// Print prints the message, also adding a new line and the end.
	Println(level level.Level, args ...interface{}) *Sypl

	// Fatal prints the message, and exit with os.Exit(1).
	Fatal(level level.Level, args ...interface{})

	// Fatalf prints the message according with the specified format, and exit
	// with os.Exit(1).
	Fatalf(level level.Level, format string, args ...interface{})

	// Fatalln prints the message, also adding a new line and the end, and exit
	// with os.Exit(1).
	Fatalln(level level.Level, args ...interface{})
}

Printer defines possible printers.

type Processor

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

Processor processes messages. `Processor`s are self-contained algorithms that run in isolation. Any error, should be properly handled, within the processor context itself, and not bubbled up. Don't need to handle cases where message has no content - it's already done, see `sypl.Process`.

func ChangeFirstCharCase

func ChangeFirstCharCase(casing Casing) *Processor

ChangeFirstCharCase changes message content's first char to the specified case.

Notes: - `casing` because `case` is a reserved word. - Order matters! If this comes after another processor like the Prefixer, it will change the case of the first char of the Prefix mask, not the message content!

func ColorizeBasedOnLevel

func ColorizeBasedOnLevel(levelColorMap map[level.Level]Color) *Processor

ColorizeBasedOnLevel colorize messages based on the specified levels.

func ColorizeBasedOnWord

func ColorizeBasedOnWord(wordColorMap map[string]Color) *Processor

ColorizeBasedOnWord colorize a messages with the specified colors if a message contains a specific word.

func EnableDisableOutputs

func EnableDisableOutputs(status bool, names ...string) *Processor

EnableDisableOutputs enables or disables the specified outputs.

Note: Order matters! Enabling or disabling an output that was already executed as no effect at all!

func EnableDisableProcessors

func EnableDisableProcessors(status bool, names ...string) *Processor

EnableDisableProcessors enables or disables the specified processors.

Note: Order matters! Enabling or disabling a processor that was already executed as no effect at all!

func ForceBasedOnLevel

func ForceBasedOnLevel(levels ...level.Level) *Processor

ForceBasedOnLevel force messages to be printed based on the specified levels.

func MuteBasedOnLevel

func MuteBasedOnLevel(levels ...level.Level) *Processor

MuteBasedOnLevel mute messages based on the specified levels.

func NewProcessor

func NewProcessor(name string, processorFunc ProcessorFunc) *Processor

NewProcessor creates a new `Processor`.

Notes: - The created `Processor` is enabled by default. - This method is chainable.

func PrefixBasedOnMask

func PrefixBasedOnMask(timestampFormat string) *Processor

PrefixBasedOnMask prefixes messages with the predefined mask.

Example: 2021-06-22 12:51:46.089 [80819] [CLI] [Info].

func PrefixBasedOnMaskExceptForLevels

func PrefixBasedOnMaskExceptForLevels(timestampFormat string, levels ...level.Level) *Processor

PrefixBasedOnMaskExceptForLevels is a specialized version of the `PrefixBasedOnMask`. It prefixes all messages, except for the specified levels.

func Prefixer

func Prefixer(prefix string) *Processor

Prefixer prefixes messages with the given string.

func Suffixer

func Suffixer(suffix string) *Processor

Suffixer suffixes messages with the given string.

func (*Processor) GetName added in v1.1.0

func (p *Processor) GetName() string

GetName returns the processor's name.

func (*Processor) GetStatus

func (p *Processor) GetStatus() bool

GetStatus returns if the processor is enabled or disabled.

func (*Processor) Run

func (p *Processor) Run(message *Message)

Process the message.

func (*Processor) SetStatus

func (p *Processor) SetStatus(status bool)

SetStatus allows to enable or disable a processor.

type ProcessorFunc

type ProcessorFunc func(message *Message)

ProcessorFunc is the processor's `do` specification.

type Sypl

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

sypl definition. It's able to print messages according to the definition of each `output`.

func New

func New(name string, outputs ...*Output) *Sypl

New creates a new custom logger.

Notes: Outputs can be added here, or later using the `AddOutput` method.

Example (Chained)

Chained is the chained example of creating, and setting up a `sypl` logger. It writes to both `stdout` and `stderr`.

// Creates logger, and name it.
New("Testing Logger").
	// Creates two `Output`s. "Console" and "Error". "Console" will print to
	// `Fatal`, `Error`, and `Info`. "Error" will only print `Fatal`, and
	// `Error` levels.
	AddOutput(NewOutput("Console", level.Info, os.Stdout)).
	// Creates a `Processor`. It will prefix all messages. It will only
	// prefix messages for this specific `Output`, and @ `Error` level.
	AddOutput(NewOutput("Error", level.Error, os.Stderr).
		AddProcessor(func(prefix string) *Processor {
			return NewProcessor("Prefixer", func(message *Message) {
				if message.GetLevel() == level.Error {
					message.SetProcessedContent(prefix + message.GetProcessedContent())
				}
			})
		}(defaultPrefixValue))).
	// Prints:
	// Test info message
	Println(level.Info, "Test info message").
	// Prints:
	// Test error message
	// My Prefix - Test error message
	Println(level.Error, "Test error message")
Output:

Example (ChainedUsingBuiltin)

ChainedUsingBuiltin is the chained example of creating, and setting up a `sypl` logger using built-in `Output`, and `Processor`. It writes to `stdout`, and `stderr`.

// Creates logger, and name it.
New("Testing Logger").
	// Adds an `Output`. In this case, called "Console" that will print to
	// `stdout` and max print level @ `Info`.
	//
	// Adds a `Processor`. It will prefix all messages.
	AddOutput(Console(level.Info).AddProcessor(Prefixer(defaultPrefixValue))).
	// Prints: My Prefix - Test info message
	Infoln("Test info message")
Output:

My Prefix - Test info message
Example (InlineUsingBuiltin)

inlineUsingBuiltin same as `ChainedUsingBuiltin` but using inline form.

New("Testing Logger", Console(level.Info).AddProcessor(Prefixer(defaultPrefixValue))).Infoln("Test info message")
Output:

My Prefix - Test info message
Example (NotChained)

NonChained is a non-chained example of creating, and setting up a `sypl` logger. It writes to a custom buffer.

var buf bytes.Buffer
bufWriter := bufio.NewWriter(&buf)

// Creates logger, and name it.
testingLogger := New("Testing Logger")

// Creates an `Output`. In this case, called "Console" that will print to
// `stdout` and max print level @ `Info`.
ConsoleToStdOut := NewOutput("Console", level.Info, bufWriter)

// Creates a `Processor`. It will prefix all messages.
Prefixer := func(prefix string) *Processor {
	return NewProcessor("Prefixer", func(message *Message) {
		message.SetProcessedContent(prefix + message.GetProcessedContent())
	})
}

// Adds `Processor` to `Output`.
ConsoleToStdOut.AddProcessor(Prefixer(defaultPrefixValue))

// Adds `Output` to logger.
testingLogger.AddOutput(ConsoleToStdOut)

// Writes: "My Prefix - Test message"
testingLogger.Print(level.Info, "Test info message")

bufWriter.Flush()

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

My Prefix - Test info message
Example (PrintPretty)

PrintPretty example.

New("Testing Logger", Console(level.Info)).PrintPretty(NewDefaultOptions())
Output:

{
	"Flag": 0,
	"OutputsNames": [],
	"ProcessorsNames": [],
	"Tags": []
}
Example (PrintWithOptions)

printWithOptions demonstrates `sypl` flexibility. `Options` enhances the usual `PrintX` methods allowing to specify flags, and tags.

// Creates logger, and name it.
testingLogger := New("Testing Logger")

// Creates 3 `Output`s, all called "Console" that will print to `stdout`, and
// max print level @ `Info`.
Console1ToStdOut := NewOutput("Console 1", level.Info, os.Stdout)
Console2ToStdOut := NewOutput("Console 2", level.Info, os.Stdout)
Console3ToStdOut := NewOutput("Console 3", level.Info, os.Stdout)

// Creates a `Processor`. It will `prefix` all messages with the Output, and
// Processor names.
Prefixer := func() *Processor {
	return NewProcessor("Prefixer", func(message *Message) {
		prefix := fmt.Sprintf("Output: %s Processor: %s Content: ",
			message.GetOutput().GetName(),
			message.GetProcessor().GetName(),
		)

		message.SetProcessedContent(prefix + message.GetProcessedContent())
	})
}

// Creates a `Processor`. It will `suffix` all messages with the specified
// `tag`.
SuffixBasedOnTag := func(tag string) *Processor {
	return NewProcessor("SuffixBasedOnTag", func(message *Message) {
		if message.ContainTag(tag) {
			message.SetProcessedContent(message.GetProcessedContent() + " - My Suffix")
		}
	})
}

// Adds `Processor`s to `Output`s.
Console1ToStdOut.
	AddProcessor(Prefixer()).
	AddProcessor(SuffixBasedOnTag("SuffixIt"))
Console2ToStdOut.
	AddProcessor(Prefixer()).
	AddProcessor(SuffixBasedOnTag("SuffixIt"))
Console3ToStdOut.
	AddProcessor(Prefixer()).
	AddProcessor(SuffixBasedOnTag("SuffixIt"))

// Adds all `Output`s to logger.
testingLogger.
	AddOutput(Console1ToStdOut).
	AddOutput(Console2ToStdOut).
	AddOutput(Console3ToStdOut)

// Prints with prefix, without suffix.
testingLogger.Println(level.Info, defaultContentOutput)

// Prints with prefix, and suffix.
testingLogger.PrintWithOptions(&Options{
	OutputsNames:    []string{"Console 1"},
	ProcessorsNames: []string{"Prefixer", "SuffixBasedOnTag"},
	Tags:            []string{"SuffixIt"},
}, level.Info, defaultContentOutput)

// output:
// Output: Console 1 Processor: Prefixer Content: contentTest
// Output: Console 2 Processor: Prefixer Content: contentTest
// Output: Console 3 Processor: Prefixer Content: contentTest
Output:

Output: Console 1 Processor: Prefixer Content: contentTest
Output: Console 2 Processor: Prefixer Content: contentTest
Output: Console 3 Processor: Prefixer Content: contentTest
Output: Console 1 Processor: Prefixer Content: contentTest - My Suffix

func (*Sypl) AddOutput

func (sypl *Sypl) AddOutput(output *Output) *Sypl

AddOutput adds an `output` to logger.

Note: This method is chainable.

func (*Sypl) Debug

func (sypl *Sypl) Debug(args ...interface{}) *Sypl

Debug prints the message (if has content) @ the Debug level.

func (*Sypl) Debugf

func (sypl *Sypl) Debugf(format string, args ...interface{}) *Sypl

Debugf prints the message (if has content) according with the specified format @ the Debug level.

func (*Sypl) Debugln

func (sypl *Sypl) Debugln(args ...interface{}) *Sypl

Debugln prints the message (if has content), also adding a new line to the end @ the Debug level.

func (*Sypl) Error

func (sypl *Sypl) Error(args ...interface{}) *Sypl

Error prints the message (if has content) @ the Error level.

func (*Sypl) Errorf

func (sypl *Sypl) Errorf(format string, args ...interface{}) *Sypl

Errorf prints the message (if has content) according with the specified format @ the Error level.

func (*Sypl) Errorln

func (sypl *Sypl) Errorln(args ...interface{}) *Sypl

Errorln prints the message (if has content), also adding a new line to the end @ the Error level.

func (*Sypl) Fatal

func (sypl *Sypl) Fatal(args ...interface{})

Fatal prints the message (if has content), and exit with os.Exit(1).

func (*Sypl) Fatalf

func (sypl *Sypl) Fatalf(format string, args ...interface{})

Fatalf prints the message (if has content) according with the specified format, and exit with os.Exit(1).

func (*Sypl) Fatalln

func (sypl *Sypl) Fatalln(args ...interface{})

Fatalln prints the message (if has content), also adding a new line and the end, and exit with os.Exit(1).

func (*Sypl) GetName added in v1.1.0

func (sypl *Sypl) GetName() string

GetName returns the sypl name.

func (*Sypl) GetOutput added in v1.1.0

func (sypl *Sypl) GetOutput(i int) *Output

GetOutput returns the specified output by its index.

func (*Sypl) GetOutputs added in v1.1.0

func (sypl *Sypl) GetOutputs() []*Output

GetOutputs returns registered outputs.

func (*Sypl) Info

func (sypl *Sypl) Info(args ...interface{}) *Sypl

Info prints the message (if has content) @ the Info level.

func (*Sypl) Infof

func (sypl *Sypl) Infof(format string, args ...interface{}) *Sypl

Infof prints the message (if has content) according with the specified format @ the Info level.

func (*Sypl) Infoln

func (sypl *Sypl) Infoln(args ...interface{}) *Sypl

Infoln prints the message (if has content), also adding a new line to the end @ the Info level.

func (*Sypl) Print

func (sypl *Sypl) Print(level level.Level, args ...interface{}) *Sypl

Print prints the message (if has content).

func (*Sypl) PrintPretty added in v1.1.1

func (sypl *Sypl) PrintPretty(data interface{})

PrintPretty prints data structures as JSON text.

func (*Sypl) PrintWithOptions added in v1.1.0

func (sypl *Sypl) PrintWithOptions(options *Options, level level.Level, args ...interface{}) *Sypl

PrintWithOptions prints the message (if has content), with `Options` to the specified outputs.

func (*Sypl) Printf

func (sypl *Sypl) Printf(level level.Level, format string, args ...interface{}) *Sypl

Printf prints the message (if has content) according with the specified format.

func (*Sypl) PrintfWithOptions added in v1.1.0

func (sypl *Sypl) PrintfWithOptions(options *Options, level level.Level, format string, args ...interface{}) *Sypl

PrintfWithOptions prints the message (if has content), with `Options` according with the specified format, and to the specified outputs.

func (*Sypl) Println

func (sypl *Sypl) Println(level level.Level, args ...interface{}) *Sypl

Println prints the message (if has content), also adding a new line to the end.

func (*Sypl) PrintlnPretty added in v1.1.1

func (sypl *Sypl) PrintlnPretty(data interface{})

PrintlnPretty prints data structures as JSON text, also adding a new line to the end. Its content will be printed regardless of the level, and it isn't processed.

func (*Sypl) PrintlnWithOptions added in v1.1.0

func (sypl *Sypl) PrintlnWithOptions(options *Options, level level.Level, args ...interface{}) *Sypl

PrintlnWithOptions prints the message (if has content), with `Options`, also adding a new line to the end, and to the specified outputs.

func (*Sypl) Trace

func (sypl *Sypl) Trace(args ...interface{}) *Sypl

Trace prints the message (if has content) @ the Trace level.

func (*Sypl) Tracef

func (sypl *Sypl) Tracef(format string, args ...interface{}) *Sypl

Tracef prints the message (if has content) according with the specified format @ the Trace level.

func (*Sypl) Traceln

func (sypl *Sypl) Traceln(args ...interface{}) *Sypl

Traceln prints the message (if has content), also adding a new line to the end @ the Trace level.

func (*Sypl) Warn

func (sypl *Sypl) Warn(args ...interface{}) *Sypl

Warn prints the message (if has content) @ the Warn level.

func (*Sypl) Warnf

func (sypl *Sypl) Warnf(format string, args ...interface{}) *Sypl

Warnf prints the message (if has content) according with the specified format @ the Warn level.

func (*Sypl) Warnln

func (sypl *Sypl) Warnln(args ...interface{}) *Sypl

Warnln prints the message (if has content), also adding a new line to the end @ the Warn level.

Directories

Path Synopsis
internal
builtin
Package log implements a simple logging package.
Package log implements a simple logging package.

Jump to

Keyboard shortcuts

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