pio

package module
v0.0.0-...-235e7d4 Latest Latest
Warning

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

Go to latest
Published: Aug 11, 2024 License: BSD-3-Clause Imports: 16 Imported by: 2

README ¶

💊 PIO

PIO [Pill for Input/Output] tries to cure headaches by solving problems where go applications use different kinds of print targets or even loggers.

build status report card godocs github issues github closed issues

  • it can combine all your loggers as one
  • it can scan from any source and print
  • opossite is possible too, it use one or more sources to output when printing

Navigate through _examples and integrations to learn if can cure yours too.

🚀 Installation

The only requirement is the Go Programming Language*.

$ go get github.com/kataras/pio

PIO is built on top of the standard library, it has zero external dependencies.

👥 Contributing

If you find that something is not working as expected please open an issue.

If you have any previous experience on this field your PR means gold to me!

📦 Projects using PIO
Package Author Description
golog Gerasimos Maropoulos Simple, fast and easy-to-use level-based logger written entirely in GoLang.

Do not hesitate to put your package on this list via PR!

Documentation ¶

Index ¶

Constants ¶

This section is empty.

Variables ¶

View Source
var (
	// ErrCanceled is returned when a hijacker canceled a specific print action.
	ErrCanceled = errors.New("canceled")
	// ErrSkipped it returned from marshaler or hijacker
	// when the content should be skipped and printer should avoid printing it.
	ErrSkipped = errors.New("skipped")
)
View Source
var (
	// JSON returns the JSON encoding of Printer#Print%v.
	// A shortcut for `encoding/json#Marshal`
	JSON = MarshalerFunc(json.Marshal)
	// JSONIndent returns the JSON encoding of Printer#Print%v.
	// A shortcut for `encoding/json#MarshalIndent(v, ""," ")`
	JSONIndent = MarshalerFunc(func(v interface{}) ([]byte, error) {
		return json.MarshalIndent(v, "", " ")
	})

	// XML returns the XML encoding of Printer#Print%v.
	// A shortcut for `encoding/xml#Marshal`
	XML = MarshalerFunc(xml.Marshal)
	// XMLIndent returns the XML encoding of Printer#Print%v.
	// A shortcut for `encoding/xml#MarshalIndent(v, ""," ")`
	XMLIndent = MarshalerFunc(func(v interface{}) ([]byte, error) {
		return xml.MarshalIndent(v, "", " ")
	})
)
View Source
var ColorBlue = 34

ColorBlue represents the blue color.

View Source
var ColorGray = 37

ColorGray represents the gray color.

View Source
var ColorGreen = 32

ColorGreen represents the green color.

View Source
var ColorLightGreen = 36

ColorLightGreen represents a light green color.

View Source
var ColorPurple = 35

ColorPurple represents the purple color.

View Source
var ColorRed = 31

ColorRed represents the red color.

View Source
var ColorRedBackground = 41

ColorRedBackground represents a white foreground color and red background.

View Source
var ColorWhite = 0

ColorWhite represents the white color.

View Source
var ColorYellow = 33

ColorYellow represents the yellow color.

View Source
var Default = NewRegistry()

Default returns the default, package-level registry instance.

View Source
var ErrMarshalNotFound = errors.New("no marshaler found for this type of dat")

ErrMarshalNotFound or ErrSkipped can be used to skip a specific printer's output operation.

View Source
var ErrMarshalNotResponsible = errors.New("this marshaler is not responsible for this type of data")

ErrMarshalNotResponsible retruns from a marshaler when it's not responsible and should continue to the next marshaler.

View Source
var NewLine = []byte("\n")

NewLine is a slice of bytes which controls the how a new line should be presented.

Defaults to \n.

View Source
var OutputFrom = OutputAdapters{}

OutputFrom is a variable which contains some helpers that can convert some forms of output to compatible `io.Writer` in order to be passed to the `NewPrinter` or `Register` functions.

View Source
var Text = MarshalerFunc(func(v interface{}) ([]byte, error) {
	if b, ok := v.([]byte); ok {
		return b, nil
	}
	if s, ok := v.(string); ok {
		return []byte(s), nil
	}

	return nil, ErrMarshalNotResponsible
})

