log

package
v0.1.1 Latest Latest
Warning

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

Go to latest
Published: Aug 18, 2023 License: MIT Imports: 9 Imported by: 20

Documentation

Overview

Package log provides loglevel aware output methods.

Loglevel are predefined as Ltrace, Ldebug, Linfo, Lwarn, Lerror, and Lfatal. The default loglevel is Linfo. To create a logger named mylogger under the default stream:

var lg = log.DefaultStream.NewLogger("mylogger", log.Linfo)

A stream is a handle that controls the output destination and output format. The default output destination is stdout.

"stdout" : output to OS.Stdout.

Other supported output destination:

"file:filepath/filename" : output to file in append mode.

More output destinations to be added, see RegOutputterFactory() and fileFactory for an example.

Loggers can be created under a named stream if more output destinations are needed. In "main" package:

mystream := log.NewStream("mystream")

In subpackages:

var lg = log.GetStream("mystream").NewLogger("mylogger", log.Lwarn)

It is the main package's responsibility to set or change the global output destination. To change the output destination to file:

mystream.SetOutput("file:filepath/filename")

More than one loggers can be created on demand in one package, usually along with the package level logger itself, i.e. each "worker" can have its own logger instance, thus its loglevel can be changed separately. It is highly recommended that dynamic loggers are named in the URL like form "package/module/xxxx", eg. You have a package level logger lgsrv for awesomesrvice package:

lgsrv := log.DefaultStream.NewLogger("awesomesrvice", log.Lwarn)

Now inside awesomesrvice, you want each worker has its own logger instance so that later loglevel can be changed respectively for each worker:

lgworker := log.DefaultStream.NewLogger("awesomesrvice/worker123", log.Lwarn)

When you want to set loglevel to one of these loggers to debug level:

log.DefaultStream.SetLoglevel("awesomesrvice/worker123", log.Ldebug)

To set all awesomesrvice loggers to debug level:

log.DefaultStream.SetLoglevel("awesomesrvice*", log.Ldebug)

Dynamically created logger should be closed if not use any more.

lgworker.Close()

When a new logger instance is getting created, it will use the loglevel that has been set the lastime calling stream.SetLoglevel() if the namePattern matches, or use the default loglevel if not.

Timestamp is in format "[2006/01/02 15:04:05.000000]" by default, set it to "" will disable timestamp to be printed. SetTimeFormat can change the timestamp format, refer to standard time package for the possible formats.

mystream := log.NewStream("mystream")
mystream.SetTimeFormat(time.RFC3339Nano)

Some APIs support wildcard matching to match logger name, and support multiple patterns separated by comma. The pattern uses simple * as the wildcard: eg.

"*" matches all
"*bar*" matches bar, foobar, or foobarabc
"foo*abc*" matches foobarabc, foobarabc123, or fooabc

The methods are concurrency safe under linux.

Index

Examples

Constants

This section is empty.

Variables

View Source
var DefaultStream = NewStream("default")

DefaultStream is the builtin output stream instance

Functions

func RegOutputterFactory

func RegOutputterFactory(keyword string, f OutputterFactory)

RegOutputterFactory registers an output destination type. No lock here, use it in init().

Types

type Flag

type Flag uint32

Flag controls output format

const (
	Ldefault  Flag = 0
	LUTC      Flag = 1 << 0 // use UTC rather than the local time zone
	Lfileline Flag = 1 << 1 // the file and line in the source code that prints the message
)

These flags define which text to prefix to each log entry generated by the Logger. Bits are or'ed together to control what's printed.

type Logger

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

Logger is the logger instance

func (*Logger) Close

func (lg *Logger) Close()

Close releases the logger

func (*Logger) Debugf

func (lg *Logger) Debugf(format string, args ...interface{})

Debugf writes the debug log, always adds a '\n' if no '\n' supplied by user

func (*Logger) Debugln

func (lg *Logger) Debugln(args ...interface{})

Debugln is like fmt.Println with loglevel debug

func (*Logger) Errorf

func (lg *Logger) Errorf(format string, args ...interface{})

Errorf writes the error log, always adds a '\n' if no '\n' supplied by user

func (*Logger) Errorln

func (lg *Logger) Errorln(args ...interface{})

Errorln is like fmt.Println with loglevel error

func (*Logger) Fatalf

