1// Copyright 2015 The Prometheus Authors 2// Licensed under the Apache License, Version 2.0 (the "License"); 3// you may not use this file except in compliance with the License. 4// You may obtain a copy of the License at 5// 6// http://www.apache.org/licenses/LICENSE-2.0 7// 8// Unless required by applicable law or agreed to in writing, software 9// distributed under the License is distributed on an "AS IS" BASIS, 10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11// See the License for the specific language governing permissions and 12// limitations under the License. 13 14// Package log implements logging via logrus. 15// 16// Deprecated: This package has been replaced with github.com/prometheus/common/promlog. 17 18package log 19 20import ( 21 "fmt" 22 "io" 23 "io/ioutil" 24 "log" 25 "net/url" 26 "os" 27 "runtime" 28 "strconv" 29 "strings" 30 31 "github.com/sirupsen/logrus" 32 "gopkg.in/alecthomas/kingpin.v2" 33) 34 35// setSyslogFormatter is nil if the target architecture does not support syslog. 36var setSyslogFormatter func(logger, string, string) error 37 38// setEventlogFormatter is nil if the target OS does not support Eventlog (i.e., is not Windows). 39var setEventlogFormatter func(logger, string, bool) error 40 41func setJSONFormatter() { 42 origLogger.Formatter = &logrus.JSONFormatter{} 43} 44 45type loggerSettings struct { 46 level string 47 format string 48} 49 50func (s *loggerSettings) apply(ctx *kingpin.ParseContext) error { 51 err := baseLogger.SetLevel(s.level) 52 if err != nil { 53 return err 54 } 55 err = baseLogger.SetFormat(s.format) 56 return err 57} 58 59// AddFlags adds the flags used by this package to the Kingpin application. 60// To use the default Kingpin application, call AddFlags(kingpin.CommandLine) 61func AddFlags(a *kingpin.Application) { 62 s := loggerSettings{} 63 a.Flag("log.level", "Only log messages with the given severity or above. Valid levels: [debug, info, warn, error, fatal]"). 64 Default(origLogger.Level.String()). 65 StringVar(&s.level) 66 defaultFormat := url.URL{Scheme: "logger", Opaque: "stderr"} 67 a.Flag("log.format", `Set the log target and format. Example: "logger:syslog?appname=bob&local=7" or "logger:stdout?json=true"`). 68 Default(defaultFormat.String()). 69 StringVar(&s.format) 70 a.Action(s.apply) 71} 72 73// Logger is the interface for loggers used in the Prometheus components. 74type Logger interface { 75 Debug(...interface{}) 76 Debugln(...interface{}) 77 Debugf(string, ...interface{}) 78 79 Info(...interface{}) 80 Infoln(...interface{}) 81 Infof(string, ...interface{}) 82 83 Warn(...interface{}) 84 Warnln(...interface{}) 85 Warnf(string, ...interface{}) 86 87 Error(...interface{}) 88 Errorln(...interface{}) 89 Errorf(string, ...interface{}) 90 91 Fatal(...interface{}) 92 Fatalln(...interface{}) 93 Fatalf(string, ...interface{}) 94 95 With(key string, value interface{}) Logger 96 97 SetFormat(string) error 98 SetLevel(string) error 99} 100 101type logger struct { 102 entry *logrus.Entry 103} 104 105func (l logger) With(key string, value interface{}) Logger { 106 return logger{l.entry.WithField(key, value)} 107} 108 109// Debug logs a message at level Debug on the standard logger. 110func (l logger) Debug(args ...interface{}) { 111 l.sourced().Debug(args...) 112} 113 114// Debug logs a message at level Debug on the standard logger. 115func (l logger) Debugln(args ...interface{}) { 116 l.sourced().Debugln(args...) 117} 118 119// Debugf logs a message at level Debug on the standard logger. 120func (l logger) Debugf(format string, args ...interface{}) { 121 l.sourced().Debugf(format, args...) 122} 123 124// Info logs a message at level Info on the standard logger. 125func (l logger) Info(args ...interface{}) { 126 l.sourced().Info(args...) 127} 128 129// Info logs a message at level Info on the standard logger. 130func (l logger) Infoln(args ...interface{}) { 131 l.sourced().Infoln(args...) 132} 133 134// Infof logs a message at level Info on the standard logger. 135func (l logger) Infof(format string, args ...interface{}) { 136 l.sourced().Infof(format, args...) 137} 138 139// Warn logs a message at level Warn on the standard logger. 140func (l logger) Warn(args ...interface{}) { 141 l.sourced().Warn(args...) 142} 143 144// Warn logs a message at level Warn on the standard logger. 145func (l logger) Warnln(args ...interface{}) { 146 l.sourced().Warnln(args...) 147} 148 149// Warnf logs a message at level Warn on the standard logger. 150func (l logger) Warnf(format string, args ...interface{}) { 151 l.sourced().Warnf(format, args...) 152} 153 154// Error logs a message at level Error on the standard logger. 155func (l logger) Error(args ...interface{}) { 156 l.sourced().Error(args...) 157} 158 159// Error logs a message at level Error on the standard logger. 160func (l logger) Errorln(args ...interface{}) { 161 l.sourced().Errorln(args...) 162} 163 164// Errorf logs a message at level Error on the standard logger. 165func (l logger) Errorf(format string, args ...interface{}) { 166 l.sourced().Errorf(format, args...) 167} 168 169// Fatal logs a message at level Fatal on the standard logger. 170func (l logger) Fatal(args ...interface{}) { 171 l.sourced().Fatal(args...) 172} 173 174// Fatal logs a message at level Fatal on the standard logger. 175func (l logger) Fatalln(args ...interface{}) { 176 l.sourced().Fatalln(args...) 177} 178 179// Fatalf logs a message at level Fatal on the standard logger. 180func (l logger) Fatalf(format string, args ...interface{}) { 181 l.sourced().Fatalf(format, args...) 182} 183 184func (l logger) SetLevel(level string) error { 185 lvl, err := logrus.ParseLevel(level) 186 if err != nil { 187 return err 188 } 189 190 l.entry.Logger.Level = lvl 191 return nil 192} 193 194func (l logger) SetFormat(format string) error { 195 u, err := url.Parse(format) 196 if err != nil { 197 return err 198 } 199 if u.Scheme != "logger" { 200 return fmt.Errorf("invalid scheme %s", u.Scheme) 201 } 202 jsonq := u.Query().Get("json") 203 if jsonq == "true" { 204 setJSONFormatter() 205 } 206 207 switch u.Opaque { 208 case "syslog": 209 if setSyslogFormatter == nil { 210 return fmt.Errorf("system does not support syslog") 211 } 212 appname := u.Query().Get("appname") 213 facility := u.Query().Get("local") 214 return setSyslogFormatter(l, appname, facility) 215 case "eventlog": 216 if setEventlogFormatter == nil { 217 return fmt.Errorf("system does not support eventlog") 218 } 219 name := u.Query().Get("name") 220 debugAsInfo := false 221 debugAsInfoRaw := u.Query().Get("debugAsInfo") 222 if parsedDebugAsInfo, err := strconv.ParseBool(debugAsInfoRaw); err == nil { 223 debugAsInfo = parsedDebugAsInfo 224 } 225 return setEventlogFormatter(l, name, debugAsInfo) 226 case "stdout": 227 l.entry.Logger.Out = os.Stdout 228 case "stderr": 229 l.entry.Logger.Out = os.Stderr 230 default: 231 return fmt.Errorf("unsupported logger %q", u.Opaque) 232 } 233 return nil 234} 235 236// sourced adds a source field to the logger that contains 237// the file name and line where the logging happened. 238func (l logger) sourced() *logrus.Entry { 239 _, file, line, ok := runtime.Caller(2) 240 if !ok { 241 file = "<???>" 242 line = 1 243 } else { 244 slash := strings.LastIndex(file, "/") 245 file = file[slash+1:] 246 } 247 return l.entry.WithField("source", fmt.Sprintf("%s:%d", file, line)) 248} 249 250var origLogger = logrus.New() 251var baseLogger = logger{entry: logrus.NewEntry(origLogger)} 252 253// Base returns the default Logger logging to 254func Base() Logger { 255 return baseLogger 256} 257 258// NewLogger returns a new Logger logging to out. 259func NewLogger(w io.Writer) Logger { 260 l := logrus.New() 261 l.Out = w 262 return logger{entry: logrus.NewEntry(l)} 263} 264 265// NewNopLogger returns a logger that discards all log messages. 266func NewNopLogger() Logger { 267 l := logrus.New() 268 l.Out = ioutil.Discard 269 return logger{entry: logrus.NewEntry(l)} 270} 271 272// With adds a field to the logger. 273func With(key string, value interface{}) Logger { 274 return baseLogger.With(key, value) 275} 276 277// Debug logs a message at level Debug on the standard logger. 278func Debug(args ...interface{}) { 279 baseLogger.sourced().Debug(args...) 280} 281 282// Debugln logs a message at level Debug on the standard logger. 283func Debugln(args ...interface{}) { 284 baseLogger.sourced().Debugln(args...) 285} 286 287// Debugf logs a message at level Debug on the standard logger. 288func Debugf(format string, args ...interface{}) { 289 baseLogger.sourced().Debugf(format, args...) 290} 291 292// Info logs a message at level Info on the standard logger. 293func Info(args ...interface{}) { 294 baseLogger.sourced().Info(args...) 295} 296 297// Infoln logs a message at level Info on the standard logger. 298func Infoln(args ...interface{}) { 299 baseLogger.sourced().Infoln(args...) 300} 301 302// Infof logs a message at level Info on the standard logger. 303func Infof(format string, args ...interface{}) { 304 baseLogger.sourced().Infof(format, args...) 305} 306 307// Warn logs a message at level Warn on the standard logger. 308func Warn(args ...interface{}) { 309 baseLogger.sourced().Warn(args...) 310} 311 312// Warnln logs a message at level Warn on the standard logger. 313func Warnln(args ...interface{}) { 314 baseLogger.sourced().Warnln(args...) 315} 316 317// Warnf logs a message at level Warn on the standard logger. 318func Warnf(format string, args ...interface{}) { 319 baseLogger.sourced().Warnf(format, args...) 320} 321 322// Error logs a message at level Error on the standard logger. 323func Error(args ...interface{}) { 324 baseLogger.sourced().Error(args...) 325} 326 327// Errorln logs a message at level Error on the standard logger. 328func Errorln(args ...interface{}) { 329 baseLogger.sourced().Errorln(args...) 330} 331 332// Errorf logs a message at level Error on the standard logger. 333func Errorf(format string, args ...interface{}) { 334 baseLogger.sourced().Errorf(format, args...) 335} 336 337// Fatal logs a message at level Fatal on the standard logger. 338func Fatal(args ...interface{}) { 339 baseLogger.sourced().Fatal(args...) 340} 341 342// Fatalln logs a message at level Fatal on the standard logger. 343func Fatalln(args ...interface{}) { 344 baseLogger.sourced().Fatalln(args...) 345} 346 347// Fatalf logs a message at level Fatal on the standard logger. 348func Fatalf(format string, args ...interface{}) { 349 baseLogger.sourced().Fatalf(format, args...) 350} 351 352// AddHook adds hook to Prometheus' original logger. 353func AddHook(hook logrus.Hook) { 354 origLogger.Hooks.Add(hook) 355} 356 357type errorLogWriter struct{} 358 359func (errorLogWriter) Write(b []byte) (int, error) { 360 baseLogger.sourced().Error(string(b)) 361 return len(b), nil 362} 363 364// NewErrorLogger returns a log.Logger that is meant to be used 365// in the ErrorLog field of an http.Server to log HTTP server errors. 366func NewErrorLogger() *log.Logger { 367 return log.New(&errorLogWriter{}, "", 0) 368} 369