logdog

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

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

Go to latest
Published: Aug 7, 2017 License: Apache-2.0 Imports: 17 Imported by: 5

README

Logdog

Why logdog

Log is the most loyal friend for programmers -- Jim Zhang

Logdog is a Go logging package for Humans™ inspired by Python’s logging module.

Overview

terminal.png

Getting Started

package main

import (
	"github.com/zoumo/logdog"
)

func init() {
	// set min level, only log info or above can be emitted
	logdog.SetLevel(logdog.INFO)

	// enable logger get caller func's filename and lineno
	logdog.EnableRuntimeCaller(true)
}

func main() {
	logdog.Debug("this is debug")
	// Fields should be the last arg
	logdog.Info("this is info", logdog.Fields{"x": "test"})
}

Introduce

Logging Flow

logging flow

Logger Mindmap

logger mindmap

Fields

Inspired by Logrus. the Fields must be the LAST arg in log fucntion.

	logdog.Info("this is info, msg ", "some msg", logdog.Fields{"x": "test"})
	logdog.Infof("this is info, msg %s", "some msg", logdog.Fields{"x": "test"})

Loggers

Logger have a threefold job. First, they expose several methods to application code so that applications can log messages at runtime. Second, logger objects determine which log messages to act upon based upon severity (the default filtering facility) or filter objects. Third, logger objects pass along relevant log messages to all interested log handlers.

I do not adopt the inheritance features in Python logging, because it is obscure, intricate and useless. I would like the Logger be simple and readable

Handlers

Handler is responsible for dispatching the appropriate log messages to the handler’s specified destination. Logger can add zero or more handlers to themselves with AddHandler() method. For example to send all log messages to stdout , all log messages of error or higher level to a log file

import (
    "github.com/zoumo/logdog"
)

func main() {
    logdog.DisableExistingLoggers()
    handler := logdog.NewStreamHandler()
    handler2 := logdog.NewFileHandler()
    handler2.LoadConfig(logdog.Config{
        "level"   : "ERROR",
		"filename": "./test",
	})
    logdog.AddHandler(handler)
    
    logdog.Debug("this is debug")
    logdog.Error("this is error")
}

Handler is a Interface Type.

type Handler interface {
    // Handle the specified record, filter and emit
    Handle(*LogRecord)
    // Check if handler should filter the specified record
    Filter(*LogRecord) bool
    // Emit log record to output - e.g. stderr or file
    Emit(*LogRecord)
    // Close output stream, if not return error
    Close() error
}

Logdog comes with built-in handlers: NullHandler, SteamHandler, FileHandler. Maybe provide more extra handlers in the future, e.g. RotatingFileHandler

Formatters

Formatters configure the final order, structure, and contents of the log message Each Handler contains one Formatter, because only Handler itself knows which Formatter should be selected to determine the order, structure, and contents of log message Logdog comes with built-in formatters: TextFormatter, JsonFormatter Formatter is a Interface Type

type Formatter interface {
	Format(*LogRecord) (string, error)
}
TextFormatter

the default TextFormatter takes three args:

arg description default
DateFmt date time format string "%Y-%m-%d %H:%M:%S"
Fmt log message format string %(color)[%(time)] [%(levelname)] [%(filename):%(lineno)]%(end_color) %(message)
EnableColors enable print log with color or not true

The DateFmt format string looks like python datetime format string the possible keys are documented in go-when Strftime

The Fmt message format string uses %(<dictionary key>) styled string substitution; the possible keys :

key name description
name Name of the logger (logging channel)
levelno Numeric logging level for the message (DEBUG, INFO, WARNING, ERROR, CRITICAL)
levelname Text logging level for the message ("DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL")
pathname Full pathname of the source file where the logging call was issued (if available) or maybe ??
filename Filename portion of pathname
lineno Source line number where the logging call was issued (if available)
funcname Function name of caller or maybe ??
time Textual time when the LogRecord was created
message The result of record.getMessage(), computed just as the record is emitted
color print color
end_color reset color

Configuring Logging

Programmers can configure logging in two ways:

  1. Creating loggers, handlers, and formatters explicitly using Golang code that calls the configuration methods listed above.
  2. Creating a json format config string and passing it to the LoadJSONConfig() function.