Text is a Text marshaler, it converts string to a compatible form of []byte.

View Source
var (
	// TotalPrinters holds the number of
	// the total printers created, either by
	// `NewPrinter`, `NewTextPrinter`, `Register` or `RegisterPrinter`
	TotalPrinters int32
)

Functions ¶

func Blue ¶

func Blue(s string) string

Blue returns the string contents of "s" wrapped by blue foreground color.

func Gray ¶

func Gray(s string) string

Gray returns the string contents of "s" wrapped by gray foreground color.

func Green ¶

func Green(s string) string

Green returns the string contents of "s" wrapped by green foreground color.

func IsNop ¶

func IsNop(w io.Writer) bool

IsNop can check wether an `w` io.Writer is a NopOutput.

func LightGreen ¶

func LightGreen(s string) string

LightGreen returns the string contents of "s" wrapped by a light green foreground color.

func NopCloser ¶

func NopCloser() io.Closer

NopCloser returns an `io.Closer` which does nothing.

func NopOutput ¶

func NopOutput() io.Writer

NopOutput returns an `io.Writer` which writes nothing.

func Print ¶

func Print(v interface{}) (int, error)

Print accepts a value of "v", tries to marshal its contents and flushes the result to all available printers.

func Println ¶

func Println(v interface{}) (int, error)

Println accepts a value of "v", tries to marshal its contents and flushes the result to all available printers, it adds a new line at the ending, the result doesn't contain this new line, therefore result's contnets kept as expected.

func Purple ¶

func Purple(s string) string

Purple returns the string contents of "s" wrapped by purple foreground color.

func Red ¶

func Red(s string) string

Red returns the string contents of "s" wrapped by red foreground color.

func RedBackground ¶

func RedBackground(s string) string

RedBackground returns the string contents of "s" wrapped by white foreground color and red background.

func Remove ¶

func Remove(printerName string)

Remove deletes a printer item from the printers collection by its name.

func Scan ¶

func Scan(r io.Reader, addNewLine bool) (cancel func())

Scan scans everything from "r" and prints its new contents to the printers, forever or until the returning "cancel" is fired, once.

func White ¶

func White(s string) string

White returns the string contents of "s" wrapped by white foreground color.

func Wrap ¶

func Wrap(printFn interface{}) io.Writer

Wrap returns a new output based on the "printfFn" if not a compatible output found then it will return a writer which writes nothing.

To check if the wrapping worked you can check if the result `io.Writer` `IsNop`, i.e: std's log.Panicf is not a compatible interface

output := Output(log.Panicf)

if IsNop(output) {
	// conversation failed, do something or panic.
}

func Yellow ¶

func Yellow(s string) string

Yellow returns the string contents of "s" wrapped by yellow foreground color.

Types ¶

type Ctx ¶

type Ctx struct {
	// Printer is the current Printer which this ctx is owned by.
	Printer *Printer
	// Value is the argument passed to the `Printer#Print`.
	//
	// Value shoult not be changed.
	Value interface{}
	// contains filtered or unexported fields
}

Ctx is the current context of the Printer's hijacker, should not be used inside goroutines, exiting this hijacker allows the Printer to continue its execution.

func (*Ctx) Cancel ¶

func (ctx *Ctx) Cancel()

Cancel cancels the printing of this `Value`.

func (*Ctx) MarshalValue ¶

func (ctx *Ctx) MarshalValue() ([]byte, error)

MarshalValue marshals the `Value` and skips the marshal operation on the `Printer#Print` state.

Remember that if `MarshalValue` called after a `SetResult` then it will not operate a marshaling and return the stored result instead.

func (*Ctx) Next ¶

func (ctx *Ctx) Next()

Next allows to continue to the next hijacker,if available, when this hijacker finished.

func (*Ctx) Store ¶

func (ctx *Ctx) Store(result []byte, err error)

Store bypasses the marshaler and sets the result explicitly. If any of the next hijackers try to call the `MarshalValue` then it will return the results that had set here.

