goolog2

package module
v0.0.0-...-df1e514 Latest Latest
Warning

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

Go to latest
Published: Apr 8, 2020 License: MIT Imports: 11 Imported by: 0

README

GoOLog2

GoOLog2 is a Go implementation of a logging framework I have made and used for years in Aveco. The original framework has been written in C++.

Severity and verbosity

The main concept making the framework different to other ordinary logging frameworks is distinction between severity and verbosity:

  • severity describes type of a logged message and its severity to logging process.
  • verbosity describes importance of a logged message.

Obviously, both concepts are not independent. One can hardly imagine logging of a critical error at a low level of importance or logging of a debugging message at a high level of importance. I guess this dependency is the reason why most of the frameworks don't distinct them.

However, the concepts are actually different. The best example is the information severity (Info). This kind of messages covers entire spectrum of verbosity levels: from highly important messages like server starting and stopping to low important messages ment only for developers.

The framework distinguishes severity levels:

  • critical an error which cannot be recovered and which cause immediate ending of the process/service. The critical errors are usually last items in the log because they are logged just before the forced end caused by the error.
  • error severity marks errors of the process's state which can be recovered. An example can be loosing of connection to another service. The process can work somehow until the connection is re-established again. A common mistake is logging of errors returned to clients (if the logging process is a server) with the error severity. These conditions are not an errors of the server itself, hence they shouldn't be reported so.
  • warning severity reports some suspicious or potentially dangerous conditions. A using of a default for a missing configuration variable is an example.
  • info severity is the most usable one. All ordinary information about run of the process are reported at this severity (but at different verbosity levels).
  • debug severity is dedicated only for developers. Messages at this level shouldn't be seen in production environment.

The verbosity levels are defined by numbers. In theory, number of levels is not limited. Practically, we have used 6 levels:

  • 0 logging disabled,
  • 1,2 messages important to operations,
  • 3,4 messages important to developers,
  • 5 too often periodical messages which would exhaust disk space so they are disabled at standard circumstances.

Subsystem

Every message can be attached to a subsystem. The subsystem can be a library or a module or special kind of log. Loggers attached to a subsystem accept only messages of the subsystem. Loggers not attached to any subsystem accept any message.

Loggers

A logger is and abstraction of a logging target. Currently there are two loggers implemented: a file logger and a console logger. The original framework implemented two other loggers: logging into an Aveco's proprietary logging system and logging into standard Unix syslog. The last one is going to be implemented in the near future.

Usage

Usage of the framework is easy. There is one global logging dispatcher. At the beginning of the process, the dispatcher must be initialized:

import(
  olog2 "github.com/Staon/goolog2"
)

olog2.Init("my_process")

The Init function accepts a name called system. The name should be unique allowing distinction of process's messages in a combined log like syslog.

Next step of the initialization is creation of requested loggers:

olog2.AddFileLogger("file", "", olog2.MaskAll, 4, "file.log", false)
olog2.AddConsoleLoggerStderr("console", "", olog2.MaskStd, 2)

The first argument of the Add* functions is a logger name. The name should be unique among all loggers. In the future the name is going to be served as an address for dynamic changing of parameters of loggers.

The second argument is a subsystem. It can be empty if the logger isn't attached to a subsystem.

The third and fourth arguments specify severities (as a mask) and maximal verbosity of messages, which the logger accepts and logs.

Now the framework is ready to log:

olog2.Info1("server started")
olog2.Critical1("No one has programmed this piece of SW!! I cannot work!")
olog2.Info1("server stopped") 

There is a set of convenient functions following simple name scheme: SeverityVerbosity. The names can end with s or f - those function allow specification of a subsystem or the message can be formatted by standard printf format description:

olog2.Error2fs("special_module", "connection failed: %s", err)

Most of the time the convenient functions are good enough. However, sometimes there is a need to specify severity and verbosity dynamically. Then the functions LogMessage() and LogMessagef() can be useful.

At the end of the process the framework should be cleaned correctly flushing and closing opened files.

olog2.Destroy()