package main

import (
	"github.com/zoumo/logdog"
)

func main() {
    
    logger := logdog.GetLogger("test")
    
    handler := logdog.NewStreamHandler()
    handler2 := logdog.NewFileHandler()
    handler2.LoadConfig(logdog.Config{
		"filename": "./test",
    })
    
    logger.AddHandler(handler, handler2)
    
    logger.SetLevel(logdog.INFO)
    logger.EnableRuntimeCaller(true)
    
	logger.Debug("this is debug")
	logger.Info("this is info", logdog.Fields{"x": "test"})
}
package main

import (
	"github.com/zoumo/logdog"
)

func main() {

	config := []byte(`{
        "disable_existing_loggers": true,
        "handlers": {
            "null": {
                "class": "NullHandler",
                "level": "DEBUG"
            },
            "console": {
                "class": "StreamHandler",
                "formatter": "default",
                "level": "INFO"
            }
        },
        "loggers": {
            "app": {
                "level": "DEBUG",
                "enable_runtime_caller": true,
                "handlers": ["null", "console"]
            }
        }

    }`)

    logdog.LoadJSONConfig(config)
    logger := logdog.GetLogger("app")
    
	logger.Debug("this is debug")
	logger.Info("this is info", logdog.Fields{"x": "test"})
}

Requirement

TODO

  • rotating file handler
  • use goroutine to accelerate logdog
  • more handler
  • godoc

Thanks

Documentation

Index

Constants

View Source
const (
	// DefaultFmtTemplate is the default log string format value for TextFormatter
	DefaultFmtTemplate = "%(time) %(color)%(levelname)%(endColor) %(filename):%(lineno) | %(message)"
	// DefaultDateFmtTemplate is the default log time string format value for TextFormatter
	DefaultDateFmtTemplate = "%Y-%m-%d %H:%M:%S"
)
View Source
const (
	// DefaultCallerStackDepth is 2 because you should ascend 2 frames
	// to get true caller function by default
	DefaultCallerStackDepth = 2
)
View Source
const (
	// RootLoggerName is the name of root logger
	RootLoggerName = "root"
)

Variables

View Source
var (
	// LogRecordFieldRegexp is the field regexp
	// for example, I will replace %(name) of real record name
	// TODO support %[(name)][flags][width].[precision]typecode
	LogRecordFieldRegexp = regexp.MustCompile(`\%\(\w+\)`)
	// DefaultFormatter is the default formatter of TextFormatter without color
	DefaultFormatter = &TextFormatter{
		Fmt:     DefaultFmtTemplate,
		DateFmt: DefaultDateFmtTemplate,
	}
	// TerminalFormatter is an TextFormatter with color
	TerminalFormatter = &TextFormatter{
		Fmt:          DefaultFmtTemplate,
		DateFmt:      DefaultDateFmtTemplate,
		EnableColors: true,
	}

	// ColorHash describes colors of different log level
	// you can add new color for your own log level
	ColorHash = map[Level]int{
		DebugLevel:  blue,
		InfoLevel:   green,
		WarnLevel:   yellow,
		ErrorLevel:  red,
		NoticeLevel: darkGreen,
		FatalLevel:  red,
	}
)
View Source
var (
	// Discard is an io.ReadWriteCloser on which all Read | Write | Close calls succeed
	// without doing anything.
	Discard = devNull(0)
)
View Source
var (
	// ForceColor forces formatter use color output
	ForceColor = false
)

Functions

func Debug

func Debug(args ...interface{})

Debug is an alias of root.Debug

func Debugf

func Debugf(msg string, args ...interface{})

Debugf is an alias of root.Debugf

func DisableExistingLoggers

func DisableExistingLoggers()

DisableExistingLoggers closes all existing loggers and unregister them

func Error

func Error(args ...interface{})

Error is an alias of root.Error

func Errorf

func Errorf(msg string, args ...interface{})

Errorf is an alias of root.Errorf

func Fatal

func Fatal(args ...interface{})

Fatal is an alias of root.Critical

func Fatalf

func Fatalf(msg string, args ...interface{})