type Handler ¶

type Handler func(PrintResult)

Handler is the signature implemented by callers that want to be notified about the results that are being printed to the Printer's output.

Look `Printer#Handle` for more.

type Hijacker ¶

type Hijacker func(*Ctx)

Hijacker is the signature implemented by callers that want to hijack the Print method.

Look `Printer#Hijack` for more.

type Marshaled ¶

type Marshaled interface {
	Marshal() ([]byte, error)
}

Marshaled or (especially British, marshalled) is an interface which is implemented by values that can marshal theirselves.

It's like Marshaler but it doesn't takes an argument.

type Marshaler ¶

type Marshaler interface {
	Marshal(v interface{}) ([]byte, error)
}

Marshaler is the interface implemented by types that can marshal themselves into valid output.

type MarshalerFunc ¶

type MarshalerFunc func(v interface{}) ([]byte, error)

MarshalerFunc is the signature implemented by callers that are responsible to marshal "v" into valid printable result.

Look `Printer#Marshal` for more.

func (MarshalerFunc) Marshal ¶

func (m MarshalerFunc) Marshal(v interface{}) ([]byte, error)

Marshal makes the Marshaler compatible with the standard golang's marshalers, so a marshaler created for a Printer, can be used on std packages as well.

type OutputAdapters ¶

type OutputAdapters struct{}

OutputAdapters is a struct which contains some forms of output and convert them to a compatible `io.Writer` in order to be passed to the `NewPrinter` or `Register` functions.

func (*OutputAdapters) Print ¶

func (a *OutputAdapters) Print(print func(v interface{})) io.Writer

Print converts a func(v interface{}) to a compatible `io.Writer`.

func (*OutputAdapters) PrintVardiadic ¶

func (a *OutputAdapters) PrintVardiadic(print func(v ...interface{})) io.Writer

PrintVardiadic converts a func(v ...interface{}) to a compatible `io.Writer`.

func (*OutputAdapters) Printf ¶

func (a *OutputAdapters) Printf(printf func(format string, args ...interface{})) io.Writer

Printf converts a func(string, ...interface{}) to a compatible `io.Writer`.

func (*OutputAdapters) Println ¶

func (a *OutputAdapters) Println(println func(s string), newLine bool) io.Writer

Println converts a func(string) to a compatible `io.Writer`. if "newLine" is true then "\n" will be appended to the "s".

type PrintResult ¶

type PrintResult struct {
	Written  int
	Error    error
	Contents []byte
	Value    interface{}
}

PrintResult contains some useful information for a `Print` or `WriteTo` action that are available inside handlers.

func (PrintResult) IsFailure ¶

func (p PrintResult) IsFailure() bool

IsFailure returns true if result's content is not safe to read or it's available, otherwise false.

func (PrintResult) IsOK ¶

func (p PrintResult) IsOK() bool

IsOK returns true if result's content is available, otherwise false.

type Printer ¶

type Printer struct {
	Name       string
	IsTerminal bool

	// if Chained is true then the parent `Registry#Print`
	// will continue to search for a compatible printer
	// even if this printer succeed to print the contents.
	Chained bool
	Output  io.Writer

	// these three will complete the interface of the:
	// https://golang.org/pkg/io/#ReadWriteCloser
	// in order to make possible to use everything inside the `io` package.
	// i.e
	// https://golang.org/pkg/io/#example_MultiWriter
	// https://golang.org/pkg/io/#example_TeeReader (piping)
	io.Reader
	io.Writer
	io.Closer
	// DirectOutput will output the contents and flush them as fast as possible,
	// without storing them to the buffer to complete the `ReadWriteCloser` std interface.
	// Enable this if you need performance and you don't use the standard functions like `TeeReader`.
	DirectOutput bool
	// contains filtered or unexported fields
}

Printer is responsible to print the end result.

func Get ¶

func Get(printerName string) *Printer

Get returns a Printer based on the "printerName". If printer with this name can't be found then this function will return nil, so a check for nil is always a good practice.

