github.com/gaukas/goofys100m@v0.24.0/api/common/logger.go (about)

     1  // Copyright 2015 - 2017 Ka-Hing Cheung
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package common
    16  
    17  import (
    18  	"fmt"
    19  	glog "log"
    20  	"log/syslog"
    21  	"os"
    22  	"strings"
    23  	"sync"
    24  
    25  	"github.com/sirupsen/logrus"
    26  	logrus_syslog "github.com/sirupsen/logrus/hooks/syslog"
    27  )
    28  
    29  var mu sync.Mutex
    30  var loggers = make(map[string]*LogHandle)
    31  
    32  var log = GetLogger("main")
    33  var cloudLogLevel = logrus.InfoLevel
    34  
    35  var syslogHook *logrus_syslog.SyslogHook
    36  
    37  func InitLoggers(logToSyslog bool) {
    38  	if logToSyslog {
    39  		var err error
    40  		syslogHook, err = logrus_syslog.NewSyslogHook("", "", syslog.LOG_DEBUG, "")
    41  		if err != nil {
    42  			// we are the child process and we cannot connect to syslog,
    43  			// probably because we are in a container without syslog
    44  			// nothing much we can do here, printing to stderr doesn't work
    45  			return
    46  		}
    47  
    48  		for _, l := range loggers {
    49  			l.Hooks.Add(syslogHook)
    50  		}
    51  	}
    52  }
    53  
    54  func SetCloudLogLevel(level logrus.Level) {
    55  	cloudLogLevel = level
    56  
    57  	for k, logr := range loggers {
    58  		if k != "main" && k != "fuse" {
    59  			logr.Level = level
    60  		}
    61  	}
    62  }
    63  
    64  type LogHandle struct {
    65  	logrus.Logger
    66  
    67  	name string
    68  	Lvl  *logrus.Level
    69  }
    70  
    71  func (l *LogHandle) Format(e *logrus.Entry) ([]byte, error) {
    72  	// Mon Jan 2 15:04:05 -0700 MST 2006
    73  	timestamp := ""
    74  	lvl := e.Level
    75  	if l.Lvl != nil {
    76  		lvl = *l.Lvl
    77  	}
    78  
    79  	if syslogHook == nil {
    80  		const timeFormat = "2006/01/02 15:04:05.000000"
    81  
    82  		timestamp = e.Time.Format(timeFormat) + " "
    83  	}
    84  
    85  	str := fmt.Sprintf("%v%v.%v %v",
    86  		timestamp,
    87  		l.name,
    88  		strings.ToUpper(lvl.String()),
    89  		e.Message)
    90  
    91  	if len(e.Data) != 0 {
    92  		str += " " + fmt.Sprint(e.Data)
    93  	}
    94  
    95  	str += "\n"
    96  	return []byte(str), nil
    97  }
    98  
    99  // for aws.Logger
   100  func (l *LogHandle) Log(args ...interface{}) {
   101  	l.Debugln(args...)
   102  }
   103  
   104  func NewLogger(name string) *LogHandle {
   105  	l := &LogHandle{name: name}
   106  	l.Out = os.Stderr
   107  	l.Formatter = l
   108  	l.Level = logrus.InfoLevel
   109  	l.Hooks = make(logrus.LevelHooks)
   110  	if syslogHook != nil {
   111  		l.Hooks.Add(syslogHook)
   112  	}
   113  	return l
   114  }
   115  
   116  func GetLogger(name string) *LogHandle {
   117  	mu.Lock()
   118  	defer mu.Unlock()
   119  
   120  	if logger, ok := loggers[name]; ok {
   121  		if name != "main" && name != "fuse" {
   122  			logger.Level = cloudLogLevel
   123  		}
   124  		return logger
   125  	} else {
   126  		logger := NewLogger(name)
   127  		loggers[name] = logger
   128  		if name != "main" && name != "fuse" {
   129  			logger.Level = cloudLogLevel
   130  		}
   131  		return logger
   132  	}
   133  }
   134  
   135  func GetStdLogger(l *LogHandle, lvl logrus.Level) *glog.Logger {
   136  	return glog.New(l.WriterLevel(lvl), "", 0)
   137  }
   138  
   139  // retryablehttp logs messages using Printf("[DEBUG|ERR] message")
   140  // logrus.Logger's Printf maps to INFO level, so this logger parses
   141  // the the message to map to the correct log level
   142  
   143  type RetryHTTPLogger struct {
   144  	*LogHandle
   145  }
   146  
   147  const DEBUG_TAG = "[DEBUG]"
   148  const ERR_TAG = "[ERR]"
   149  
   150  func (logger RetryHTTPLogger) Printf(format string, args ...interface{}) {
   151  	// unfortunately logrus.ParseLevel uses "error" instead of "err"
   152  	// so we have to map this ourselves
   153  	if strings.HasPrefix(format, DEBUG_TAG) {
   154  		logger.LogHandle.Debugf(format[len(DEBUG_TAG)+1:], args...)
   155  	} else if strings.HasPrefix(format, ERR_TAG) {
   156  		logger.LogHandle.Errorf(format[len(ERR_TAG)+1:], args...)
   157  	} else {
   158  		logger.LogHandle.Infof(format, args...)
   159  	}
   160  
   161  }