forked from pingcap/tidb
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
21 changed files
with
1,568 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
The MIT License (MIT) | ||
|
||
Copyright (c) 2014 Simon Eskildsen | ||
|
||
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. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
package logrus | ||
|
||
// The following code was sourced and modified from the | ||
// https://bitbucket.org/tebeka/atexit package governed by the following license: | ||
// | ||
// Copyright (c) 2012 Miki Tebeka <[email protected]>. | ||
// | ||
// 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. | ||
|
||
import ( | ||
"fmt" | ||
"os" | ||
) | ||
|
||
var handlers = []func(){} | ||
|
||
func runHandler(handler func()) { | ||
defer func() { | ||
if err := recover(); err != nil { | ||
fmt.Fprintln(os.Stderr, "Error: Logrus exit handler error:", err) | ||
} | ||
}() | ||
|
||
handler() | ||
} | ||
|
||
func runHandlers() { | ||
for _, handler := range handlers { | ||
runHandler(handler) | ||
} | ||
} | ||
|
||
// Exit runs all the Logrus atexit handlers and then terminates the program using os.Exit(code) | ||
func Exit(code int) { | ||
runHandlers() | ||
os.Exit(code) | ||
} | ||
|
||
// RegisterExitHandler adds a Logrus Exit handler, call logrus.Exit to invoke | ||
// all handlers. The handlers will also be invoked when any Fatal log entry is | ||
// made. | ||
// | ||
// This method is useful when a caller wishes to use logrus to log a fatal | ||
// message but also needs to gracefully shutdown. An example usecase could be | ||
// closing database connections, or sending a alert that the application is | ||
// closing. | ||
func RegisterExitHandler(handler func()) { | ||
handlers = append(handlers, handler) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
/* | ||
Package logrus is a structured logger for Go, completely API compatible with the standard library logger. | ||
The simplest way to use Logrus is simply the package-level exported logger: | ||
package main | ||
import ( | ||
log "github.com/Sirupsen/logrus" | ||
) | ||
func main() { | ||
log.WithFields(log.Fields{ | ||
"animal": "walrus", | ||
"number": 1, | ||
"size": 10, | ||
}).Info("A walrus appears") | ||
} | ||
Output: | ||
time="2015-09-07T08:48:33Z" level=info msg="A walrus appears" animal=walrus number=1 size=10 | ||
For a full guide visit https://github.com/Sirupsen/logrus | ||
*/ | ||
package logrus |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,275 @@ | ||
package logrus | ||
|
||
import ( | ||
"bytes" | ||
"fmt" | ||
"os" | ||
"sync" | ||
"time" | ||
) | ||
|
||
var bufferPool *sync.Pool | ||
|
||
func init() { | ||
bufferPool = &sync.Pool{ | ||
New: func() interface{} { | ||
return new(bytes.Buffer) | ||
}, | ||
} | ||
} | ||
|
||
// Defines the key when adding errors using WithError. | ||
var ErrorKey = "error" | ||
|
||
// An entry is the final or intermediate Logrus logging entry. It contains all | ||
// the fields passed with WithField{,s}. It's finally logged when Debug, Info, | ||
// Warn, Error, Fatal or Panic is called on it. These objects can be reused and | ||
// passed around as much as you wish to avoid field duplication. | ||
type Entry struct { | ||
Logger *Logger | ||
|
||
// Contains all the fields set by the user. | ||
Data Fields | ||
|
||
// Time at which the log entry was created | ||
Time time.Time | ||
|
||
// Level the log entry was logged at: Debug, Info, Warn, Error, Fatal or Panic | ||
Level Level | ||
|
||
// Message passed to Debug, Info, Warn, Error, Fatal or Panic | ||
Message string | ||
|
||
// When formatter is called in entry.log(), an Buffer may be set to entry | ||
Buffer *bytes.Buffer | ||
} | ||
|
||
func NewEntry(logger *Logger) *Entry { | ||
return &Entry{ | ||
Logger: logger, | ||
// Default is three fields, give a little extra room | ||
Data: make(Fields, 5), | ||
} | ||
} | ||
|
||
// Returns the string representation from the reader and ultimately the | ||
// formatter. | ||
func (entry *Entry) String() (string, error) { | ||
serialized, err := entry.Logger.Formatter.Format(entry) | ||
if err != nil { | ||
return "", err | ||
} | ||
str := string(serialized) | ||
return str, nil | ||
} | ||
|
||
// Add an error as single field (using the key defined in ErrorKey) to the Entry. | ||
func (entry *Entry) WithError(err error) *Entry { | ||
return entry.WithField(ErrorKey, err) | ||
} | ||
|
||
// Add a single field to the Entry. | ||
func (entry *Entry) WithField(key string, value interface{}) *Entry { | ||
return entry.WithFields(Fields{key: value}) | ||
} | ||
|
||
// Add a map of fields to the Entry. | ||
func (entry *Entry) WithFields(fields Fields) *Entry { | ||
data := make(Fields, len(entry.Data)+len(fields)) | ||
for k, v := range entry.Data { | ||
data[k] = v | ||
} | ||
for k, v := range fields { | ||
data[k] = v | ||
} | ||
return &Entry{Logger: entry.Logger, Data: data} | ||
} | ||
|
||
// This function is not declared with a pointer value because otherwise | ||
// race conditions will occur when using multiple goroutines | ||
func (entry Entry) log(level Level, msg string) { | ||
var buffer *bytes.Buffer | ||
entry.Time = time.Now() | ||
entry.Level = level | ||
entry.Message = msg | ||
|
||
if err := entry.Logger.Hooks.Fire(level, &entry); err != nil { | ||
entry.Logger.mu.Lock() | ||
fmt.Fprintf(os.Stderr, "Failed to fire hook: %v\n", err) | ||
entry.Logger.mu.Unlock() | ||
} | ||
buffer = bufferPool.Get().(*bytes.Buffer) | ||
buffer.Reset() | ||
defer bufferPool.Put(buffer) | ||
entry.Buffer = buffer | ||
serialized, err := entry.Logger.Formatter.Format(&entry) | ||
entry.Buffer = nil | ||
if err != nil { | ||
entry.Logger.mu.Lock() | ||
fmt.Fprintf(os.Stderr, "Failed to obtain reader, %v\n", err) | ||
entry.Logger.mu.Unlock() | ||
} else { | ||
entry.Logger.mu.Lock() | ||
_, err = entry.Logger.Out.Write(serialized) | ||
if err != nil { | ||
fmt.Fprintf(os.Stderr, "Failed to write to log, %v\n", err) | ||
} | ||
entry.Logger.mu.Unlock() | ||
} | ||
|
||
// To avoid Entry#log() returning a value that only would make sense for | ||
// panic() to use in Entry#Panic(), we avoid the allocation by checking | ||
// directly here. | ||
if level <= PanicLevel { | ||
panic(&entry) | ||
} | ||
} | ||
|
||
func (entry *Entry) Debug(args ...interface{}) { | ||
if entry.Logger.Level >= DebugLevel { | ||
entry.log(DebugLevel, fmt.Sprint(args...)) | ||
} | ||
} | ||
|
||
func (entry *Entry) Print(args ...interface{}) { | ||
entry.Info(args...) | ||
} | ||
|
||
func (entry *Entry) Info(args ...interface{}) { | ||
if entry.Logger.Level >= InfoLevel { | ||
entry.log(InfoLevel, fmt.Sprint(args...)) | ||
} | ||
} | ||
|
||
func (entry *Entry) Warn(args ...interface{}) { | ||
if entry.Logger.Level >= WarnLevel { | ||
entry.log(WarnLevel, fmt.Sprint(args...)) | ||
} | ||
} | ||
|
||
func (entry *Entry) Warning(args ...interface{}) { | ||
entry.Warn(args...) | ||
} | ||
|
||
func (entry *Entry) Error(args ...interface{}) { | ||
if entry.Logger.Level >= ErrorLevel { | ||
entry.log(ErrorLevel, fmt.Sprint(args...)) | ||
} | ||
} | ||
|
||
func (entry *Entry) Fatal(args ...interface{}) { | ||
if entry.Logger.Level >= FatalLevel { | ||
entry.log(FatalLevel, fmt.Sprint(args...)) | ||
} | ||
Exit(1) | ||
} | ||
|
||
func (entry *Entry) Panic(args ...interface{}) { | ||
if entry.Logger.Level >= PanicLevel { | ||
entry.log(PanicLevel, fmt.Sprint(args...)) | ||
} | ||
panic(fmt.Sprint(args...)) | ||
} | ||
|
||
// Entry Printf family functions | ||
|
||
func (entry *Entry) Debugf(format string, args ...interface{}) { | ||
if entry.Logger.Level >= DebugLevel { | ||
entry.Debug(fmt.Sprintf(format, args...)) | ||
} | ||
} | ||
|
||
func (entry *Entry) Infof(format string, args ...interface{}) { | ||
if entry.Logger.Level >= InfoLevel { | ||
entry.Info(fmt.Sprintf(format, args...)) | ||
} | ||
} | ||
|
||
func (entry *Entry) Printf(format string, args ...interface{}) { | ||
entry.Infof(format, args...) | ||
} | ||
|
||
func (entry *Entry) Warnf(format string, args ...interface{}) { | ||
if entry.Logger.Level >= WarnLevel { | ||
entry.Warn(fmt.Sprintf(format, args...)) | ||
} | ||
} | ||
|
||
func (entry *Entry) Warningf(format string, args ...interface{}) { | ||
entry.Warnf(format, args...) | ||
} | ||
|
||
func (entry *Entry) Errorf(format string, args ...interface{}) { | ||
if entry.Logger.Level >= ErrorLevel { | ||
entry.Error(fmt.Sprintf(format, args...)) | ||
} | ||
} | ||
|
||
func (entry *Entry) Fatalf(format string, args ...interface{}) { | ||
if entry.Logger.Level >= FatalLevel { | ||
entry.Fatal(fmt.Sprintf(format, args...)) | ||
} | ||
Exit(1) | ||
} | ||
|
||
func (entry *Entry) Panicf(format string, args ...interface{}) { | ||
if entry.Logger.Level >= PanicLevel { | ||
entry.Panic(fmt.Sprintf(format, args...)) | ||
} | ||
} | ||
|
||
// Entry Println family functions | ||
|
||
func (entry *Entry) Debugln(args ...interface{}) { | ||
if entry.Logger.Level >= DebugLevel { | ||
entry.Debug(entry.sprintlnn(args...)) | ||
} | ||
} | ||
|
||
func (entry *Entry) Infoln(args ...interface{}) { | ||
if entry.Logger.Level >= InfoLevel { | ||
entry.Info(entry.sprintlnn(args...)) | ||
} | ||
} | ||
|
||
func (entry *Entry) Println(args ...interface{}) { | ||
entry.Infoln(args...) | ||
} | ||
|
||
func (entry *Entry) Warnln(args ...interface{}) { | ||
if entry.Logger.Level >= WarnLevel { | ||
entry.Warn(entry.sprintlnn(args...)) | ||
} | ||
} | ||
|
||
func (entry *Entry) Warningln(args ...interface{}) { | ||
entry.Warnln(args...) | ||
} | ||
|
||
func (entry *Entry) Errorln(args ...interface{}) { | ||
if entry.Logger.Level >= ErrorLevel { | ||
entry.Error(entry.sprintlnn(args...)) | ||
} | ||
} | ||
|
||
func (entry *Entry) Fatalln(args ...interface{}) { | ||
if entry.Logger.Level >= FatalLevel { | ||
entry.Fatal(entry.sprintlnn(args...)) | ||
} | ||
Exit(1) | ||
} | ||
|
||
func (entry *Entry) Panicln(args ...interface{}) { | ||
if entry.Logger.Level >= PanicLevel { | ||
entry.Panic(entry.sprintlnn(args...)) | ||
} | ||
} | ||
|
||
// Sprintlnn => Sprint no newline. This is to get the behavior of how | ||
// fmt.Sprintln where spaces are always added between operands, regardless of | ||
// their type. Instead of vendoring the Sprintln implementation to spare a | ||
// string allocation, we do the simplest thing. | ||
func (entry *Entry) sprintlnn(args ...interface{}) string { | ||
msg := fmt.Sprintln(args...) | ||
return msg[:len(msg)-1] | ||
} |
Oops, something went wrong.