logger

package module
v0.5.11 Latest Latest
Warning

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

Go to latest
Published: Feb 27, 2023 License: MIT Imports: 9 Imported by: 13

README

Logger

Go Report Card Maintainability Test Coverage Build Status GoDoc

Gol4ng/Logger is another GO logger. The main line is to provide a friendly and fast API to send your log whenever you want.

Why another one?

When i start GO i searched a logger that can be simple to use, efficient, multi output, multi formats and quite easy to extend. That's why i created this logger with built-in handlers(process a log), formatters(format log in another representation), middlewares(log modification before handler)

Installation

go get -u github.com/gol4ng/logger

Quick Start

package main

import (
	"os"
	"runtime"
	
	"github.com/gol4ng/logger"
	"github.com/gol4ng/logger/formatter"
	"github.com/gol4ng/logger/handler"
)

func main(){
	// logger will print on STDOUT with default line format
	l := logger.NewLogger(handler.Stream(os.Stdout, formatter.NewDefaultFormatter(formatter.WithContext(true))))
	
	l.Debug("Go debug information", logger.String("go_os", runtime.GOOS), logger.String("go_arch", runtime.GOARCH))
	// <debug> MyExample message {"go_arch":"amd64","go_os":"darwin"}
	
	l.Info("Another")
    //<info> Another
}

Logger interface

This library expose some quite simple interfaces.

Simplest one

type LogInterface interface {
	Log(message string, level Level, field ...Field)
}

The friendly one

type LoggerInterface interface {
	LogInterface
	Debug(message string, field ...Field)
	Info(message string, field ...Field)
	Notice(message string, field ...Field)
	Warning(message string, field ...Field)
	Error(message string, field ...Field)
	Critical(message string, field ...Field)
	Alert(message string, field ...Field)
	Emergency(message string, field ...Field)
}

Handlers

Handlers are log entry processor. It received a log entry and process it in order to send log to it's destination

Available handlers:

  • stream it will write formatted log in io.Writer
  • socket it will write formatted log in net.Conn
  • chan send all entry in provided go channel
  • gelf format to gelf and send to gelf server (TCP or UDP gzipped chunk)
  • group it will send log to all provided child handlers
  • rotate it will write formatted log in file and rotate file (mode: interval/archive)
  • syslog send formatted log in syslog server

Formatters

The formatter convert log entry to a string representation (text, json, gelf...) They are often inject in handler to do the conversion process

Available formatters:

  • default <info> My log message {"my_key":"my_value"}
  • line it's just a fmt.Sprintf facade format:%s %s %s will produce My log message info <my_key:my_value>
  • gelf format log entry to gelf {"version":"1.1","host":"my_fake_hostname","level":6,"timestamp":513216000.000,"short_message":"My log message","full_message":"<info> My log message [ <my key:my_value> ]","_my_key":"my_value"}
  • json format log entry to json {"Message":"My log message","Level":6,"Context":{"my_key":"my_value"}}

Middlewares

The middleware are handler decorator/wrapper. It will allow you to do some process around child handler

Available middleware:

  • caller it will add caller file/line to context <file:/my/example/path/file> <line:31>
  • context it permit to have a default context value useful when you want to set global context value
  • error it will print provided handler error (can be configure to silent it)
  • filter it will permit to filter log entry level filter are available or you can use your own callback filter
  • placeholder it will replace log message placeholder with contextual value
  • recover it will convert handler panic to error
  • timestamp it will add timestamp to log context

Writers

Writers are use by handler to write/send log to appropriate destination

Available writer:

  • compress it will compress log to gzip/zlib
  • gelf_chunked it will chunked log entry into gelf chunk
  • rotate it will write in io.Writer and rotate writer on demand
  • time_rotate it's a rotate writer that rotate with time.Ticker
Todo
  • benchmark

  • Implement all the handler

    • SSE http endpoint
    • websocket server
    • socket server
    • https://craig.is/writing/chrome-logger
    • fingercross
    • grpc / protobuf
    • curl
    • Mail
    • Slack
    • hipchat
    • amqp
    • redis
    • elasticsearch
    • newrelic
    • browser console
    • couchdb
    • cube
    • ifttt
    • InsightOps
    • mandrill
    • pushover
    • raven
    • rollbar
    • sampling
    • LogEntries
    • ???
  • Implement all the formatter

    • html
    • proto
    • slack
    • flowdoc
    • fluentd
    • logstash
    • mongodb
    • wildfire