Warning: the initialization (Init and adding of loggers) phase and destrucion phase are not thread safe! Be careful that all threads have already stopped before you invoke the Destroy() function.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func AddApacheLogger

func AddApacheLogger(
	name string,
	subsystem Subsystem,
	severities SeverityMask,
	verbosity Verbosity,
	file string,
	sync bool,
)

Add a Apache logger

Parameters:

name: ID of the logger
subsystem: logging subsystem. Can be empty.
severities: mask of logging severities
verbosity: logging verbosity
file: path to the logging file
sync: flush all message immediately

func AddConsoleLogger

func AddConsoleLogger(
	name string,
	subsystem Subsystem,
	severities SeverityMask,
	verbosity Verbosity,
	output *os.File,
)

Add a console logger

Parameters:

name: ID of the logger
subsystem: logging subsystem. Can be empty.
severities: mask of logging severities
verbosity: logging verbosity
output: an output stream

func AddConsoleLoggerStderr

func AddConsoleLoggerStderr(
	name string,
	subsystem Subsystem,
	severities SeverityMask,
	verbosity Verbosity,
)

Add a console logger on the standard error

Parameters:

name: ID of the logger
subsystem: logging subsystem. Can be empty.
severities: mask of logging severities
verbosity: logging verbosity

func AddFileLogger

func AddFileLogger(
	name string,
	subsystem Subsystem,
	severities SeverityMask,
	verbosity Verbosity,
	file string,
	sync bool,
)

Add a simple file logger

Parameters:

name: ID of the logger
subsystem: logging subsystem. Can be empty.
severities: mask of logging severities
verbosity: logging verbosity
file: path to the logging file
sync: flush all message immediately

func AddLogRotator

func AddLogRotator(
	rotator LogRotator,
)

Add a rotator. The rotator is usually connected to one particular logger. See interface LogRotator. Methods NeedRotate + Rotate are runed in separate goroutine. The start time of boths method is determined by the method GetNextCheckTime.

Parameters:

rotator

func AddLogger

func AddLogger(
	name string,
	subsystem Subsystem,
	severities SeverityMask,
	verbosity Verbosity,
	logger Logger,
)

Add a logger

Parameters:

name: ID of the logger
subsystem: logging subsystem. Can be empty.
severities: mask of logging severities
verbosity: logging verbosity
logger: the logger. The ownership is taken - the logger
        is destroyed with the dispatcher.

func AddPatternApacheLogger

func AddPatternApacheLogger(
	name string,
	subsystem Subsystem,
	severities SeverityMask,
	verbosity Verbosity,
	pattern string,
	sync bool,
)

Add a Apache logger

Parameters:

name: ID of the logger
subsystem: logging subsystem. Can be empty.
severities: mask of logging severities
verbosity: logging verbosity
pattern: pattern of names the log files
sync: flush all message immediately

func AddPatternFileLogger

func AddPatternFileLogger(
	name string,
	subsystem Subsystem,
	severities SeverityMask,
	verbosity Verbosity,
	pattern string,
	sync bool,
)

Add a pattern file logger

Parameters:

name: ID of the logger
subsystem: logging subsystem. Can be empty.
severities: mask of logging severities
verbosity: logging verbosity
pattern: pattern of names the log files
sync: flush all message immediately

func AddRotatableApacheLogger

func AddRotatableApacheLogger(
	name string,
	subsystem Subsystem,
	severities SeverityMask,
	verbosity Verbosity,
	file string,
	sync bool,
	maxSize int64,
	checkInterval time.Duration,
)

Add a rotatable Apache logger (It rotate access.log => access.log.1 => access.log.2 => ...)

Parameters:

name: ID of the logger
subsystem: logging subsystem. Can be empty.
severities: mask of logging severities
verbosity: logging verbosity
file: path to the logging file
sync: flush all message immediately
maxSize:  Make log rotation if log size is bigger than maxSize.
checkInterval: time interval to check the log size; usually minutes or tens of minutes

func AddRotatableFileLogger

func AddRotatableFileLogger(
	name string,
	subsystem Subsystem,
	severities SeverityMask,
	verbosity Verbosity,
	file string,
	sync bool,
	maxSize int64,
	checkInterval time.Duration,
)

