colog

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

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

Go to latest
Published: Apr 16, 2016 License: MIT Imports: 15 Imported by: 10

README

Build Status godoc reference

What's CoLog?

CoLog is a prefix-based leveled execution log for Go. It's heavily inspired by Logrus and aims to offer similar features by parsing the output of the standard library log. If you don't understand what this means take a look at this picture.

CoLog showcase

But why?

An introduction and the rationale behind CoLog can be found in this blog post: https://texlution.com/post/colog-prefix-based-logging-in-golang/

Features

  • Supports hooks to receive log entries and send them to external systems via AddHook
  • Supports customs formatters (color/pain text and JSON built-in) via SetFormatter
  • Provides 6 built-in levels: trace, debug, info, warning, error, alert
  • Understands full, 3 letter, and 1 letter headers: error:, err:, e:
  • Supports custom prefixes (headers in CoLog terms) via SetHeaders and AddHeader
  • Control levels used via SetMinLevel and SetDefaultLevel
  • Supports optionally parsing key=value or key='some value' pairs
  • Supports custom key-value extractor via SetExtractor
  • Supports permanent context values via FixedValue and ClearFixedValues
  • Supports standalone loggers via NewCoLog and NewLogger
  • Compatible with existing Logrus hooks and formatters via cologrus
  • Supports Windows terminal colors via wincolog

API stability

CoLog's API is very unlikely to get breaking changes, but there are no promises. That being said, CoLog only needs to be imported by final applications and if you have one of those, you should be vendoring you dependencies in the first place. CoLog has no external dependencies, to vendor it you just need to clone this repo anywhere you want and start using it.

Usage examples

Basic usage
package main

import (
	"log"

	"github.com/comail/colog"
)

func main() {
	colog.Register()
	log.Print("info: that's all it takes!")
}
JSON output to a file with field parsing
package main

import (
	"log"
	"os"
	"time"

	"github.com/comail/colog"
)

func main() {
	file, err := os.OpenFile("temp_json.log", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0777)
	if err != nil {
		panic(err)
	}

	colog.Register()
	colog.SetOutput(file)
	colog.ParseFields(true)
	colog.SetFormatter(&colog.JSONFormatter{
		TimeFormat: time.RFC3339,
		Flag:       log.Lshortfile,
	})

	log.Print("info: logging this to json")
	log.Print("warning: with fields foo=bar")
}

// cat tempjson.log
// {"level":"info","time":"2015-08-16T13:26:07+02:00","file":"json_example.go","line":24,"message":"logging this to json"}
// {"level":"warning","time":"2015-08-16T13:26:07+02:00","file":"json_example.go","line":25,"message":"with fields","fields":{"foo":"bar"}}
Standalone logger with level control and fixed values
package main

import (
	"log"
	"os"

	"github.com/comail/colog"
)

func main() {
	cl := colog.NewCoLog(os.Stdout, "worker ", log.LstdFlags)
	cl.SetMinLevel(colog.LInfo)
	cl.SetDefaultLevel(colog.LWarning)
	cl.FixedValue("worker_id", 42)

	logger := cl.NewLogger()
	logger.Print("this gets warning level")
	logger.Print("debug: this won't be displayed")
}

// [  warn ] worker 2015/08/16 13:43:06 this gets warning level    worker_id=42
Adding custom hooks
package main

import (
	"fmt"
	"log"

	"github.com/comail/colog"
)

type myHook struct {
	levels []colog.Level
}

func (h *myHook) Levels() []colog.Level {
	return h.levels
}

func (h *myHook) Fire(e *colog.Entry) error {
	fmt.Printf("We got an entry: \n%#v", e)
	return nil
}

func main() {
	colog.Register()
	colog.ParseFields(true)

	hook := &myHook{
		levels: []colog.Level{
			colog.LInfo,    // the hook only receives
			colog.LWarning, // these levels
		},
	}

	colog.AddHook(hook)

	colog.SetMinLevel(colog.LError) // this affects only the output
	log.Print("info: something foo=bar")
}

// We got an entry:
// &colog.Entry{Level:0x3, Time:time.Time{sec:63575323196, nsec:244349216, loc:(*time.Location)(0x23f8c0)}, Host:"",
// Prefix:"", File:"/data/workspace/comail/comail/src/comail.io/go/colog/examples/hook_example.go", Line:37,
// Message:[]uint8{0x73, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x69, 0x6e, 0x67}, Fields:colog.Fields{"foo":"bar"}}%

Documentation

Overview

Package colog implements prefix based logging by setting itself as output of the standard library and parsing the log messages. Level prefixes are called headers in CoLog terms to not confuse with log.Prefix() which is independent. Basic usage only requires registering:

func main() {
	colog.Register()
	log.Print("info: that's all it takes!")
}

CoLog requires the standard logger to submit messages without prefix or flags. So it resets them while registering and assigns them to itself, unfortunately CoLog cannot be aware of any output previously set.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func AddHeader