Idea
  • log server with log routing

Documentation

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func EntryToString

func EntryToString(entry Entry, byteBuffer *bytebufferpool.ByteBuffer)

EntryToString will write entry as string in byteBuffer

func ErrorHandler

func ErrorHandler(error error, entry Entry)

ErrorHandler will print error and entry when logging error occurred

func InjectInContext

func InjectInContext(ctx context.Context, l LoggerInterface) context.Context

InjectInContext will inject a logger into the go-context

Types

type Context

type Context map[string]Field

Context contain all contextual log data we advise you to choose your data wisely You should keep a reasonable quantity of data

func Ctx

func Ctx(name string, value interface{}) *Context

Ctx will create a new context with given value

func NewContext

func NewContext(fields ...Field) *Context

NewContext will create a new context with optional fields

func (*Context) Add

func (c *Context) Add(name string, value interface{}) *Context

Add will guess and add value to the context

func (*Context) Binary

func (c *Context) Binary(name string, value []byte) *Context

Binary will add binary field to context

func (*Context) ByteString

func (c *Context) ByteString(name string, value []byte) *Context

ByteString will add byteString field to context

func (*Context) Get

func (c *Context) Get(name string, defaultField *Field) Field

Get will return field with given name or the default value

func (*Context) GoString

func (c *Context) GoString() string

GoString was called by fmt.Printf("%#v", context) fmt GoStringer interface

func (*Context) Has

func (c *Context) Has(name string) bool

Has will checks if the current context has a field name

func (*Context) Merge

func (c *Context) Merge(context Context) *Context

Merge and overwrite context data with the given one

func (*Context) SetField

func (c *Context) SetField(fields ...Field) *Context

SetField will add a new context field

func (*Context) Skip

func (c *Context) Skip(name string, value string) *Context

Skip will add skip field to context

func (*Context) Slice

func (c *Context) Slice() *Fields

Slice will return fields as *Fields

func (*Context) String

func (c *Context) String() string

String will return fields as string

func (*Context) StringTo added in v0.5.10

func (c *Context) StringTo(byteBuffer *bytebufferpool.ByteBuffer) *Context

type Entry

type Entry struct {
	Message string
	Level   Level
	Context *Context
}

Entry represents a log in its entirety it is composed of a level, a message and a context

func (*Entry) String

func (e *Entry) String() string

String will return Entry as string

type Field

type Field struct {
	Name  string
	Type  FieldType
	Value interface{}
}

Field represents a contextual information this data was carry by Context struct

func Any

func Any(name string, value interface{}) Field

Any will guess and create Field for given value

func Binary

func Binary(name string, value []byte) Field

Binary will create Binary Field

func Bool

func Bool(name string, value bool) Field

Bool will create Bool Field

func ByteString

func ByteString(name string, value []byte) Field

ByteString will create ByteString Field

func Complex128

func Complex128(name string, value complex128) Field

Complex128 will create Complex128 Field

func Complex64

func Complex64(name string, value complex64) Field

Complex64 will create Complex64 Field

func Duration

func Duration(name string, value time.Duration) Field

Duration will create Duration Field

func Error

func Error(name string, value error) Field

Error will create Error Field

func Float32

func Float32(name string, value float32) Field

Float32 will create Float32 Field

func Float64

func Float64(name string, value float64) Field

Float64 will create Float64 Field

func Int16

func Int16(name string, value int16) Field

Int16 will create Int16 Field

func Int32

func Int32(name string, value int32) Field

Int32 will create Int32 Field

func Int64

func Int64(name string, value int64) Field

Int64 will create Int64 Field

func Int8

func Int8(name string, value int8) Field

Int8 will create Int8 Field

func Reflect

func Reflect(name string, value interface{}) Field

Reflect will create Reflect Field

func Skip

func Skip(name string, value string) Field

Skip will create Skip Field

func String

func String(name string, value string) Field

String will create String Field

func Stringer

func Stringer(name string, value fmt.Stringer) Field

Stringer will create Stringer Field

func Time

func Time(name string, value time.Time) Field

Time will create Time Field

func Uint16

func Uint16(name string, value uint16) Field

Uint16 will create Uint16 Field

func Uint32

func Uint32(name string, value uint32) Field

Uint32 will create Uint32 Field

func Uint64

func Uint64(name string, value uint64) Field