func (lg *Logger) Fatalf(format string, args ...interface{})

Fatalf writes the log entry followed by a panic, always adds a '\n' if no '\n' supplied by user

func (*Logger) Fatalln

func (lg *Logger) Fatalln(args ...interface{})

Fatalln is like fmt.Println with loglevel fatal followed by a panic

func (*Logger) Infof

func (lg *Logger) Infof(format string, args ...interface{})

Infof writes the info log, always adds a '\n' if no '\n' supplied by user

func (*Logger) Infoln

func (lg *Logger) Infoln(args ...interface{})

Infoln is like fmt.Println with loglevel info

Example
lg := DefaultStream.NewLogger("demo", Linfo)
defer lg.Close()
// recreate the same name logger will panic
//lg = DefaultStream.NewLogger("demo")
DefaultStream.SetTimeFormat("")
lg.Infoln("no need to put a new line")
lg.Infoln("another line")
Output:

[demo][INFO] no need to put a new line
[demo][INFO] another line

func (*Logger) SetLoglevel

func (lg *Logger) SetLoglevel(level Loglevel)

SetLoglevel sets the log level of the logger instance.

func (*Logger) Tracef

func (lg *Logger) Tracef(format string, args ...interface{})

Tracef writes the trace log, always adds a '\n' if no '\n' supplied by user

func (*Logger) Traceln

func (lg *Logger) Traceln(args ...interface{})

Traceln is like fmt.Println with loglevel trace

func (*Logger) Warnf

func (lg *Logger) Warnf(format string, args ...interface{})

Warnf writes the warning log, always adds a '\n' if no '\n' supplied by user

func (*Logger) Warnln

func (lg *Logger) Warnln(args ...interface{})

Warnln is like fmt.Println with loglevel warning

type Loglevel

type Loglevel uint32

Loglevel is one of the predefined loglevels

const (
	Linvalid Loglevel = 0
	Ltrace   Loglevel = 1
	Ldebug   Loglevel = 2
	Linfo    Loglevel = 3
	Lwarn    Loglevel = 4
	Lerror   Loglevel = 5
	Lfatal   Loglevel = 6
)

All predefined loglevels

func StringToLoglevel

func StringToLoglevel(loglevelName string) Loglevel

StringToLoglevel returns the loglevel described by the given string. Return Linvalid if loglevelName is none of case insensitive "trace", "debug", "info", "warn", "error", "fatal".

func (Loglevel) String

func (level Loglevel) String() string

String returns the string description of the Loglevel. Return "invalid" if level is out of range.

type Outputter

type Outputter io.Writer

Outputter outputs log lines. The old Outputter will be closed if it implements io.Closer when closing the stream or changing the stream's output destination.

type OutputterFactory

type OutputterFactory interface {
	NewOutputter(description string) (Outputter, error)
}

OutputterFactory is an outputter type.

type Stream

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

Stream is a output stream handle, all loggers under a stream share one output destination and same log format, but can have separete loglevel.

func GetStream

func GetStream(name string) *Stream

GetStream returns the Stream handle if it has been created with the same input non empty "name", returns nil if not. Usually used for a subpackage other than main to get the named Stream handle.

func NewStream

func NewStream(name string) *Stream

NewStream creates a Stream instance. The Stream will be anonymous if input name is empty, therefore GetStream() can not find it.

func (*Stream) AllLoggerNames

func (s *Stream) AllLoggerNames() (names []string)

AllLoggerNames returns the logger names under the stream.

func (*Stream) Close

func (s *Stream) Close()

Close closes the stream.

func (*Stream) GetLogger

func (s *Stream) GetLogger(name string) *Logger

GetLogger returns logger instance that has been created or nil if not.

func (*Stream) NewLogger

func (s *Stream) NewLogger(name string, defaultLoglevel Loglevel) *Logger

NewLogger returns a logger instance. In a project where all logs go to the same destination, using builtin DefaultStream is enough. In case multiple destinations are needed, use "named" stream returned by NewStream(). stream is the stream that the logger instance belongs to. name is the identifier of the logger, which is assembled to each log entry. defaultLoglevel sets the default loglevel of the returned logger instance, unless the name matches preconfigured namePattern, in which case loglevel sets to preconfigured loglevel. See Stream.SetLoglevel(). Returns nil if stream is nil or name is empty.