Fatalf is an alias of root.Criticalf

func Flush

func Flush() error

Flush ...

func FormatTime

func FormatTime(record *LogRecord, datefmt string) string

FormatTime returns the creation time of the specified LogRecord as formatted text.

func Info

func Info(args ...interface{})

Info is an alias of root.Info

func Infof

func Infof(msg string, args ...interface{})

Infof is an alias of root.Infof

func IsColorTerminal

func IsColorTerminal() (bool, bool)

IsColorTerminal return isTerminal and isColorTerminal

func LoadJSONConfig

func LoadJSONConfig(config []byte) error

LoadJSONConfig loads a json config if DisableExistingLoggers is true, all existing loggers will be closed, then a new root logger will be created

func Notice

func Notice(args ...interface{})

Notice is an alias of root.Notice

func Noticef

func Noticef(msg string, args ...interface{})

Noticef is an alias of root.Noticef

func Panic

func Panic(msg string, args ...interface{})

Panic an alias of root.Panic

func Panicf

func Panicf(msg string, args ...interface{})

Panicf is an alias of root.Panicf

func RegisterConstructor

func RegisterConstructor(name string, c Constructor)

RegisterConstructor binds name and Constructor

func RegisterFormatter

func RegisterFormatter(name string, formatter Formatter)

RegisterFormatter binds name and Formatter

func RegisterHandler

func RegisterHandler(name string, handler Handler)

RegisterHandler binds name and Handler

func RegisterLevel

func RegisterLevel(name string, level Level)

RegisterLevel binds name and level

func Warn

func Warn(args ...interface{})

Warn is an alias of root.Warn

func Warnf

func Warnf(msg string, args ...interface{})

Warnf is an alias of root.Warnf

func Warning

func Warning(args ...interface{})

Warning is an alias of root.Warning

func Warningf

func Warningf(msg string, args ...interface{})

Warningf is an alias of root.Warningf

Types

type Config

type Config map[string]interface{}

Config is a alias of map[string]interface{}

type ConfigLoader

type ConfigLoader interface {
	LoadConfig(map[string]interface{}) error
}

ConfigLoader is an interface which con load map[string]interface{} config

type Constructor

type Constructor func() ConfigLoader

Constructor is a function which returns an ConfigLoader

func GetConstructor

func GetConstructor(name string) Constructor

GetConstructor returns an Constructor registered with the given name if not, returns nil

type Fields

type Fields map[string]interface{}

Fields is an alias to man[string]interface{}

func (Fields) String

func (f Fields) String() string

String convert Fields to string

func (Fields) ToKVString

func (f Fields) ToKVString(color, endColor string) string

ToKVString convert Fields to string likes k1=v1 k2=v2

type FileHandler

type FileHandler struct {
	Name      string
	Level     Level
	Formatter Formatter
	Output    flushWriteCloser
	Path      string
	// contains filtered or unexported fields
}

FileHandler is a handler similar to SteamHandler if specified file and it will close the file

func NewFileHandler

func NewFileHandler(options ...Option) *FileHandler

NewFileHandler returns a new FileHandler fully initialized

func (*FileHandler) ApplyOptions

func (hdlr *FileHandler) ApplyOptions(options ...Option) *FileHandler

ApplyOptions applys all option to StreamHandler

func (*FileHandler) Close

func (hdlr *FileHandler) Close() error

Close file, if not return error

func (*FileHandler) Emit

func (hdlr *FileHandler) Emit(record *LogRecord)

Emit log record to file

func (*FileHandler) Filter

func (hdlr *FileHandler) Filter(record *LogRecord) bool

Filter checks if handler should filter the specified record

func (*FileHandler) Flush

func (hdlr *FileHandler) Flush() error

Flush flushes the file system's in-memory copy of recently written data to disk.

func (*FileHandler) LoadConfig

func (hdlr *FileHandler) LoadConfig(c map[string]interface{}) error

LoadConfig loads config from its input and stores it in the value pointed to by c

func (*FileHandler) SetPath

func (hdlr *FileHandler) SetPath(path string) *FileHandler

SetPath opens file located in the path, if not, create it

type Formatter