func NewPrinter ¶

func NewPrinter(name string, output io.Writer) *Printer

NewPrinter returns a new named printer if "output" is nil then it doesn't prints anywhere.

If "name" is empty then it will be filled with "printer_$printers.len".

If the marshaler is nil, meaning that this writer's result will never being proceed, caller should add a marshaler using the `Marshal` function.

Look `OutputFrom` too.

func NewTextPrinter ¶

func NewTextPrinter(name string, output io.Writer) *Printer

NewTextPrinter same as NewPrinter but registers a text marshaler, no matter what kind of "output", which converts string type to a compatible form of slice of bytes.

If "name" is empty then it will be filled with "printer_$printers.len".

Look `OutputFrom` too.

func Register ¶

func Register(printerName string, output io.Writer) *Printer

Register creates and registers a new Printer based on a name(string) and an "output"(io.Writer).

If a printer with the same `Name` is already registered then it will be overridden by this new "printer".

Look `OutputFrom` too.

Returns the just created Printer.

func (*Printer) AddOutput ¶

func (p *Printer) AddOutput(writers ...io.Writer) *Printer

AddOutput adds one or more io.Writer to the Printer. Returns itself.

Look `OutputFrom` and `Wrap` too.

func (*Printer) EnableDirectOutput ¶

func (p *Printer) EnableDirectOutput() *Printer

EnableDirectOutput will output the contents and flush them as fast as possible, without storing them to the buffer to complete the `ReadWriteCloser` std interface. Enable this if you need performance and you don't use the standard functions like `TeeReader`. Returns itself.

func (*Printer) Flush ¶

func (p *Printer) Flush() ([]byte, error)

Flush will consume and flush the Printer's current contents.

func (*Printer) Handle ¶

func (p *Printer) Handle(h func(PrintResult)) *Printer

Handle adds a callback which is called whenever a `Print` is successfully executed, it's being executed after the contents are written to its output.

The callback accepts the final result, can be used as an easy, pluggable, access to all the logs passed to the `Print`. i.e: `Handle(func(result PrintResult){ fmt.Printf("%s\n", result.Contents)})`

Returns itself.

func (*Printer) Hijack ¶

func (p *Printer) Hijack(cb func(ctx *Ctx)) *Printer

Hijack registers a callback which is executed when ever `Print` or `WriteTo` is called, this callback can intercept the final result which will be written or be printed.

Returns itself.

func (*Printer) Marshal ¶

func (p *Printer) Marshal(marshaler Marshaler) *Printer

Marshal adds a "marshaler" to the printer. Returns itself.

func (*Printer) MarshalFunc ¶

func (p *Printer) MarshalFunc(marshaler func(v interface{}) ([]byte, error)) *Printer

MarshalFunc adds a "marshaler" to the printer. Returns itself.

func (*Printer) Print ¶

func (p *Printer) Print(v interface{}) (int, error)

Print of a Printer accepts a value of "v", tries to marshal its contents and flushes the result to the Printer's output.

If "v" implements the `Marshaler` type, then this marshaler is called automatically, first.

Print -> Store[Marshal -> err != nil && result -> Hijack(result) -> Write(result)] -> Flush[Printer.Write(buf) and Handle(buf)]

Returns how much written and an error on failure.

func (*Printer) Println ¶

func (p *Printer) Println(v interface{}) (int, error)

Println accepts a value of "v", tries to marshal its contents and flushes the result to this "p" Printer, it adds a new line at the ending, the result doesn't contain this new line, therefore result's contents kept as expected.

func (*Printer) Priority ¶

func (p *Printer) Priority(prio int) *Printer

Priority changes the order of this printer. Higher value means that the `Registry#Print` will try to print first from this printer. Default order is 0 for all printers.

Returns it self.

func (*Printer) Scan ¶

func (p *Printer) Scan(r io.Reader, addNewLine bool) (cancel func())

Scan scans everything from "r" and prints its new contents to the "p" Printer, forever or until the returning "cancel" is fired, once.

func (*Printer) SetOutput ¶

