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.
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
SetHeadersandAddHeader - Control levels used via
SetMinLevelandSetDefaultLevel - Supports optionally parsing key=value or key='some value' pairs
- Supports custom key-value extractor via
SetExtractor - Supports permanent context values via
FixedValueandClearFixedValues - Supports standalone loggers via
NewCoLogandNewLogger - 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"}}%

