2018-11-14 09:18:03 +00:00
|
|
|
package log
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"fmt"
|
|
|
|
"io"
|
|
|
|
"os"
|
|
|
|
|
|
|
|
"github.com/sirupsen/logrus"
|
|
|
|
)
|
|
|
|
|
|
|
|
type contextKey int
|
|
|
|
|
|
|
|
const (
|
|
|
|
loggerKey contextKey = iota
|
|
|
|
)
|
|
|
|
|
2020-05-11 10:06:07 +00:00
|
|
|
// Logger the Traefik logger.
|
2018-11-14 09:18:03 +00:00
|
|
|
type Logger interface {
|
|
|
|
logrus.FieldLogger
|
|
|
|
WriterLevel(logrus.Level) *io.PipeWriter
|
|
|
|
}
|
|
|
|
|
|
|
|
var (
|
|
|
|
mainLogger Logger
|
|
|
|
logFilePath string
|
|
|
|
logFile *os.File
|
|
|
|
)
|
|
|
|
|
|
|
|
func init() {
|
|
|
|
mainLogger = logrus.StandardLogger()
|
|
|
|
logrus.SetOutput(os.Stdout)
|
|
|
|
}
|
|
|
|
|
|
|
|
// SetLogger sets the logger.
|
|
|
|
func SetLogger(l Logger) {
|
|
|
|
mainLogger = l
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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)
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetLevel returns the standard logger level.
|
|
|
|
func GetLevel() logrus.Level {
|
|
|
|
return logrus.GetLevel()
|
|
|
|
}
|
|
|
|
|
2020-05-11 10:06:07 +00:00
|
|
|
// Str adds a string field.
|
2018-11-14 09:18:03 +00:00
|
|
|
func Str(key, value string) func(logrus.Fields) {
|
|
|
|
return func(fields logrus.Fields) {
|
|
|
|
fields[key] = value
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-11 10:06:07 +00:00
|
|
|
// With Adds fields.
|
2018-11-14 09:18:03 +00:00
|
|
|
func With(ctx context.Context, opts ...func(logrus.Fields)) context.Context {
|
|
|
|
logger := FromContext(ctx)
|
|
|
|
|
|
|
|
fields := make(logrus.Fields)
|
|
|
|
for _, opt := range opts {
|
|
|
|
opt(fields)
|
|
|
|
}
|
|
|
|
logger = logger.WithFields(fields)
|
|
|
|
|
|
|
|
return context.WithValue(ctx, loggerKey, logger)
|
|
|
|
}
|
|
|
|
|
2020-05-11 10:06:07 +00:00
|
|
|
// FromContext Gets the logger from context.
|
2018-11-14 09:18:03 +00:00
|
|
|
func FromContext(ctx context.Context) Logger {
|
|
|
|
if ctx == nil {
|
|
|
|
panic("nil context")
|
|
|
|
}
|
|
|
|
|
|
|
|
logger, ok := ctx.Value(loggerKey).(Logger)
|
|
|
|
if !ok {
|
|
|
|
logger = mainLogger
|
|
|
|
}
|
|
|
|
|
|
|
|
return logger
|
|
|
|
}
|
|
|
|
|
2020-05-11 10:06:07 +00:00
|
|
|
// WithoutContext Gets the main logger.
|
2018-11-14 09:18:03 +00:00
|
|
|
func WithoutContext() Logger {
|
|
|
|
return mainLogger
|
|
|
|
}
|
|
|
|
|
2020-05-11 10:06:07 +00:00
|
|
|
// OpenFile opens the log file using the specified path.
|
2018-11-14 09:18:03 +00:00
|
|
|
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 {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
SetOutput(logFile)
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2020-05-11 10:06:07 +00:00
|
|
|
// CloseFile closes the log and sets the Output to stdout.
|
2018-11-14 09:18:03 +00:00
|
|
|
func CloseFile() error {
|
|
|
|
logrus.SetOutput(os.Stdout)
|
|
|
|
|
|
|
|
if logFile != nil {
|
|
|
|
return logFile.Close()
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2020-05-11 10:06:07 +00:00
|
|
|
// 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.
|
2018-11-14 09:18:03 +00:00
|
|
|
func RotateFile() error {
|
|
|
|
logger := FromContext(context.Background())
|
|
|
|
|
|
|
|
if logFile == nil && logFilePath == "" {
|
|
|
|
logger.Debug("Traefik log is not writing to a file, ignoring rotate request")
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
if logFile != nil {
|
|
|
|
defer func(f *os.File) {
|
|
|
|
_ = f.Close()
|
|
|
|
}(logFile)
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := OpenFile(logFilePath); err != nil {
|
|
|
|
return fmt.Errorf("error opening log file: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|