type Formatter interface {
	Format(*LogRecord) (string, error)
	Option
}

Formatter is an interface which can convert a LogRecord to string

func GetFormatter

func GetFormatter(name string) Formatter

GetFormatter returns an Formatter registered with the given name

type Handler

type Handler interface {
	// Filter checks if handler should filter the specified record
	Filter(*LogRecord) bool
	// Emit log record to output - e.g. stderr or file
	Emit(*LogRecord)
	// Flush flushes the file system's in-memory copy of recently written data to disk.
	// Typically, calls the file.Sync()
	Flush() error
	// Close output stream, if not return error
	Close() error
}

Handler specifies how to write a LoadConfig, appropriately formatted, to output.

func GetHandler

func GetHandler(name string) Handler

GetHandler returns a Handler registered with the given name

type JSONFormatter

type JSONFormatter struct {
	Datefmt string
	ConfigLoader
}

JSONFormatter can convert LogRecord to json text

func NewJSONFormatter

func NewJSONFormatter() *JSONFormatter

NewJSONFormatter returns a JSONFormatter with default config

func (*JSONFormatter) Format

func (jf *JSONFormatter) Format(record *LogRecord) (string, error)

Format converts the specified record to json string.

func (*JSONFormatter) LoadConfig

func (jf *JSONFormatter) LoadConfig(c map[string]interface{}) error

LoadConfig loads config from its input and stores it in the value pointed to by c

type Level

type Level int

Level is a logging priority. Note that Level satisfies the Option interface

const (
	// NothingLevel log level only used in filter
	NothingLevel Level = 0
	// DebugLevel log level
	DebugLevel Level = 1 //0x00000001
	// InfoLevel log level
	InfoLevel Level = 2 //0x00000010
	// WarnLevel log level
	WarnLevel Level = 4 //0x00000100
	// WarningLevel is alias of WARN
	WarningLevel Level = 4 //0x00000100
	// ErrorLevel log level
	ErrorLevel Level = 8 //0x00001000
	// NoticeLevel log level
	NoticeLevel Level = 16 //0x00010000
	// FatalLevel log level
	FatalLevel Level = 32 //0x00100000
	// AllLevel log level only used in filter
	AllLevel Level = 255 //0x11111111
)

func GetLevel

func GetLevel(name string) Level

GetLevel returns a Level registered with the given name

func (Level) String

func (l Level) String() string

type LogConfig

type LogConfig struct {
	DisableExistingLoggers bool                              `json:"disableExistingLoggers"`
	Formatters             map[string]map[string]interface{} `json:"formatters"`
	Handlers               map[string]map[string]interface{} `json:"handlers"`
	Loggers                map[string]map[string]interface{} `json:"loggers"`
}

LogConfig defines the configuration of logger

type LogRecord

type LogRecord struct {
	Name          string
	Level         Level
	LevelName     string
	PathName      string
	FileName      string
	FuncName      string
	ShortFuncName string
	Line          int
	Time          time.Time
	// msg could be ""
	Msg  string
	Args []interface{}
	// extract fields from args
	Fields Fields
}

LogRecord defines a real log record should be

func NewLogRecord

func NewLogRecord(name string, level Level, pathname string, funcname string, line int, msg string, args ...interface{}) *LogRecord

NewLogRecord returns a new log record

func (*LogRecord) ExtractFieldsFromArgs

func (lr *LogRecord) ExtractFieldsFromArgs()

ExtractFieldsFromArgs extracts fields (Fields) from args Fields must be the last element in args

func (LogRecord) GetMessage

func (lr LogRecord) GetMessage() string

GetMessage formats record message by msg and args

type Logger

type Logger struct {
	Name     string
	Handlers []Handler
	Level    Level
	// callerStackDepth is the number of stack frames to ascend
	// you should change it if you implement your own log function
	CallerStackDepth    int
	EnableRuntimeCaller bool
}

Logger entries pass through the formatter before logged to Output. The included formatters are `TextFormatter` and `JSONFormatter` for which TextFormatter is the default. In development (when a TTY is attached) it logs with colors, but to a file it wouldn't. You can easily implement your own that implements the `Formatter` interface, see the `README` or included formatters for examples.