Example
// in your main.go
stream := NewStream("mystream")
defer stream.Close()
stream.SetTimeFormat("")

// in your xxxpackage.go
lg := GetStream("mystream").NewLogger("myexample", Linfo)
defer lg.Close()
i := 200
lg.normalLevelPrintf("hello world %d", i)

// if you need to change loglevel in elsewhere.go
GetStream("mystream").SetLoglevel("*", Ltrace)
lg.normalLevelPrintf("hello world %d", i+1)
Output:

[myexample][INFO] hello world 200
[myexample][WARN] hello world 200
[myexample][ERROR] hello world 200
[myexample][TRACE] hello world 201
[myexample][DEBUG] hello world 201
[myexample][INFO] hello world 201
[myexample][WARN] hello world 201
[myexample][ERROR] hello world 201

func (*Stream) SetFlag

func (s *Stream) SetFlag(newFlag Flag)

SetFlag sets the flag to control output format.

func (*Stream) SetLoglevel

func (s *Stream) SetLoglevel(namePattern string, newLevel Loglevel)

SetLoglevel set the loglevel for every logger instance if its name matches the namePattern. namePattern is a simple wildcard pattern, i.e. *foo*bar*, and supports multiple patterns, i.e. "*foo,bar*,worker123", patterns are separated by a comma.

Example
stream := NewStream("examplePattern")
defer stream.Close()
stream.SetTimeFormat("")
lg := stream.NewLogger("service", Linfo)
defer lg.Close()
var wg sync.WaitGroup

type workerInfo struct {
	workerName string
	workerlg   *Logger
}

freeInstance := func(wi *workerInfo, id int) {
	wi.workerlg.Debugln("free instance:", id)
}

handleworker := func(wi *workerInfo) {
	wi.workerlg.Infoln("doing something awaresome...")
	freeInstance(wi, 3)
	wi.workerlg.Infoln("work done")
	wi.workerlg.Close()
	lg.Infof("worker: %s closed", wi.workerName)
	wg.Done()
}

onworkerDetect := func(workerName string) {
	lg.Infof("creating a new routine to handle %s", workerName)
	wi := &workerInfo{workerName: workerName, workerlg: stream.NewLogger(fmt.Sprintf("service/%s", workerName), Linfo)}
	lg.Infoln("handling worker info...")
	go handleworker(wi)
}

wg.Add(3)
//with pattern "service/worker123*", worker123456 and worker123999 match and are set to Ldebug level
stream.SetLoglevel("service/worker123*", Ldebug)
onworkerDetect("worker123456")
onworkerDetect("worker123999")
onworkerDetect("worker555666")

wg.Wait()
Output:

[service][INFO] creating a new routine to handle worker123456
[service][INFO] handling worker info...
[service][INFO] creating a new routine to handle worker123999
[service][INFO] handling worker info...
[service][INFO] creating a new routine to handle worker555666
[service][INFO] handling worker info...
[service/worker555666][INFO] doing something awaresome...
[service/worker555666][INFO] work done
[service][INFO] worker: worker555666 closed
[service/worker123999][INFO] doing something awaresome...
[service/worker123999][DEBUG] free instance: 3
[service/worker123999][INFO] work done
[service][INFO] worker: worker123999 closed
[service/worker123456][INFO] doing something awaresome...
[service/worker123456][DEBUG] free instance: 3
[service/worker123456][INFO] work done
[service][INFO] worker: worker123456 closed

func (*Stream) SetOutput

func (s *Stream) SetOutput(newOutputDest string) error

SetOutput sets the output destination to the new one, and close the old one. newOutputDest is in the form: "keyword:description". See supported output destination keywords.

Example
mystream := NewStream("mystream")
defer mystream.Close()
//set log output to file, args with "file:<file path>"
mystream.SetOutput("file:test/test.log")
mystream.SetTimeFormat(time.RFC3339Nano)
Output:

func (*Stream) SetOutputter

func (s *Stream) SetOutputter(newOutputter io.Writer)

SetOutputter sets the outputter for this stream.

func (*Stream) SetTimeFormat

func (s *Stream) SetTimeFormat(newFormat string)

SetTimeFormat can change the timestamp format, refer to standard time package for the possible formats. An empty string "" will disable timestamp to be printed.

Jump to

Keyboard shortcuts

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