func AddHeader(header string, level Level)

AddHeader adds a custom header to the input headers to be search for to determine the level for the standard logger

func AddHook

func AddHook(hook Hook)

AddHook adds a hook to be fired on every event with matching level being logged on the standard logger

func ClearFixedValues

func ClearFixedValues()

ClearFixedValues removes all previously set field-value in the standard logger

func FixedValue

func FixedValue(key string, value interface{})

FixedValue sets a field-value pair that will get automatically added to every log entry in the standard logger

func Flags

func Flags() int

Flags returns the output flags for the standard log formatter if any

func ParseFields

func ParseFields(active bool)

ParseFields activates or deactivates field parsing in the message for the standard logger

func Register

func Register()

Register sets CoLog as output for the default logger. It "hijacks" the standard logger flags and prefix previously set. It's not possible to know the output previously set, so the default os.Stderr is assumed.

func SetDefaultLevel

func SetDefaultLevel(l Level)

SetDefaultLevel sets the level that will be used when no level is detected for the standard logger

func SetExtractor

func SetExtractor(ex Extractor)

SetExtractor sets the extractor to use by the standard logger

func SetFlags

func SetFlags(flags int)

SetFlags sets the output flags for the standard log formatter if any

func SetFormatter

func SetFormatter(f Formatter)

SetFormatter sets the formatter to use by the standard logger

func SetHeaders

func SetHeaders(headers HeaderMap)

SetHeaders sets custom headers as the input headers to be search for to determine the level for the standard logger

func SetHost

func SetHost(host string)

SetHost sets the logger hostname assigned to the entries of the standard logger

func SetMinLevel

func SetMinLevel(l Level)

SetMinLevel sets the minimum level that will be actually logged by the standard logger

func SetOutput

func SetOutput(w io.Writer)

SetOutput is analog to log.SetOutput sets the output destination for the standard logger

func SetPrefix

func SetPrefix(prefix string)

SetPrefix sets the logger output prefix of the standard logger

Types

type CoLog

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

CoLog encapsulates our log writer

func NewCoLog

func NewCoLog(out io.Writer, prefix string, flags int) *CoLog

NewCoLog returns CoLog instance ready to be used in logger.SetOutput()

func (*CoLog) AddHeader

func (cl *CoLog) AddHeader(header string, level Level)

AddHeader adds a custom header to the input headers to be search for to determine the level

func (*CoLog) AddHook

func (cl *CoLog) AddHook(hook Hook)

AddHook adds a hook to be fired on every event with matching level being logged. See the hook interface

func (*CoLog) ClearFixedValues

func (cl *CoLog) ClearFixedValues()

ClearFixedValues removes all previously set fields from the logger

func (*CoLog) FixedValue

func (cl *CoLog) FixedValue(key string, value interface{})

FixedValue sets a key-value pair that will get automatically added to every log entry in this logger

func (*CoLog) Flags

func (cl *CoLog) Flags() int

Flags returns the output flags for the formatter if any

func (*CoLog) NewLogger

func (cl *CoLog) NewLogger() *log.Logger

NewLogger returns a colog-enabled logger

func (*CoLog) ParseFields

func (cl *CoLog) ParseFields(active bool)

ParseFields activates or deactivates field parsing in the message

func (*CoLog) SetDefaultLevel

func (cl *CoLog) SetDefaultLevel(l Level)

SetDefaultLevel sets the level that will be used when no level is detected

func (*CoLog) SetExtractor

func (cl *CoLog) SetExtractor(ex Extractor)

SetExtractor sets the formatter to use

func (*CoLog) SetFlags

func (cl *CoLog) SetFlags(flags int)

SetFlags sets the output flags for the formatter if any

func (*CoLog) SetFormatter

func (cl *CoLog) SetFormatter(f Formatter)

SetFormatter sets the formatter to use

func (*CoLog) SetHeaders

func (cl *CoLog) SetHeaders(headers HeaderMap)

SetHeaders sets custom headers as the input headers to be search for to determine the level

func (*CoLog) SetHost

func (cl *CoLog) SetHost(host string)

SetHost sets the logger hostname assigned to the entries

func (*CoLog) SetMinLevel

func (cl *CoLog) SetMinLevel(l Level)

SetMinLevel sets the minimum level that will be actually logged

func (*CoLog) SetOutput

func (cl *CoLog) SetOutput(w io.Writer)

SetOutput is analog to log.SetOutput sets the output destination.

func (*CoLog) SetPrefix

func (cl *CoLog) SetPrefix(prefix string)

SetPrefix sets the logger output prefix

func (*CoLog) Write

func (cl *CoLog) Write(p []byte) (n int, err error)

Write implements io.Writer interface to that the standard logger uses.

type ColorFormatter

type ColorFormatter interface {
	Formatter
	ColorSupported(yes bool)
}

