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 }