Uint64 will create Uint64 Field

func Uint8

func Uint8(name string, value uint8) Field

Uint8 will create Uint8 Field

func Uintptr

func Uintptr(name string, value uintptr) Field

Uintptr will create Uintptr Field

func (*Field) GoString

func (f *Field) GoString() string

GoString was called by fmt.Printf("%#v", Fields) fmt GoStringer interface

func (*Field) MarshalJSON

func (f *Field) MarshalJSON() ([]byte, error)

MarshalJSON was called by json.Marshal(field) json Marshaller interface

func (*Field) String

func (f *Field) String() string

String will return Field as string

type FieldType

type FieldType uint8

FieldType represents the type of a logger context field

const (
	// UnknownType is the default field type.
	UnknownType FieldType = iota
	// SkipType indicates that the field is a no-op.
	SkipType
	BoolType
	Int8Type
	Int16Type
	Int32Type
	Int64Type
	Uint8Type
	Uint16Type
	Uint32Type
	Uint64Type
	UintptrType
	Float32Type
	Float64Type
	Complex64Type
	Complex128Type
	StringType
	BinaryType
	ByteStringType
	ErrorType
	TimeType
	DurationType
	StringerType
	// ReflectType indicates that the field carries an interface{}, which should be serialized using reflection.
	ReflectType
)

list of available field types

type Fields

type Fields []Field

Fields was slice format of Fields

func NewFields

func NewFields(name string, value interface{}) *Fields

NewFields will create a Fields collection with initial value

func (*Fields) Add

func (f *Fields) Add(name string, value interface{}) *Fields

Add will guess and add value to the fields

func (*Fields) Binary

func (f *Fields) Binary(name string, value []byte) *Fields

Binary will add binary field to fields

func (*Fields) ByteString

func (f *Fields) ByteString(name string, value []byte) *Fields

ByteString will add byteString field to fields

func (*Fields) GoString

func (f *Fields) GoString() string

GoString was called by fmt.Printf("%#v", Fields) fmt GoStringer interface

func (*Fields) SetField

func (f *Fields) SetField(fields ...Field) *Fields

SetField will add a new fields field

func (*Fields) Skip

func (f *Fields) Skip(name string, value string) *Fields

Skip will add skip field to fields

func (*Fields) String

func (f *Fields) String() string

String will return Fields as string

func (*Fields) StringTo added in v0.5.10

func (f *Fields) StringTo(byteBuffer *bytebufferpool.ByteBuffer)

type FormatterInterface

type FormatterInterface interface {
	Format(entry Entry) string
}

FormatterInterface will convert Entry into string ex: format a log entry to string/json/... format

type HandlerInterface

type HandlerInterface func(Entry) error

HandlerInterface allows you to process a Entry See basic handler implementations in the handler package.

var NopHandler HandlerInterface = func(entry Entry) error {
	return nil
}

NopHandler is a no operating handler that do nothing with received Entry

func DecorateHandler

func DecorateHandler(handler HandlerInterface, middlewares ...MiddlewareInterface) HandlerInterface

DecorateHandler will return the handler after decorate with middlewares

type Level

type Level int8

Level represent log Entry levelString

const (
	EmergencyLevel Level = iota
	AlertLevel
	CriticalLevel
	ErrorLevel
	WarningLevel
	NoticeLevel
	InfoLevel
	DebugLevel
)

Log Severity level

https://github.com/freebsd/freebsd/blob/master/sys/sys/syslog.h#L51 From /usr/include/sys/syslog.h. These are the same on Linux, BSD, and OS X.

func (Level) String

func (l Level) String() string

String will return Level as string

func (Level) StringTo added in v0.5.10

func (l Level) StringTo(byteBuffer *bytebufferpool.ByteBuffer)

StringTo will return Level as string

type LevelString

type LevelString string

LevelString represent log Entry level as string

func (LevelString) Level

func (l LevelString) Level() Level

Level will return log Level for string or DebugLevel if unknown value

type LogInterface

type LogInterface interface {
	Log(message string, level Level, field ...Field)
}

LogInterface define simplest logger contract See LoggerInterface for a more convenient one

type Logger

type Logger struct {
	ErrorHandler func(error, Entry)
	// contains filtered or unexported fields
}

Logger is basic implementation of WrappableLoggerInterface

Example (CallerHandler)
package main