func AddHandlers

func AddHandlers(handlers ...Handler) *Logger

AddHandlers is an alias of root.AddHandler

func ApplyOptions

func ApplyOptions(options ...Option) *Logger

ApplyOptions is an alias of root.ApplyOptions

func GetLogger

func GetLogger(name string, options ...Option) *Logger

GetLogger returns an logger by name if not, create one and add it to logger register

func NewLogger

func NewLogger(options ...Option) *Logger

NewLogger returns a new Logger

func (*Logger) AddHandlers

func (lg *Logger) AddHandlers(handlers ...Handler) *Logger

AddHandlers adds handler to logger

func (*Logger) ApplyOptions

func (lg *Logger) ApplyOptions(options ...Option) *Logger

ApplyOptions applys all option to Logger

func (*Logger) Close

func (lg *Logger) Close() error

Close closes output stream

func (Logger) Debug

func (lg Logger) Debug(args ...interface{})

Debug emits log message with DEBUG level

func (Logger) Debugf

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

Debugf emits log with DEBUG level and format string

func (Logger) Error

func (lg Logger) Error(args ...interface{})

Error emits log message with ERROR level

func (Logger) Errorf

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

Errorf emits log with ERROR level and format string

func (Logger) Fatal

func (lg Logger) Fatal(args ...interface{})

Fatal emits log message with FATAL level

func (Logger) Fatalf

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

Fatalf emits log with FATAL level and format string

func (Logger) Filter

func (lg Logger) Filter(record *LogRecord) bool

Filter checks if logger should filter the specified record

func (*Logger) Flush

func (lg *Logger) Flush() error

Flush flushes the file system's in-memory copy to disk

func (*Logger) Handle

func (lg *Logger) Handle(record *LogRecord)

Handle handles the LogRecord, call all halders

func (Logger) Info

func (lg Logger) Info(args ...interface{})

Info emits log message with INFO level

func (Logger) Infof

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

Infof emits log with INFO level and format string

func (*Logger) LoadConfig

func (lg *Logger) LoadConfig(c map[string]interface{}) error

LoadConfig loads config from its input and stores it in the value pointed to by c

func (Logger) Log

func (lg Logger) Log(level Level, args ...interface{})

Log emits log message

func (Logger) Logf

func (lg Logger) Logf(level Level, msg string, args ...interface{})

Logf emits log with specified level and format string

func (Logger) Notice

func (lg Logger) Notice(args ...interface{})

Notice emits log message with NOTICE level

func (Logger) Noticef

func (lg Logger) Noticef(msg string, args ...interface{})

Noticef emits log with NOTICE level and format string

func (Logger) Panic

func (lg Logger) Panic(msg string, args ...interface{})

Panic emits log message with FATAL level and panic it

func (Logger) Panicf

func (lg Logger) Panicf(msg string, args ...interface{})

Panicf emits log with FATAL level and format string and panic it

func (Logger) Warn

func (lg Logger) Warn(args ...interface{})

Warn emits log message with WARN level

func (Logger) Warnf

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

Warnf emits log with WARN level and format string

type NullHandler

type NullHandler struct {
	Name string
}

NullHandler is an example handler doing nothing

func NewNullHandler

func NewNullHandler() *NullHandler

NewNullHandler returns a NullHandler

func (*NullHandler) Close

func (hdlr *NullHandler) Close() error

Close output stream, if not return error

func (*NullHandler) Emit

func (hdlr *NullHandler) Emit(*LogRecord)

Emit log record to output - e.g. stderr or file

func (*NullHandler) Filter

func (hdlr *NullHandler) Filter(*LogRecord) bool

Filter checks if handler should filter the specified record

func (*NullHandler) Flush

func (hdlr *NullHandler) Flush() error

Flush flushes in-memory data to disk

func (*NullHandler) LoadConfig

func (hdlr *NullHandler) LoadConfig(config map[string]interface{}) error

LoadConfig loads config from its input and stores it in the value pointed to by c

type Option

type Option interface {
	// contains filtered or unexported methods
}

Option is an interface which is used to set options for the target

func OptionCallerStackDepth