Add a rotatable file logger (It rotate file.log => file.log.1 => file.log.2 => ...)

Parameters:

name: ID of the logger
subsystem: logging subsystem. Can be empty.
severities: mask of logging severities
verbosity: logging verbosity
file: path to the logging file
sync: flush all message immediately
maxSize:  Make log rotation if log size is bigger than maxSize.
checkInterval: time interval to check the log size; usually minutes or tens of minutes

func AfterChangeMockedTime

func AfterChangeMockedTime(waitToRotators bool)

If mocked time source is used (see InitWithTimeSource), this method must be called after every time shift.

Parameters:

waitToRotators - true => Wait to finish corresponding rotators actions (scheduled for this time or earlier).

func Critical1

func Critical1(
	message string,
)

-- critical errors

func Critical1f

func Critical1f(
	format string,
	args ...interface{},
)

func Critical1fs

func Critical1fs(
	subsystem Subsystem,
	format string,
	args ...interface{},
)

func Critical1s

func Critical1s(
	subsystem Subsystem,
	message string,
)

func Debug3

func Debug3(
	message string,
)

func Debug3f

func Debug3f(
	format string,
	args ...interface{},
)

func Debug3fs

func Debug3fs(
	subsystem Subsystem,
	format string,
	args ...interface{},
)

func Debug3s

func Debug3s(
	subsystem Subsystem,
	message string,
)

func Debug4

func Debug4(
	message string,
)

func Debug4f

func Debug4f(
	format string,
	args ...interface{},
)

func Debug4fs

func Debug4fs(
	subsystem Subsystem,
	format string,
	args ...interface{},
)

func Debug4s

func Debug4s(
	subsystem Subsystem,
	message string,
)

func Debug5

func Debug5(
	message string,
)

func Debug5f

func Debug5f(
	format string,
	args ...interface{},
)

func Debug5fs

func Debug5fs(
	subsystem Subsystem,
	format string,
	args ...interface{},
)

func Debug5s

func Debug5s(
	subsystem Subsystem,
	message string,
)

func Destroy

func Destroy()

Destroy the global log

func DispatcherLogMessage

func DispatcherLogMessage(
	log LogDispatcher,
	subsystem Subsystem,
	severity Severity,
	verbosity Verbosity,
	message string,
)

Log a text message

func DispatcherLogMessagef

func DispatcherLogMessagef(
	log LogDispatcher,
	subsystem Subsystem,
	severity Severity,
	verbosity Verbosity,
	format string,
	args ...interface{},
)

Log a formatted text message

func DispatcherLogObject

func DispatcherLogObject(
	log LogDispatcher,
	subsystem Subsystem,
	severity Severity,
	verbosity Verbosity,
	object interface{},
)

Log a logging object

func Error1

func Error1(
	message string,
)

-- errors

func Error1f

func Error1f(
	format string,
	args ...interface{},
)

func Error1fs

func Error1fs(
	subsystem Subsystem,
	format string,
	args ...interface{},
)

func Error1s

func Error1s(
	subsystem Subsystem,
	message string,
)

func Error2

func Error2(
	message string,
)

func Error2f

func Error2f(
	format string,
	args ...interface{},
)

func Error2fs

func Error2fs(
	subsystem Subsystem,
	format string,
	args ...interface{},
)

func Error2s

func Error2s(
	subsystem Subsystem,
	message string,
)

func Error3

func Error3(
	message string,
)

func Error3f

func Error3f(
	format string,
	args ...interface{},
)

func Error3fs

func Error3fs(
	subsystem Subsystem,
	format string,
	args ...interface{},
)

func Error3s

func Error3s(
	subsystem Subsystem,
	message string,
)

func Error4

func Error4(
	message string,
)

func Error4f

func Error4f(
	format string,
	args ...interface{},
)

func Error4fs

func Error4fs(
	subsystem Subsystem,
	format string,
	args ...interface{},
)

func Error4s

func Error4s(
	subsystem Subsystem,
	message string,
)