import (
	"bytes"
	"fmt"
	"strings"

	"github.com/gol4ng/logger"
	"github.com/gol4ng/logger/formatter"
	"github.com/gol4ng/logger/handler"
	"github.com/gol4ng/logger/middleware"
)

func main() {
	output := &Output{}
	myLogger := logger.NewLogger(
		middleware.Caller(3)(
			handler.Stream(output, formatter.NewLine("lvl: %[2]s | msg: %[1]s | ctx: %[3]v")),
		),
	)

	myLogger.Debug("Log example")
	myLogger.Info("Log example")
	myLogger.Notice("Log example")
	myLogger.Warning("Log example")
	myLogger.Error("Log example")
	myLogger.Critical("Log example")
	myLogger.Alert("Log example")
	myLogger.Emergency("Log example")

	output.Contains([]string{
		"lvl: debug | msg: Log example | ctx:", "<file:/", "<line:",
		"lvl: info | msg: Log example | ctx:", "<file:/", "<line:",
		"lvl: notice | msg: Log example | ctx:", "<file:/", "<line:",
		"lvl: warning | msg: Log example | ctx:", "<file:/", "<line:",
		"lvl: error | msg: Log example | ctx:", "<file:/", "<line:",
		"lvl: critical | msg: Log example | ctx:", "<file:/", "<line:",
		"lvl: alert | msg: Log example | ctx:", "<file:/", "<line:",
		"lvl: emergency | msg: Log example | ctx:", "<file:/", "<line:",
	})

}

type Output struct {
	bytes.Buffer
}

func (o *Output) Contains(str []string) {
	b := o.String()
	for _, s := range str {
		if strings.Contains(b, s) != true {
			fmt.Printf("buffer %s must contain %s\n", b, s)
		}
	}
}
Output:

Example (GroupHandler)
package main

import (
	"bytes"
	"fmt"
	"strings"

	"github.com/gol4ng/logger"
	"github.com/gol4ng/logger/formatter"
	"github.com/gol4ng/logger/handler"
)

func main() {
	output := &Output{}
	output2 := &Output{}
	myLogger := logger.NewLogger(
		handler.Group(
			handler.Stream(output, formatter.NewJSONEncoder()),
			handler.Stream(output2, formatter.NewDefaultFormatter(formatter.WithContext(true))),
		),
	)

	myLogger.Debug("Log example", logger.Any("my_key", "my_value"))
	myLogger.Info("Log example", logger.Any("my_key", "my_value"))
	myLogger.Notice("Log example", logger.Any("my_key", "my_value"))
	myLogger.Warning("Log example", logger.Any("my_key", "my_value"))
	myLogger.Error("Log example", logger.Any("my_key", "my_value"))
	myLogger.Critical("Log example", logger.Any("my_key", "my_value"))
	myLogger.Alert("Log example", logger.Any("my_key", "my_value"))
	myLogger.Emergency("Log example", logger.Any("my_key", "my_value"))

	output.Contains([]string{
		`{"Message":"Log example","Level":7,"Context":{"my_key":"my_value"}}`,
		`{"Message":"Log example","Level":6,"Context":{"my_key":"my_value"}}`,
		`{"Message":"Log example","Level":5,"Context":{"my_key":"my_value"}}`,
		`{"Message":"Log example","Level":4,"Context":{"my_key":"my_value"}}`,
		`{"Message":"Log example","Level":3,"Context":{"my_key":"my_value"}}`,
		`{"Message":"Log example","Level":2,"Context":{"my_key":"my_value"}}`,
		`{"Message":"Log example","Level":1,"Context":{"my_key":"my_value"}}`,
		`{"Message":"Log example","Level":0,"Context":{"my_key":"my_value"}}`,
	})

	output2.Contains([]string{
		`<debug> Log example {"my_key":"my_value"}`,
		`<info> Log example {"my_key":"my_value"}`,
		`<notice> Log example {"my_key":"my_value"}`,
		`<warning> Log example {"my_key":"my_value"}`,
		`<error> Log example {"my_key":"my_value"}`,
		`<critical> Log example {"my_key":"my_value"}`,
		`<alert> Log example {"my_key":"my_value"}`,
		`<emergency> Log example {"my_key":"my_value"}`,
	})

}

type Output struct {
	bytes.Buffer
}

func (o *Output) Contains(str []string) {
	b := o.String()
	for _, s := range str {
		if strings.Contains(b, s) != true {
			fmt.Printf("buffer %s must contain %s\n", b, s)
		}
	}
}
Output:

Example (JsonFormatter)
package main

import (
	"bytes"
	"fmt"
	"strings"

	"github.com/gol4ng/logger"
	"github.com/gol4ng/logger/formatter"
	"github.com/gol4ng/logger/handler"
)

func main() {
	output := &Output{}
	myLogger := logger.NewLogger(
		handler.Stream(output, formatter.NewJSONEncoder()),
	)

	myLogger.Debug("Log example", logger.Any("my_key", "my_value"))
	myLogger.Info("Log example", logger.Any("my_key", "my_value"))
	myLogger.Notice("Log example", logger.Any("my_key", "my_value"))
	myLogger.Warning("Log example", logger.Any("my_key", "my_value"))
	myLogger.Error("Log example", logger.Any("my_key", "my_value"))
	myLogger.Critical("Log example", logger.Any("my_key", "my_value"))
	myLogger.Alert("Log example", logger.Any("my_key", "my_value"))
	myLogger.Emergency("Log example", logger.Any("my_key", "my_value"))

	output.Contains([]string{
		`{"Message":"Log example","Level":7,"Context":{"my_key":"my_value"}}`,
		`{"Message":"Log example","Level":6,"Context":{"my_key":"my_value"}}`,
		`{"Message":"Log example","Level":5,"Context":{"my_key":"my_value"}}`,
		`{"Message":"Log example","Level":4,"Context":{"my_key":"my_value"}}`,
		`{"Message":"Log example","Level":3,"Context":{"my_key":"my_value"}}`,
		`{"Message":"Log example","Level":2,"Context":{"my_key":"my_value"}}`,
		`{"Message":"Log example","Level":1,"Context":{"my_key":"my_value"}}`,
		`{"Message":"Log example","Level":0,"Context":{"my_key":"my_value"}}`,
	})

}

type Output struct {
	bytes.Buffer
}

func (o *Output) Contains(str []string) {
	b := o.String()
	for _, s := range str {
		if strings.Contains(b, s) != true {
			fmt.Printf("buffer %s must contain %s\n", b, s)
		}
	}
}
Output:

Example (LineFormatter)
package main

import (
	"bytes"
	"fmt"
	"strings"

	"github.com/gol4ng/logger"
	"github.com/gol4ng/logger/formatter"
	"github.com/gol4ng/logger/handler"
)

func main() {
	output := &Output{}
	myLogger := logger.NewLogger(
		handler.Stream(output, formatter.NewLine("lvl: %[2]s | msg: %[1]s | ctx: %[3]v")),
	)

	myLogger.Debug("Log example", logger.Any("my_key", "my_value"))
	myLogger.Info("Log example", logger.Any("my_key", "my_value"))
	myLogger.Notice("Log example", logger.Any("my_key", "my_value"))
	myLogger.Warning("Log example", logger.Any("my_key", "my_value"))
	myLogger.Error("Log example", logger.Any("my_key", "my_value"))
	myLogger.Critical("Log example", logger.Any("my_key", "my_value"))
	myLogger.Alert("Log example", logger.Any("my_key", "my_value"))
	myLogger.Emergency("Log example", logger.Any("my_key", "my_value"))

	output.Contains([]string{
		"lvl: debug | msg: Log example | ctx: <my_key:my_value>",
		"lvl: info | msg: Log example | ctx: <my_key:my_value>",
		"lvl: notice | msg: Log example | ctx: <my_key:my_value>",
		"lvl: warning | msg: Log example | ctx: <my_key:my_value>",
		"lvl: error | msg: Log example | ctx: <my_key:my_value>",
		"lvl: critical | msg: Log example | ctx: <my_key:my_value>",
		"lvl: alert | msg: Log example | ctx: <my_key:my_value>",
		"lvl: emergency | msg: Log example | ctx: <my_key:my_value>",
	})

}

type Output struct {
	bytes.Buffer
}

func (o *Output) Contains(str []string) {
	b := o.String()
	for _, s := range str {
		if strings.Contains(b, s) != true {
			fmt.Printf("buffer %s must contain %s\n", b, s)
		}
	}
}
Output:

Example (LogRotateHandler)
package main

import (
	"os"
	"time"

	"github.com/gol4ng/logger"
	"github.com/gol4ng/logger/formatter"
	"github.com/gol4ng/logger/handler"
)