ColorFormatter interface can be implemented by formatters to get notifications on whether the output supports color

type ColorSupporter

type ColorSupporter interface {
	ColorSupported() bool
}

ColorSupporter interface can be implemented by "smart" outputs that want to handle color display themselves

type Entry

type Entry struct {
	Level   Level     // severity: trace, debug, info, warning, error, alert
	Time    time.Time // time of the event
	Host    string    // host origin of the message
	Prefix  string    // Prefix set to the logger
	File    string    // file where the log was called
	Line    int       // line in the file where the log was called
	Message []byte    // logged message
	Fields  Fields    // map of key-value data parsed from the message
}

Entry represents a message being logged and all attached data

type Extractor

type Extractor interface {
	Extract(*Entry) error
}

Extractor interface must be implemented by data extractors the extractor reads the message and tries to extract key-value pairs from the message and sets the in the entry

type Fields

type Fields map[string]interface{}

Fields is the key-value map for extracted data

type Formatter

type Formatter interface {
	Format(*Entry) ([]byte, error) // The actual formatter called every time
	SetFlags(flags int)            // Like the standard log.SetFlags(flags int)
	Flags() int                    // Like the standard log.Flags() int
}

Formatter interface must be implemented by message formatters Format(*Entry) will be called and the resulting bytes sent to output

type HeaderMap

type HeaderMap map[string]Level

HeaderMap links input header strings with levels

type Hook

type Hook interface {
	Levels() []Level   // returns the set of levels for which the hook should be triggered
	Fire(*Entry) error // triggers the hook, this function will be called for every eligible log entry
}

Hook is the interface to be implemented by event hooks

type JSONEntry

type JSONEntry struct {
	Level   string `json:"level,omitempty"`
	Time    string `json:"time,omitempty"`
	Host    string `json:"host,omitempty"`
	Prefix  string `json:"prefix,omitempty"`
	File    string `json:"file,omitempty"`
	Line    int    `json:"line,omitempty"`
	Message string `json:"message,omitempty"`
	Fields  Fields `json:"fields,omitempty"`
}

JSONEntry is an entry with the final JSON field types We can not just implement the Marshaller interface since some of the process depends on runtime options

type JSONFormatter

type JSONFormatter struct {
	TimeFormat string
	LevelAsNum bool
	Flag       int
	// contains filtered or unexported fields
}

JSONFormatter serializes entries to JSON TimeFormat can be any Go time format, if empty it will mimic the standard logger format LevelAsNum will use a numeric string "1", "2",... for as levels instead of "trace", "debug", ..

func (*JSONFormatter) Flags

func (jf *JSONFormatter) Flags() int

Flags returns the output flags for the formatter.

func (*JSONFormatter) Format

func (jf *JSONFormatter) Format(e *Entry) ([]byte, error)

Format takes and entry and returns the formatted output in bytes

func (*JSONFormatter) SetFlags

func (jf *JSONFormatter) SetFlags(flags int)

SetFlags sets the output flags for the formatter.

type Level

type Level uint8

Level represents severity level

const (

	// LTrace represents trace severity level
	LTrace Level
	// LDebug represents debug severity level
	LDebug
	// LInfo represents info severity level
	LInfo
	// LWarning represents warning severity level
	LWarning
	// LError represents error severity level
	LError
	// LAlert represents alert severity level
	LAlert
)

func ParseLevel

func ParseLevel(level string) (Level, error)

ParseLevel parses a string into a type Level

func (Level) String

func (level Level) String() string

String implements the Stringer interface for levels

type LevelMap

type LevelMap map[Level][]byte

LevelMap links levels with output header bytes

type StdExtractor

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

StdExtractor implements a regex based extractor for key-value pairs both unquoted foo=bar and quoted foo="some bar" are supported

func (*StdExtractor) Extract

func (se *StdExtractor) Extract(e *Entry) error

Extract finds key-value pairs in the message and sets them as Fields in the entry removing the pairs from the message.

type StdFormatter

type StdFormatter struct {
	Flag        int
	HeaderPlain LevelMap
	HeaderColor LevelMap
	Colors      bool // Force enable colors
	NoColors    bool // Force disable colors (has preference)
	// contains filtered or unexported fields
}

StdFormatter supports plain and color level headers and bold/padded fields

func (*StdFormatter) ColorSupported

func (sf *StdFormatter) ColorSupported(supp bool)

ColorSupported enables or disables the colors, this will be called on every

func (*StdFormatter) Flags

func (sf *StdFormatter) Flags() int

Flags returns the output flags for the formatter.

func (*StdFormatter) Format

func (sf *StdFormatter) Format(e *Entry) ([]byte, error)

Format takes and entry and returns the formatted output in bytes

func (*StdFormatter) SetFlags

func (sf *StdFormatter) SetFlags(flags int)

SetFlags sets the output flags for the formatter.

Jump to

Keyboard shortcuts

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