func Info1

func Info1(
	message string,
)

-- info messages

func Info1f

func Info1f(
	format string,
	args ...interface{},
)

func Info1fs

func Info1fs(
	subsystem Subsystem,
	format string,
	args ...interface{},
)

func Info1s

func Info1s(
	subsystem Subsystem,
	message string,
)

func Info2

func Info2(
	message string,
)

func Info2f

func Info2f(
	format string,
	args ...interface{},
)

func Info2fs

func Info2fs(
	subsystem Subsystem,
	format string,
	args ...interface{},
)

func Info2s

func Info2s(
	subsystem Subsystem,
	message string,
)

func Info3

func Info3(
	message string,
)

func Info3f

func Info3f(
	format string,
	args ...interface{},
)

func Info3fs

func Info3fs(
	subsystem Subsystem,
	format string,
	args ...interface{},
)

func Info3s

func Info3s(
	subsystem Subsystem,
	message string,
)

func Info4

func Info4(
	message string,
)

func Info4f

func Info4f(
	format string,
	args ...interface{},
)

func Info4fs

func Info4fs(
	subsystem Subsystem,
	format string,
	args ...interface{},
)

func Info4s

func Info4s(
	subsystem Subsystem,
	message string,
)

func Info5

func Info5(
	message string,
)

func Info5f

func Info5f(
	format string,
	args ...interface{},
)

func Info5fs

func Info5fs(
	subsystem Subsystem,
	format string,
	args ...interface{},
)

func Info5s

func Info5s(
	subsystem Subsystem,
	message string,
)

func Init

func Init(
	system string,
)

Initialize the global log

Parameters:

system: a system identifier shown in the logs

func InitWithTimeSource

func InitWithTimeSource(
	system string,
	timesrc TimeSource,
)

Initialize the global log with specified time source

func LogMessage

func LogMessage(
	subsystem Subsystem,
	severity Severity,
	verbosity Verbosity,
	message string,
)

Log a text message

Parameters:

subsystem: logging subsystem
severity: logging severity
verbosity: logging verbosity
message: the message

func LogMessagef

func LogMessagef(
	subsystem Subsystem,
	severity Severity,
	verbosity Verbosity,
	format string,
	args ...interface{},
)

Log a formatted text message

Parameters:

subsystem: logging subsystem
severity: logging severity
verbosity: logging verbosity
format: printf-like format of the message
args: arguments of the message

func LogObject

func LogObject(
	subsystem Subsystem,
	severity Severity,
	verbosity Verbosity,
	object interface{},
)

Log a logging object into the global log

Parameters:

subsystem: logging subsystem
severity: logging severity
verbosity: logging verbosity
object: logging object

func Warning1

func Warning1(
	message string,
)

func Warning1f

func Warning1f(
	format string,
	args ...interface{},
)

func Warning1fs

func Warning1fs(
	subsystem Subsystem,
	format string,
	args ...interface{},
)

func Warning1s

func Warning1s(
	subsystem Subsystem,
	message string,
)

func Warning2

func Warning2(
	message string,
)

func Warning2f

func Warning2f(
	format string,
	args ...interface{},
)

func Warning2fs

func Warning2fs(
	subsystem Subsystem,
	format string,
	args ...interface{},
)

func Warning2s

func Warning2s(
	subsystem Subsystem,
	message string,
)

func Warning3

func Warning3(
	message string,
)

func Warning3f

func Warning3f(
	format string,
	args ...interface{},
)

func Warning3fs

func Warning3fs(
	subsystem Subsystem,
	format string,
	args ...interface{},
)

func Warning3s

func Warning3s(
	subsystem Subsystem,
	message string,
)

func Warning4

func Warning4(
	message string,
)

func Warning4f

func Warning4f(
	format string,
	args ...interface{},
)

func Warning4fs

func Warning4fs(
	subsystem Subsystem,
	format string,
	args ...interface{},
)

func Warning4s

func Warning4s(
	subsystem Subsystem,
	message string,
)

Types

type ApacheObject