func (p *Printer) SetOutput(writers ...io.Writer) *Printer

SetOutput sets accepts one or more io.Writer and set a multi-writter instance to the Printer's Output. Returns itself.

Look `OutputFrom` too.

func (*Printer) Store ¶

func (p *Printer) Store(v interface{}, appendNewLine bool) error

Store will store-only the contents of "v". Returns a PrintResult type in order to the final contents be accessible by third-party tools.

If you want to Print and Flush to the Printer's Output use `Print` instead.

If "appendNewLine" is true then it writes a new line to the Printer's output. Note that it doesn't concat it to the returning PrintResult, therefore the "appendNewLine" it is not affect the rest of the implementation like custom hijackers and handlers.

func (*Printer) WithMarshalers ¶

func (p *Printer) WithMarshalers(marshalers ...Marshaler) *Printer

WithMarshalers same as `Marshal` but accepts more than one marshalers and returns the Printer itself in order to be used side by side with the creational function.

func (*Printer) WriteTo ¶

func (p *Printer) WriteTo(v interface{}, w io.Writer, appendNewLine bool) ([]byte, error)

WriteTo marshals and writes the "v" to the "w" writer.

Returns this WriteTo's result information such as error, written.

type Registry ¶

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

Registry is the Printer(s) container.

It can be used as follows: reg := NewRegistry().

RegisterPrinter(NewPrinter("err", os.Stderr)).
RegisterPrinter(NewPrinter("default", os.Stdout)).
Print("something")

func NewRegistry ¶

func NewRegistry() *Registry

NewRegistry returns an empty printer Registry.

Note that: Registry have a zero value, so it can be declared with a simple `var` keyword and without pointer.

func RegisterPrinter ¶

func RegisterPrinter(p *Printer) *Registry

RegisterPrinter registers an already-created printer to the registry.

If a printer with the same `Name` is already registered then it will be overridden by this new "printer".

Returns the Registry, therefore it can be used as builder.

func (*Registry) Get ¶

func (reg *Registry) Get(printerName string) *Printer

Get returns a Printer based on the "printerName". If printer with this name can't be found then this function will return nil, so a check for nil is always a good practice.

func (*Registry) Print ¶

func (reg *Registry) Print(v interface{}) (n int, err error)

Print accepts a value of "v", tries to marshal its contents and flushes the result to all available printers.

func (*Registry) Println ¶

func (reg *Registry) Println(v interface{}) (n int, err error)

Println accepts a value of "v", tries to marshal its contents and flushes the result to all available printers, it adds a new line at the ending, the result doesn't contain this new line, therefore result's contents kept as expected.

func (*Registry) Register ¶

func (reg *Registry) Register(printerName string, output io.Writer) *Printer

Register creates and registers a new Printer based on a name(string) and an "output"(io.Writer).

If "printerName" is empty then it will be filled with "printer_$printers.len".

If a printer with the same `Printer#Name` is already registered then it will be overridden by this new "printer".

Look `OutputFrom` too.

Returns the just created Printer.

func (*Registry) RegisterPrinter ¶

func (reg *Registry) RegisterPrinter(printer *Printer) *Registry

RegisterPrinter registers an already-created printer to the registry.

If `Printer#Name` is empty then it will be filled with "printer_$printers.len".

If a printer with the same `Printer#Name` is already registered then it will be overridden by this new "printer".

Returns this Registry, therefore it can be used as builder.

func (*Registry) Remove ¶

func (reg *Registry) Remove(printerName string) *Registry

Remove deletes a printer item from the printers collection by its name.

Returns this Registry, so it can be used as builder.

func (*Registry) Scan ¶

func (reg *Registry) Scan(r io.Reader, addNewLine bool) (cancel func())

Scan scans everything from "r" and prints its new contents to the printers, forever or until the returning "cancel" is fired, once.

Directories ¶

Path Synopsis
_examples
integrations/logrus
Package logrus registers the global logrus logger to the pio ecosystem, install logrus first:
Package logrus registers the global logrus logger to the pio ecosystem, install logrus first:

Jump to

Keyboard shortcuts

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