pax_global_header00006660000000000000000000000064131400176740014515gustar00rootroot0000000000000052 comment=75edb2e85a38873f0318be05a458446681d1022f golang-github-kotakanbe-logrus-prefixed-formatter-0.0~git20170801.0.75edb2e8/000077500000000000000000000000001314001767400262655ustar00rootroot00000000000000golang-github-kotakanbe-logrus-prefixed-formatter-0.0~git20170801.0.75edb2e8/.gitignore000066400000000000000000000004751314001767400302630ustar00rootroot00000000000000# Compiled Object files, Static and Dynamic libs (Shared Objects) *.o *.a *.so # Folders _obj _test # Architecture specific extensions/prefixes *.[568vq] [568vq].out *.cgo1.go *.cgo2.c _cgo_defun.c _cgo_gotypes.go _cgo_export.* _testmain.go *.exe *.test *.prof # IDEA files .idea *.iml # OS X .DS_Store vendor golang-github-kotakanbe-logrus-prefixed-formatter-0.0~git20170801.0.75edb2e8/Gopkg.lock000066400000000000000000000022151314001767400302060ustar00rootroot00000000000000# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. [[projects]] name = "github.com/mattn/go-colorable" packages = ["."] revision = "941b50ebc6efddf4c41c8e4537a5f68a4e686b24" version = "v0.0.8" [[projects]] name = "github.com/mattn/go-isatty" packages = ["."] revision = "fc9e8d8ef48496124e79ae0df75490096eccf6fe" version = "v0.0.2" [[projects]] branch = "master" name = "github.com/mgutz/ansi" packages = ["."] revision = "9520e82c474b0a04dd04f8a40959027271bab992" [[projects]] branch = "master" name = "github.com/sirupsen/logrus" packages = ["."] revision = "181d419aa9e2223811b824e8f0b4af96f9ba9302" [[projects]] branch = "master" name = "golang.org/x/crypto" packages = ["ssh/terminal"] revision = "558b6879de74bc843225cde5686419267ff707ca" [[projects]] branch = "master" name = "golang.org/x/sys" packages = ["unix"] revision = "0f826bdd13b500be0f1d4004938ad978fcc6031e" [solve-meta] analyzer-name = "dep" analyzer-version = 1 inputs-digest = "8093add19cc460ff2fe3a86458257841e386bf2474b9c215fe64459a73d66622" solver-name = "gps-cdcl" solver-version = 1 golang-github-kotakanbe-logrus-prefixed-formatter-0.0~git20170801.0.75edb2e8/Gopkg.toml000066400000000000000000000003211314001767400302250ustar00rootroot00000000000000[[constraint]] branch = "master" name = "github.com/mgutz/ansi" [[constraint]] branch = "master" name = "github.com/sirupsen/logrus" [[constraint]] branch = "master" name = "golang.org/x/crypto" golang-github-kotakanbe-logrus-prefixed-formatter-0.0~git20170801.0.75edb2e8/LICENSE000066400000000000000000000020721314001767400272730ustar00rootroot00000000000000The MIT License (MIT) Copyright (c) 2015 Denis Parchenko Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. golang-github-kotakanbe-logrus-prefixed-formatter-0.0~git20170801.0.75edb2e8/README.md000066400000000000000000000046421314001767400275520ustar00rootroot00000000000000# Logrus Prefixed Log Formatter [Logrus](https://github.com/Sirupsen/logrus) formatter mainly based on original `logrus.TextFormatter` but with slightly modified colored output and support for log entry prefixes, e.g. message source followed by a colon. ![Formatter screenshot](http://cl.ly/image/1w0B3F233F3z/formatter-screenshot@2x.png) Just like with the original `logrus.TextFormatter` when a TTY is not attached, the output is compatible with the [logfmt](http://godoc.org/github.com/kr/logfmt) format: ```text time="Oct 27 00:44:26" level=debug msg="Started observing beach" animal=walrus number=8 time="Oct 27 00:44:26" level=info msg="A group of walrus emerges from the ocean" animal=walrus size=10 time="Oct 27 00:44:26" level=warning msg="The group's number increased tremendously!" number=122 omg=true time="Oct 27 00:44:26" level=debug msg="Temperature changes" temperature=-4 time="Oct 27 00:44:26" level=panic msg="It's over 9000!" animal=orca size=9009 time="Oct 27 00:44:26" level=fatal msg="The ice breaks!" number=100 omg=true exit status 1 ``` ## Installation To install formatter, use `go get`: ```sh $ go get github.com/x-cray/logrus-prefixed-formatter ``` ## Usage Here is how it should be used: ```go package main import ( "github.com/Sirupsen/logrus" prefixed "github.com/x-cray/logrus-prefixed-formatter" ) var log = logrus.New() func init() { log.Formatter = new(prefixed.TextFormatter) log.Level = logrus.DebugLevel } func main() { log.WithFields(logrus.Fields{ "prefix": "main", "animal": "walrus", "number": 8, }).Debug("Started observing beach") log.WithFields(logrus.Fields{ "prefix": "sensor", "temperature": -4, }).Info("Temperature changes") } ``` ## API `prefixed.TextFormatter` exposes the following fields: * `ForceColors bool` — set to true to bypass checking for a TTY before outputting colors. * `DisableColors bool` — force disabling colors. * `DisableTimestamp bool` — disable timestamp logging. useful when output is redirected to logging system that already adds timestamps. * `ShortTimestamp bool` — enable logging of just the time passed since beginning of execution. * `TimestampFormat string` — timestamp format to use for display when a full timestamp is printed. * `DisableSorting bool` — the fields are sorted by default for a consistent output. For applications that log extremely frequently and don't use the JSON formatter this may not be desired. # License MIT golang-github-kotakanbe-logrus-prefixed-formatter-0.0~git20170801.0.75edb2e8/examples/000077500000000000000000000000001314001767400301035ustar00rootroot00000000000000golang-github-kotakanbe-logrus-prefixed-formatter-0.0~git20170801.0.75edb2e8/examples/basic.go000066400000000000000000000020701314001767400315120ustar00rootroot00000000000000package main import ( prefixed "github.com/kotakanbe/logrus-prefixed-formatter" "github.com/sirupsen/logrus" ) var log = logrus.New() func init() { log.Formatter = new(prefixed.TextFormatter) log.Level = logrus.DebugLevel } func main() { defer func() { err := recover() if err != nil { log.WithFields(logrus.Fields{ "prefix": "main", "omg": true, "number": 100, }).Fatal("The ice breaks!") } }() log.WithFields(logrus.Fields{ "prefix": "main", "animal": "walrus", "number": 8, }).Debug("Started observing beach") log.WithFields(logrus.Fields{ "prefix": "main", "animal": "walrus", "size": 10, }).Info("A group of walrus emerges from the ocean") log.WithFields(logrus.Fields{ "prefix": "main", "omg": true, "number": 122, }).Warn("The group's number increased tremendously!") log.WithFields(logrus.Fields{ "prefix": "sensor", "temperature": -4, }).Debug("Temperature changes") log.WithFields(logrus.Fields{ "prefix": "sensor", "animal": "orca", "size": 9009, }).Panic("It's over 9000!") } golang-github-kotakanbe-logrus-prefixed-formatter-0.0~git20170801.0.75edb2e8/formatter.go000066400000000000000000000112141314001767400306160ustar00rootroot00000000000000package prefixed import ( "bytes" "fmt" "io" "os" "runtime" "sort" "strings" "sync" "time" "golang.org/x/crypto/ssh/terminal" "github.com/mgutz/ansi" "github.com/sirupsen/logrus" ) const reset = ansi.Reset var ( baseTimestamp time.Time ) func init() { baseTimestamp = time.Now() } func miniTS() int { return int(time.Since(baseTimestamp) / time.Second) } // TextFormatter .. type TextFormatter struct { // Set to true to bypass checking for a TTY before outputting colors. ForceColors bool // Force disabling colors. DisableColors bool // Disable timestamp logging. useful when output is redirected to logging // system that already adds timestamps. DisableTimestamp bool // Enable logging of just the time passed since beginning of execution. ShortTimestamp bool // Timestamp format to use for display when a full timestamp is printed. TimestampFormat string // The fields are sorted by default for a consistent output. For applications // that log extremely frequently and don't use the JSON formatter this may not // be desired. DisableSorting bool // Message MsgAnsiColor string isTerminal bool terminalOnce sync.Once } func (f *TextFormatter) checkIfTerminal(w io.Writer) bool { switch v := w.(type) { case *os.File: return terminal.IsTerminal(int(v.Fd())) default: return false } } // Format .. func (f *TextFormatter) Format(entry *logrus.Entry) ([]byte, error) { var keys = make([]string, 0, len(entry.Data)) for k := range entry.Data { if k != "prefix" { keys = append(keys, k) } } if !f.DisableSorting { sort.Strings(keys) } b := &bytes.Buffer{} prefixFieldClashes(entry.Data) f.terminalOnce.Do(func() { if entry.Logger != nil { f.isTerminal = f.checkIfTerminal(entry.Logger.Out) } }) isColorTerminal := f.isTerminal && (runtime.GOOS != "windows") isColored := (f.ForceColors || isColorTerminal) && !f.DisableColors timestampFormat := f.TimestampFormat if timestampFormat == "" { timestampFormat = time.Stamp } if isColored { f.printColored(b, entry, keys, timestampFormat) } else { if !f.DisableTimestamp { f.appendKeyValue(b, "time", entry.Time.Format(timestampFormat)) } f.appendKeyValue(b, "level", entry.Level.String()) if entry.Message != "" { f.appendKeyValue(b, "msg", entry.Message) } for _, key := range keys { f.appendKeyValue(b, key, entry.Data[key]) } } b.WriteByte('\n') return b.Bytes(), nil } func (f *TextFormatter) printColored(b *bytes.Buffer, entry *logrus.Entry, keys []string, timestampFormat string) { var levelColor string var levelText string switch entry.Level { case logrus.InfoLevel: levelColor = ansi.Green case logrus.WarnLevel: levelColor = ansi.Yellow case logrus.ErrorLevel, logrus.FatalLevel, logrus.PanicLevel: levelColor = ansi.Red default: levelColor = ansi.Blue } if entry.Level != logrus.WarnLevel { levelText = strings.ToUpper(entry.Level.String()) } else { levelText = "WARN" } if len(f.MsgAnsiColor) == 0 { f.MsgAnsiColor = ansi.DefaultFG } prefix := "" prefixValue, ok := entry.Data["prefix"] str, _ := prefixValue.(string) if ok && 0 < len(str) { // prefix = fmt.Sprint(" ", ansi.Cyan, prefixValue, reset) prefix = fmt.Sprint(f.MsgAnsiColor, " [", prefixValue, "]", reset) } if f.ShortTimestamp { fmt.Fprintf(b, "%s[%04d]%s %s%+5s%s%s %s%s%s", ansi.LightBlack, miniTS(), reset, levelColor, levelText, reset, prefix, f.MsgAnsiColor, entry.Message, reset) } else { fmt.Fprintf(b, "%s[%s]%s %s%+5s%s%s %s%s%s", ansi.LightBlack, entry.Time.Format(timestampFormat), reset, levelColor, levelText, reset, prefix, f.MsgAnsiColor, entry.Message, reset) } for _, k := range keys { v := entry.Data[k] fmt.Fprintf(b, " %s%s%s=%+v", levelColor, k, reset, v) } } func needsQuoting(text string) bool { for _, ch := range text { if !((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9') || ch == '-' || ch == '.') { return false } } return true } func (f *TextFormatter) appendKeyValue(b *bytes.Buffer, key string, value interface{}) { b.WriteString(key) b.WriteByte('=') switch value := value.(type) { case string: if needsQuoting(value) { b.WriteString(value) } else { fmt.Fprintf(b, "%q", value) } case error: errmsg := value.Error() if needsQuoting(errmsg) { b.WriteString(errmsg) } else { fmt.Fprintf(b, "%q", value) } default: fmt.Fprint(b, value) } b.WriteByte(' ') } func prefixFieldClashes(data logrus.Fields) { _, ok := data["time"] if ok { data["fields.time"] = data["time"] } _, ok = data["msg"] if ok { data["fields.msg"] = data["msg"] } _, ok = data["level"] if ok { data["fields.level"] = data["level"] } }