type ApacheObject interface {
	// Get values to be logged
	//
	// Returns:
	//     remoteHost: IP or host of the client
	//     identity: identity string (RFC 1413)
	//     user: user name determined by the http authentication
	//     requestTime: time when the request comes (local time)
	//     method: http method
	//     resource: resource from the request line
	//     protocol: used protocol (ie HTTP/1.0)
	//     status: status code returned to the user
	//     length: length of the response without the header
	//     referer: referer string
	//     agent: user agent (browser)
	GetValues() (
		remoteHost string,
		identity string,
		user string,
		requestTime time.Time,
		method string,
		resource string,
		protocol string,
		status int,
		length uint64,
		referer string,
		agent string)
}

This is a logging interface used for the Apache combined logging format.

type Color

type Color int

Color constants

const (
	NONE Color = iota
	RED
	YELLOW
	BLUE
)

type FileHolder

type FileHolder interface {
	// Access and log the log writer for writing of one item
	AccessWriter(
		functor func(writer FileWriter))

	// Increase reference counter - there is new owner of the holder
	//
	// Returns: itself
	Ref() FileHolder

	// Decrease reference counter
	//
	// If the counter reaches zero the object is destroyed (files
	// closed etc.)
	//
	// Expectation: there are no other threads accessing the holder
	//     if the reference counter reaches zero!
	Unref()
}

Holder of a file

This interface wraps a logging file. The file can be just one physical file. Or it can be a pattern defining a rotating logs.

func NewSimpleFile

func NewSimpleFile(
	filepath string,
	sync bool,
) FileHolder

Create new simple file holder

Parameters:

filepath: name of the logging file
sync: if true, the stream is flushed after every message

Returns:

the new file holder

Note: the reference counter is set to 1. You have to invoke Unref()

to clean up the holder.

func NewSimpleFileHandle

func NewSimpleFileHandle(
	file *os.File,
	sync bool,
) FileHolder

Create new simple file holder working over an opened file handle

Parameters:

file: the opened file
sync: if true, the stream is flushed after every message

Returns:

the new file holder

Note: the reference counter is set to 1. You have to invoke Unref()

to clean up the holder.

type FileWriter

type FileWriter interface {
	// If writter is not closable, the method Close returns nil.
	io.WriteCloser

	// If it is unable to read file info, it returns nil
	Stat() os.FileInfo

	// Flush the output
	Sync()

	// Change output color
	ChangeColor(
		color Color)

	// Reset the output color
	ResetColor()
}

Generic file writer

This interface is a classic io.Writer interface extended by possibility to change colors of the output.

type LineFormatter

type LineFormatter interface {
	// Format a line
	//
	// Parameters:
	//     writer: line writer
	//     now: current time
	//     system: logging system
	//     subsystem: logging subsystem (can be empty)
	//     severity: severity of the logging message
	//     verbosity: verbosity of the logging message
	//     line: the logging message
	FormatLine(
		writer FileWriter,
		now time.Time,
		system string,
		subsystem Subsystem,
		severity Severity,
		verbosity Verbosity,
		line string)
}

Generic line formatter

Implementations of this class format output logging lines

func NewLineFormatterDefault

func NewLineFormatterDefault(
	short bool,
) LineFormatter

Create new default line formatter

Parameters:

short: determine whether the short format should be used

type LineObject

type LineObject interface {
	// Get the message line
	GetLogLine() string
}

Simple line logging object

This interface wraps simple logging message - one line of text

type LogDispatcher

type LogDispatcher interface {
	// Destroy the distpatcher
	//
	// Warning: this method is not thread safe. Use it if you're certain
	//     all threads have stopped already.
	Destroy()

	// Log an object
	//
	// Parameters:
	//     subsystem: ID of logging subsystem
	//     severity: severity of the log message
	//     verbosity: verbosity of the log message
	//     object: an object to be logged
	LogObject(
		subsystem Subsystem,
		severity Severity,
		verbosity Verbosity,
		object interface{})

	// Add new logger
	//
	// Parameters:
	//     name: a unique name of the logger
	//     subsystem: ID of logging subsystem
	//     severity: maximal severity of the logger
	//     verbosity: maximal verbosity of the logger
	//     logger: the logger object
	AddLogger(
		name string,
		subsystem Subsystem,
		severities SeverityMask,
		verbosity Verbosity,
		logger Logger)
}