func main() {
	lineFormatter := formatter.NewLine("lvl: %[2]s | msg: %[1]s | ctx: %[3]v")

	rotateLogHandler, _ := handler.LogRotateFileStream("test", os.TempDir()+"/%s.log", time.Stamp, lineFormatter, 1*time.Second)
	myLogger := logger.NewLogger(rotateLogHandler)

	myLogger.Debug("Log example", logger.Any("ctx_key", "ctx_value"))
	myLogger.Info("Log example", logger.Any("ctx_key", "ctx_value"))
	myLogger.Warning("Log example", logger.Any("ctx_key", "ctx_value"))
	time.Sleep(1 * time.Second)
	myLogger.Error("Log example", logger.Any("ctx_key", "ctx_value"))
	myLogger.Alert("Log example", logger.Any("ctx_key", "ctx_value"))
	myLogger.Critical("Log example", logger.Any("ctx_key", "ctx_value"))

}
Output:

Example (MinLevelFilterHandler)
package main

import (
	"bytes"
	"fmt"
	"strings"

	"github.com/gol4ng/logger"
	"github.com/gol4ng/logger/formatter"
	"github.com/gol4ng/logger/handler"
	"github.com/gol4ng/logger/middleware"
)

func main() {
	output := &Output{}
	myLogger := logger.NewLogger(
		middleware.MinLevelFilter(logger.WarningLevel)(
			handler.Stream(output, formatter.NewDefaultFormatter(formatter.WithContext(true))),
		),
	)

	myLogger.Debug("Log example", logger.Any("my_key", "my_value"))
	myLogger.Info("Log example", logger.Any("my_key", "my_value"))
	myLogger.Notice("Log example", logger.Any("my_key", "my_value"))
	myLogger.Warning("Log example", logger.Any("my_key", "my_value"))
	myLogger.Error("Log example", logger.Any("my_key", "my_value"))
	myLogger.Critical("Log example", logger.Any("my_key", "my_value"))
	myLogger.Alert("Log example", logger.Any("my_key", "my_value"))
	myLogger.Emergency("Log example", logger.Any("my_key", "my_value"))

	output.Contains([]string{
		`<warning> Log example {"my_key":"my_value"}`,
		`<error> Log example {"my_key":"my_value"}`,
		`<critical> Log example {"my_key":"my_value"}`,
		`<alert> Log example {"my_key":"my_value"}`,
		`<emergency> Log example {"my_key":"my_value"}`,
	})

}

type Output struct {
	bytes.Buffer
}

func (o *Output) Contains(str []string) {
	b := o.String()
	for _, s := range str {
		if strings.Contains(b, s) != true {
			fmt.Printf("buffer %s must contain %s\n", b, s)
		}
	}
}
Output:

Example (PlaceholderMiddleware)
package main

import (
	"bytes"
	"fmt"
	"strings"
	"time"

	"github.com/gol4ng/logger"
	"github.com/gol4ng/logger/formatter"
	"github.com/gol4ng/logger/handler"
	"github.com/gol4ng/logger/middleware"
)

func main() {
	output := &Output{}
	myLogger := logger.NewLogger(
		handler.Stream(output, formatter.NewLine("%[2]s %[1]s%.[3]s")),
	)
	myLogger.Wrap(middleware.Placeholder())

	myLogger.Debug("Log %ctx_key% example", logger.Any("ctx_key", false))
	myLogger.Info("Log %ctx_key% example", logger.Any("ctx_key", 1234))
	myLogger.Warning("Log %ctx_key% example", logger.Any("ctx_key", 5*time.Second))
	myLogger.Error("Log %ctx_key% example", logger.Any("ctx_key", "ctx_value"))
	myLogger.Alert("Log %ctx_key% example", logger.Any("ctx_key", struct{ attr string }{attr: "attrValue"}))
	myLogger.Critical("Log %ctx_key% example another value %ctx_key2%", logger.Any("ctx_key", false), logger.Any("ctx_key2", 1234))

	output.Contains([]string{
		`debug Log false example`,
		`info Log 1234 example`,
		`warning Log 5s example`,
		`error Log ctx_value example`,
		`alert Log {attrValue} example`,
		`critical Log false example another value 1234`,
	})

}

type Output struct {
	bytes.Buffer
}

func (o *Output) Contains(str []string) {
	b := o.String()
	for _, s := range str {
		if strings.Contains(b, s) != true {
			fmt.Printf("buffer %s must contain %s\n", b, s)
		}
	}
}
Output:

Example (SyslogHandler)

You can run the command below to show syslog messages syslog -F '$Time $Host $(Sender)[$(PID)] <$((Level)(str))>: $Message' Apr 26 12:22:06 hades my_go_logger[69302] <Notice>: <notice> Log example2 {"ctx_key":"ctx_value"} Apr 26 12:22:06 hades my_go_logger[69302] <Warning>: <warning> Log example3 {"ctx_key":"ctx_value"} Apr 26 12:22:06 hades my_go_logger[69302] <Error>: <error> Log example4 {"ctx_key":"ctx_value"} Apr 26 12:22:06 hades my_go_logger[69302] <Critical>: <critical> Log example5 {"ctx_key":"ctx_value"} Apr 26 12:22:06 hades my_go_logger[69302] <Alert>: <alert> Log example6 {"ctx_key":"ctx_value"} Apr 26 12:22:06 hades my_go_logger[69302] <Emergency>: <emergency> Log example7 {"ctx_key":"ctx_value"}

package main

import (
	"log/syslog"

	"github.com/gol4ng/logger"
	"github.com/gol4ng/logger/formatter"
	"github.com/gol4ng/logger/handler"
)

func main() {
	syslogHandler, _ := handler.Syslog(
		formatter.NewDefaultFormatter(formatter.WithContext(true)),
		"",
		"",
		syslog.LOG_DEBUG,
		"my_go_logger")
	myLogger := logger.NewLogger(syslogHandler)

	myLogger.Debug("Log example", logger.Any("ctx_key", "ctx_value"))
	myLogger.Info("Log example1", logger.Any("ctx_key", "ctx_value"))
	myLogger.Notice("Log example2", logger.Any("ctx_key", "ctx_value"))
	myLogger.Warning("Log example3", logger.Any("ctx_key", "ctx_value"))
	myLogger.Error("Log example4", logger.Any("ctx_key", "ctx_value"))
	myLogger.Critical("Log example5", logger.Any("ctx_key", "ctx_value"))
	myLogger.Alert("Log example6", logger.Any("ctx_key", "ctx_value"))
	myLogger.Emergency("Log example7", logger.Any("ctx_key", "ctx_value"))

}
Output:

Example (TimeRotateHandler)
package main

import (
	"os"
	"time"

	"github.com/gol4ng/logger"
	"github.com/gol4ng/logger/formatter"
	"github.com/gol4ng/logger/handler"
)

func main() {
	lineFormatter := formatter.NewLine("lvl: %[2]s | msg: %[1]s | ctx: %[3]v")

	rotateLogHandler, _ := handler.TimeRotateFileStream(os.TempDir()+"/%s.log", time.Stamp, lineFormatter, 1*time.Second)
	myLogger := logger.NewLogger(rotateLogHandler)

	myLogger.Debug("Log example", logger.Any("ctx_key", "ctx_value"))
	myLogger.Info("Log example", logger.Any("ctx_key", "ctx_value"))
	myLogger.Warning("Log example", logger.Any("ctx_key", "ctx_value"))
	time.Sleep(1 * time.Second)
	myLogger.Error("Log example", logger.Any("ctx_key", "ctx_value"))
	myLogger.Alert("Log example", logger.Any("ctx_key", "ctx_value"))
	myLogger.Critical("Log example", logger.Any("ctx_key", "ctx_value"))

}
Output:

Example (WrapHandler)
package main

import (
	"bytes"
	"fmt"
	"strings"

	"github.com/gol4ng/logger"
	"github.com/gol4ng/logger/formatter"
	"github.com/gol4ng/logger/handler"
	"github.com/gol4ng/logger/middleware"
)

func main() {
	output := &Output{}
	myLogger := logger.NewLogger(
		handler.Stream(output, formatter.NewDefaultFormatter(formatter.WithContext(true))),
	)
	myLogger.Wrap(middleware.MinLevelFilter(logger.WarningLevel))

	myLogger.Debug("Log example", logger.Any("my_key", "my_value"))
	myLogger.Info("Log example", logger.Any("my_key", "my_value"))
	myLogger.Notice("Log example", logger.Any("my_key", "my_value"))
	myLogger.Warning("Log example", logger.Any("my_key", "my_value"))
	myLogger.Error("Log example", logger.Any("my_key", "my_value"))
	myLogger.Critical("Log example", logger.Any("my_key", "my_value"))
	myLogger.Alert("Log example", logger.Any("my_key", "my_value"))
	myLogger.Emergency("Log example", logger.Any("my_key", "my_value"))
	output.Contains([]string{
		`<warning> Log example {"my_key":"my_value"}`,
		`<error> Log example {"my_key":"my_value"}`,
		`<critical> Log example {"my_key":"my_value"}`,
		`<alert> Log example {"my_key":"my_value"}`,
		`<emergency> Log example {"my_key":"my_value"}`,
	})

}

