2016-09-23 19:27:01 +03:00
package log
import (
2017-07-08 00:46:15 +03:00
"bufio"
2017-08-11 13:04:58 +03:00
"fmt"
2016-09-23 19:27:01 +03:00
"io"
2017-08-11 13:04:58 +03:00
"os"
2017-07-08 00:46:15 +03:00
"runtime"
2016-12-30 11:21:13 +03:00
2018-01-22 14:16:03 +03:00
"github.com/sirupsen/logrus"
2016-09-23 19:27:01 +03:00
)
2018-09-14 14:34:03 +03:00
// Logger allows overriding the logrus logger behavior
type Logger interface {
logrus . FieldLogger
WriterLevel ( logrus . Level ) * io . PipeWriter
}
2016-09-23 19:27:01 +03:00
var (
2018-09-14 14:34:03 +03:00
logger Logger
2017-08-11 13:04:58 +03:00
logFilePath string
logFile * os . File
2016-09-23 19:27:01 +03:00
)
func init ( ) {
logger = logrus . StandardLogger ( ) . WithFields ( logrus . Fields { } )
2017-09-06 12:58:03 +03:00
logrus . SetOutput ( os . Stdout )
2016-09-23 19:27:01 +03:00
}
// Context sets the Context of the logger
func Context ( context interface { } ) * logrus . Entry {
return logger . WithField ( "context" , context )
}
// SetOutput sets the standard logger output.
func SetOutput ( out io . Writer ) {
logrus . SetOutput ( out )
}
// SetFormatter sets the standard logger formatter.
func SetFormatter ( formatter logrus . Formatter ) {
logrus . SetFormatter ( formatter )
}
// SetLevel sets the standard logger level.
func SetLevel ( level logrus . Level ) {
logrus . SetLevel ( level )
}
2018-09-14 14:34:03 +03:00
// SetLogger sets the logger.
func SetLogger ( l Logger ) {
logger = l
}
2016-09-23 19:27:01 +03:00
// GetLevel returns the standard logger level.
func GetLevel ( ) logrus . Level {
return logrus . GetLevel ( )
}
// AddHook adds a hook to the standard logger hooks.
func AddHook ( hook logrus . Hook ) {
logrus . AddHook ( hook )
}
// WithError creates an entry from the standard logger and adds an error to it, using the value defined in ErrorKey as key.
func WithError ( err error ) * logrus . Entry {
return logger . WithError ( err )
}
// WithField creates an entry from the standard logger and adds a field to
// it. If you want multiple fields, use `WithFields`.
//
// Note that it doesn't log until you call Debug, Print, Info, Warn, Fatal
// or Panic on the Entry it returns.
func WithField ( key string , value interface { } ) * logrus . Entry {
return logger . WithField ( key , value )
}
// WithFields creates an entry from the standard logger and adds multiple
// fields to it. This is simply a helper for `WithField`, invoking it
// once for each field.
//
// Note that it doesn't log until you call Debug, Print, Info, Warn, Fatal
// or Panic on the Entry it returns.
func WithFields ( fields logrus . Fields ) * logrus . Entry {
return logger . WithFields ( fields )
}
// Debug logs a message at level Debug on the standard logger.
func Debug ( args ... interface { } ) {
logger . Debug ( args ... )
}
// Print logs a message at level Info on the standard logger.
func Print ( args ... interface { } ) {
logger . Print ( args ... )
}
// Info logs a message at level Info on the standard logger.
func Info ( args ... interface { } ) {
logger . Info ( args ... )
}
// Warn logs a message at level Warn on the standard logger.
func Warn ( args ... interface { } ) {
logger . Warn ( args ... )
}
// Warning logs a message at level Warn on the standard logger.
func Warning ( args ... interface { } ) {
logger . Warning ( args ... )
}
// Error logs a message at level Error on the standard logger.
func Error ( args ... interface { } ) {
logger . Error ( args ... )
}
// Panic logs a message at level Panic on the standard logger.
func Panic ( args ... interface { } ) {
logger . Panic ( args ... )
}
// Fatal logs a message at level Fatal on the standard logger.
func Fatal ( args ... interface { } ) {
logger . Fatal ( args ... )
}
// Debugf logs a message at level Debug on the standard logger.
func Debugf ( format string , args ... interface { } ) {
logger . Debugf ( format , args ... )
}
// Printf logs a message at level Info on the standard logger.
func Printf ( format string , args ... interface { } ) {
logger . Printf ( format , args ... )
}
// Infof logs a message at level Info on the standard logger.
func Infof ( format string , args ... interface { } ) {
logger . Infof ( format , args ... )
}
// Warnf logs a message at level Warn on the standard logger.
func Warnf ( format string , args ... interface { } ) {
logger . Warnf ( format , args ... )
}
// Warningf logs a message at level Warn on the standard logger.
func Warningf ( format string , args ... interface { } ) {
logger . Warningf ( format , args ... )
}
// Errorf logs a message at level Error on the standard logger.
func Errorf ( format string , args ... interface { } ) {
logger . Errorf ( format , args ... )
}
// Panicf logs a message at level Panic on the standard logger.
func Panicf ( format string , args ... interface { } ) {
logger . Panicf ( format , args ... )
}
// Fatalf logs a message at level Fatal on the standard logger.
func Fatalf ( format string , args ... interface { } ) {
logger . Fatalf ( format , args ... )
}
// Debugln logs a message at level Debug on the standard logger.
func Debugln ( args ... interface { } ) {
logger . Debugln ( args ... )
}
// Println logs a message at level Info on the standard logger.
func Println ( args ... interface { } ) {
logger . Println ( args ... )
}
// Infoln logs a message at level Info on the standard logger.
func Infoln ( args ... interface { } ) {
logger . Infoln ( args ... )
}
// Warnln logs a message at level Warn on the standard logger.
func Warnln ( args ... interface { } ) {
logger . Warnln ( args ... )
}
// Warningln logs a message at level Warn on the standard logger.
func Warningln ( args ... interface { } ) {
logger . Warningln ( args ... )
}
// Errorln logs a message at level Error on the standard logger.
func Errorln ( args ... interface { } ) {
logger . Errorln ( args ... )
}
// Panicln logs a message at level Panic on the standard logger.
func Panicln ( args ... interface { } ) {
logger . Panicln ( args ... )
}
// Fatalln logs a message at level Fatal on the standard logger.
func Fatalln ( args ... interface { } ) {
logger . Fatalln ( args ... )
}
2017-07-08 00:46:15 +03:00
2017-08-11 13:04:58 +03:00
// OpenFile opens the log file using the specified path
func OpenFile ( path string ) error {
logFilePath = path
var err error
logFile , err = os . OpenFile ( logFilePath , os . O_RDWR | os . O_CREATE | os . O_APPEND , 0666 )
if err == nil {
SetOutput ( logFile )
}
return err
}
// CloseFile closes the log and sets the Output to stdout
func CloseFile ( ) error {
logrus . SetOutput ( os . Stdout )
if logFile != nil {
return logFile . Close ( )
}
return nil
}
// RotateFile closes and reopens the log file to allow for rotation
// by an external source. If the log isn't backed by a file then
// it does nothing.
func RotateFile ( ) error {
if logFile == nil && logFilePath == "" {
Debug ( "Traefik log is not writing to a file, ignoring rotate request" )
return nil
}
2017-09-15 16:02:03 +03:00
if logFile != nil {
defer func ( f * os . File ) {
f . Close ( )
} ( logFile )
2017-08-11 13:04:58 +03:00
}
if err := OpenFile ( logFilePath ) ; err != nil {
return fmt . Errorf ( "error opening log file: %s" , err )
}
return nil
}
2017-07-08 00:46:15 +03:00
// Writer logs writer (Level Info)
func Writer ( ) * io . PipeWriter {
return WriterLevel ( logrus . InfoLevel )
}
// WriterLevel logs writer for a specific level.
func WriterLevel ( level logrus . Level ) * io . PipeWriter {
return logger . WriterLevel ( level )
}
// CustomWriterLevel logs writer for a specific level. (with a custom scanner buffer size.)
// adapted from github.com/Sirupsen/logrus/writer.go
func CustomWriterLevel ( level logrus . Level , maxScanTokenSize int ) * io . PipeWriter {
reader , writer := io . Pipe ( )
var printFunc func ( args ... interface { } )
switch level {
case logrus . DebugLevel :
printFunc = Debug
case logrus . InfoLevel :
printFunc = Info
case logrus . WarnLevel :
printFunc = Warn
case logrus . ErrorLevel :
printFunc = Error
case logrus . FatalLevel :
printFunc = Fatal
case logrus . PanicLevel :
printFunc = Panic
default :
printFunc = Print
}
go writerScanner ( reader , maxScanTokenSize , printFunc )
runtime . SetFinalizer ( writer , writerFinalizer )
return writer
}
// extract from github.com/Sirupsen/logrus/writer.go
// Hack the buffer size
2018-02-19 03:04:45 +03:00
func writerScanner ( reader io . ReadCloser , scanTokenSize int , printFunc func ( args ... interface { } ) ) {
2017-07-08 00:46:15 +03:00
scanner := bufio . NewScanner ( reader )
if scanTokenSize > bufio . MaxScanTokenSize {
buf := make ( [ ] byte , bufio . MaxScanTokenSize )
scanner . Buffer ( buf , scanTokenSize )
}
for scanner . Scan ( ) {
printFunc ( scanner . Text ( ) )
}
if err := scanner . Err ( ) ; err != nil {
Errorf ( "Error while reading from Writer: %s" , err )
}
reader . Close ( )
}
func writerFinalizer ( writer * io . PipeWriter ) {
writer . Close ( )
}