func OptionCallerStackDepth(depth int) Option

OptionCallerStackDepth is an option. used in every target which has fields named `CallerStackDepth`

func OptionDiscardOutput

func OptionDiscardOutput() Option

OptionDiscardOutput is an option used in every target which has fields named `Output` and make all Read | Write | Close calls succeed without doing anything.

func OptionEnableRuntimeCaller

func OptionEnableRuntimeCaller(enable bool) Option

OptionEnableRuntimeCaller is an option useed in : used in every target which has fields named `EnableRuntimeCaller`

func OptionHandlers

func OptionHandlers(handlers ...Handler) Option

OptionHandlers is an option used in every target which has fields named `Handlers`

func OptionName

func OptionName(name string) Option

OptionName is an option used in every target which has fields named `Name`

func OptionOutput

func OptionOutput(out io.WriteCloser) Option

OptionOutput is an option used in every target which has fields named `Output`

type StreamHandler

type StreamHandler struct {
	Name      string
	Level     Level
	Formatter Formatter
	Output    flushWriter
	// contains filtered or unexported fields
}

StreamHandler is a handler which writes logging records, appropriately formatted, to a stream. Note that this handler does not close the stream, as os.Stdout or os.Stderr may be used.

func NewStreamHandler

func NewStreamHandler(options ...Option) *StreamHandler

NewStreamHandler returns a new StreamHandler fully initialized

func (*StreamHandler) ApplyOptions

func (hdlr *StreamHandler) ApplyOptions(options ...Option) *StreamHandler

ApplyOptions applys all option to StreamHandler

func (*StreamHandler) Close

func (hdlr *StreamHandler) Close() error

Close output stream, if not return error

func (*StreamHandler) Emit

func (hdlr *StreamHandler) Emit(record *LogRecord)

Emit log record to output - e.g. stderr or file

func (*StreamHandler) Filter

func (hdlr *StreamHandler) Filter(record *LogRecord) bool

Filter checks if handler should filter the specified record

func (*StreamHandler) Flush

func (hdlr *StreamHandler) Flush() error

Flush flushes the file system's in-memory copy to disk

func (*StreamHandler) LoadConfig

func (hdlr *StreamHandler) LoadConfig(c map[string]interface{}) error

LoadConfig loads config from its input and stores it in the value pointed to by c

type TextFormatter

type TextFormatter struct {
	Fmt          string
	DateFmt      string
	EnableColors bool

	ConfigLoader
	// contains filtered or unexported fields
}

TextFormatter is the default formatter used to convert a LogRecord to text.

The Formatter can be initialized with a format string which makes use of knowledge of the LogRecord attributes - e.g. the default value mentioned above makes use of the fact that the user's message and arguments are pre- formatted into a LogRecord's message attribute. Currently, the useful attributes in a LogRecord are described by:

%(name) Name of the logger (logging channel) %(levelno) Numeric logging level for the message (DEBUG, INFO,

WARNING, ERROR, CRITICAL)

%(levelname) Text logging level for the message ("DEBUG", "INFO",

"WARNING", "ERROR", "CRITICAL")

%(pathname) Full pathname of the source file where the logging

call was issued (if available) or maybe ??

%(filename) Filename portion of pathname %(lineno) Source line number where the logging call was issued

(if available)

%(funcname) Function name of caller or maybe ?? %(time) Textual time when the LogRecord was created %(message) The result of record.getMessage(), computed just as

the record is emitted

%(color) Print color %(endColor) Reset color

func NewTextFormatter

func NewTextFormatter() *TextFormatter

NewTextFormatter return a new TextFormatter with default config

func (*TextFormatter) Format

func (tf *TextFormatter) Format(record *LogRecord) (string, error)

Format converts the specified record to string. bench mark with 10 fields go template 33153 ns/op ReplaceAllStringFunc 8420 ns/op field sequence 5046 ns/op

func (*TextFormatter) LoadConfig

func (tf *TextFormatter) LoadConfig(c map[string]interface{}) error

LoadConfig loads config from its input and stores it in the value pointed to by c

Directories

Path Synopsis
pkg

Jump to

Keyboard shortcuts

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