type Output struct {
	bytes.Buffer
}

func (o *Output) Contains(str []string) {
	b := o.String()
	for _, s := range str {
		if strings.Contains(b, s) != true {
			fmt.Printf("buffer %s must contain %s\n", b, s)
		}
	}
}
Output:

func NewLogger

func NewLogger(handler HandlerInterface) *Logger

NewLogger will return a new logger

func NewNopLogger

func NewNopLogger() *Logger

NewNopLogger will create a new no operating logger that log nowhere

func (*Logger) Alert

func (l *Logger) Alert(message string, fields ...Field)

Alert will log a alert message

func (*Logger) Critical

func (l *Logger) Critical(message string, fields ...Field)

Critical will log a critical message

func (*Logger) Debug

func (l *Logger) Debug(message string, fields ...Field)

Debug will log a debug message

func (*Logger) Emergency

func (l *Logger) Emergency(message string, fields ...Field)

Emergency will log a emergency message

func (*Logger) Error

func (l *Logger) Error(message string, fields ...Field)

Error will log a message

func (*Logger) Info

func (l *Logger) Info(message string, fields ...Field)

Info will log a info message

func (*Logger) Log

func (l *Logger) Log(message string, level Level, fields ...Field)

Log will log a message with a given level

func (*Logger) Notice

func (l *Logger) Notice(message string, fields ...Field)

Notice will log a notice message

func (*Logger) Warning

func (l *Logger) Warning(message string, fields ...Field)

Warning will log a warning message

func (*Logger) Wrap

func (l *Logger) Wrap(middlewares ...MiddlewareInterface) LoggerInterface

Wrap will return the logger after decorate his handler with given middleware

func (*Logger) WrapNew

func (l *Logger) WrapNew(middlewares ...MiddlewareInterface) LoggerInterface

WrapNew will return a new logger after wrap his handler with given middleware

type LoggerInterface

type LoggerInterface interface {
	LogInterface
	Debug(message string, field ...Field)
	Info(message string, field ...Field)
	Notice(message string, field ...Field)
	Warning(message string, field ...Field)
	Error(message string, field ...Field)
	Critical(message string, field ...Field)
	Alert(message string, field ...Field)
	Emergency(message string, field ...Field)
}

LoggerInterface define a convenient logger contract

func FromContext

func FromContext(ctx context.Context, defaultLogger LoggerInterface) LoggerInterface

FromContext will retrieve a logger from the go-context or return defaultLogger

type MiddlewareInterface

type MiddlewareInterface func(HandlerInterface) HandlerInterface

MiddlewareInterface is a function to decorate handler See middleware implementations in the middleware package.

type Middlewares

type Middlewares []MiddlewareInterface

Middlewares was a collection of middleware the slice order matter when middleware are compose with DecorateHandler

func MiddlewareStack

func MiddlewareStack(middlewares ...MiddlewareInterface) Middlewares

MiddlewareStack helper return Middlewares slice from given middlewares

func (Middlewares) Decorate

func (m Middlewares) Decorate(handler HandlerInterface) HandlerInterface

Decorate will return the handler after decorate with middlewares

type NopFormatter

type NopFormatter struct{}

NopFormatter is a no operating formatter

func NewNopFormatter

func NewNopFormatter() *NopFormatter

NewNopFormatter will create a NopFormatter

func (*NopFormatter) Format

func (n *NopFormatter) Format(_ Entry) string

Format will return empty string

type WrappableLoggerInterface

type WrappableLoggerInterface interface {
	LoggerInterface
	// Implementation should return the same logger after wrapping it
	Wrap(middlewares ...MiddlewareInterface) LoggerInterface
	// Implementation should return a new decorated logger
	WrapNew(middlewares ...MiddlewareInterface) LoggerInterface
}

WrappableLoggerInterface define a contract to wrap or decorate the logger with given middleware

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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