github.com/rigado/snapd@v2.42.5-go-mod+incompatible/logger/logger.go (about) 1 // -*- Mode: Go; indent-tabs-mode: t -*- 2 3 /* 4 * Copyright (C) 2014,2015,2017 Canonical Ltd 5 * 6 * This program is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 3 as 8 * published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 * 18 */ 19 20 package logger 21 22 import ( 23 "bytes" 24 "fmt" 25 "io" 26 "log" 27 "os" 28 "sync" 29 30 "github.com/snapcore/snapd/osutil" 31 ) 32 33 // A Logger is a fairly minimal logging tool. 34 type Logger interface { 35 // Notice is for messages that the user should see 36 Notice(msg string) 37 // Debug is for messages that the user should be able to find if they're debugging something 38 Debug(msg string) 39 } 40 41 const ( 42 // DefaultFlags are passed to the default console log.Logger 43 DefaultFlags = log.Ldate | log.Ltime | log.Lmicroseconds | log.Lshortfile 44 ) 45 46 type nullLogger struct{} 47 48 func (nullLogger) Notice(string) {} 49 func (nullLogger) Debug(string) {} 50 51 // NullLogger is a logger that does nothing 52 var NullLogger = nullLogger{} 53 54 var ( 55 logger Logger = NullLogger 56 lock sync.Mutex 57 ) 58 59 // Panicf notifies the user and then panics 60 func Panicf(format string, v ...interface{}) { 61 msg := fmt.Sprintf(format, v...) 62 63 lock.Lock() 64 defer lock.Unlock() 65 66 logger.Notice("PANIC " + msg) 67 panic(msg) 68 } 69 70 // Noticef notifies the user of something 71 func Noticef(format string, v ...interface{}) { 72 msg := fmt.Sprintf(format, v...) 73 74 lock.Lock() 75 defer lock.Unlock() 76 77 logger.Notice(msg) 78 } 79 80 // Debugf records something in the debug log 81 func Debugf(format string, v ...interface{}) { 82 msg := fmt.Sprintf(format, v...) 83 84 lock.Lock() 85 defer lock.Unlock() 86 87 logger.Debug(msg) 88 } 89 90 // MockLogger replaces the exiting logger with a buffer and returns 91 // the log buffer and a restore function. 92 func MockLogger() (buf *bytes.Buffer, restore func()) { 93 buf = &bytes.Buffer{} 94 oldLogger := logger 95 l, err := New(buf, DefaultFlags) 96 if err != nil { 97 panic(err) 98 } 99 SetLogger(l) 100 return buf, func() { 101 SetLogger(oldLogger) 102 } 103 } 104 105 // SetLogger sets the global logger to the given one 106 func SetLogger(l Logger) { 107 lock.Lock() 108 defer lock.Unlock() 109 110 logger = l 111 } 112 113 type Log struct { 114 log *log.Logger 115 } 116 117 // Debug only prints if SNAPD_DEBUG is set 118 func (l Log) Debug(msg string) { 119 if osutil.GetenvBool("SNAPD_DEBUG") { 120 l.log.Output(3, "DEBUG: "+msg) 121 } 122 } 123 124 // Notice alerts the user about something, as well as putting it syslog 125 func (l Log) Notice(msg string) { 126 l.log.Output(3, msg) 127 } 128 129 // New creates a log.Logger using the given io.Writer and flag. 130 func New(w io.Writer, flag int) (Logger, error) { 131 return Log{log: log.New(w, "", flag)}, nil 132 } 133 134 // SimpleSetup creates the default (console) logger 135 func SimpleSetup() error { 136 flags := log.Lshortfile 137 if term := os.Getenv("TERM"); term != "" { 138 // snapd is probably not running under systemd 139 flags = DefaultFlags 140 } 141 l, err := New(os.Stderr, flags) 142 if err == nil { 143 SetLogger(l) 144 } 145 return err 146 }