Dispatch a log object into the logger objects

func NewLogDispatcher

func NewLogDispatcher(
	system string,
) LogDispatcher

Create new log dispatcher

Parameters:

system: an identifier shown in the logs

type LogRotator

type LogRotator interface {
	// return if this file need rotation
	NeedRotate(timesrc TimeSource) bool
	// Rotate this file
	Rotate(timesrc TimeSource)
	// Return the time of next check. It is called after logsRotator.Add and after NeedRotate/Rotate
	GetNextCheckTime(timesrc TimeSource) time.Time
}

The rotator interface. The rotator is usually connected to one particular logger. If a rotator is added to logsRotatorStarter, methods NeedRotate + Rotate are runed in separate goroutine. The start time of boths method is determined by the method GetNextCheckTime.

type Logger

type Logger interface {
	// Destroy the logger
	//
	// Warning: the method is not thread safe!
	Destroy()

	// Log an object
	//
	// Parameters:
	//     system: a logging system
	//     subsystem: a logging sybsystem
	//     severity: message severity
	//     verbosity: message verbosity
	//     object: an object to be logged
	LogObject(
		system string,
		subsystem Subsystem,
		severity Severity,
		verbosity Verbosity,
		object interface{})
}

An object logger

func NewApacheLogger

func NewApacheLogger(
	file FileHolder,
) Logger

Create new apache logger

The Apache logger expects the Apache logging objects. The output format follows the combined Apache logging format.

Parameters:

file: a file holder used for the output

Returns:

the logger

func NewFileLogger

func NewFileLogger(
	timesrc TimeSource,
	file FileHolder,
	formatter LineFormatter,
) Logger

Create new file logger

Parameters:

timesrc: a timesource
file: a file holder used for the output
formatter: a line formatter

Returns:

the logger

type RotatableFileHolder

type RotatableFileHolder interface {
	LogRotator
	FileHolder
}

FileHolder with the LogRotator

func NewPatternFile

func NewPatternFile(
	timesrc TimeSource,
	pattern string,
	sync bool,
) RotatableFileHolder

Create new pattern file holder

This implementation allows rotating of log files according specified pattern.

The pattern is a string which can contain special sequences:

%Y ..... year (4 digits)
%m ..... month (01 - 12)
%d ..... day (01 - 31)
%H ..... hour (00 - 23)
%M ..... minute (00 - 59)
%% ..... %

Parameters:

timesrc: time source
pattern: the filename pattern
sync: flush the file after every line

Returns:

the new file holder

Note: the reference counter is set to 1. You have to invoke Unref()

to clean up the holder.

func NewRotatableFile

func NewRotatableFile(filePath string, sync bool, maxSize int64, checkInterval time.Duration) RotatableFileHolder

Create new rotatable file holder.

Parameters:

filepath: name of the logging file
sync: if true, the stream is flushed after every message
maxSize:  Make log rotation if log size is bigger than maxSize.
checkInterval: time interval to check the log size; usually minutes or tens of minutes

Returns:

the new rotatable file holder

Note: the reference counter is set to 1. You have to invoke Unref()

to clean up the holder.

type Severity

type Severity uint32

Severity of a log message

const (
	Critical Severity = 1 << iota
	Error
	Warning
	Info
	Debug
)

func (Severity) Code

func (this Severity) Code() string

type SeverityMask

type SeverityMask uint32

Mask of severities

type Subsystem

type Subsystem string

Subsystem name

type TimeSource

type TimeSource interface {
	// Get current time
	Now() time.Time
}

Source of current time used in the logging messages

func NewTimeSourceLocal

func NewTimeSourceLocal() TimeSource

Create new local time source

This time source returns local current time read from the system

type Verbosity

type Verbosity uint32

Verbosity of a log message

0 means no logging, a higher number means a higher verbosity level

Jump to

Keyboard shortcuts

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