├── .github └── workflows │ └── go.yml ├── .gitignore ├── LICENSE ├── README.md ├── go.mod ├── logger.go └── logger_test.go /.github/workflows/go.yml: -------------------------------------------------------------------------------- 1 | name: Go 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | pull_request: 7 | branches: [ main ] 8 | 9 | jobs: 10 | 11 | build: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/checkout@v2 15 | 16 | - name: Set up Go 17 | uses: actions/setup-go@v2 18 | with: 19 | go-version: 1.17 20 | 21 | - name: Build 22 | run: go build -v ./... 23 | 24 | - name: Test 25 | run: go test -v ./... 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.exe~ 4 | *.dll 5 | *.so 6 | *.dylib 7 | 8 | # Test binary, built with `go test -c` 9 | *.test 10 | 11 | # Output of the go coverage tool, specifically when used with LiteIDE 12 | *.out 13 | 14 | # Dependency directories (remove the comment below to include it) 15 | # vendor/ -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Erman İmer 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # log 2 | 3 | [![Go](https://github.com/ermanimer/log/actions/workflows/go.yml/badge.svg?branch=main)](https://github.com/ermanimer/log/actions/workflows/go.yml) [![Go Report Card](https://goreportcard.com/badge/github.com/ermanimer/log)](https://goreportcard.com/report/github.com/ermanimer/log) 4 | 5 | Simple, customizable, leveled and efficient logging in Go 6 | 7 | # Installation 8 | 9 | ```bash 10 | go get -u github.com/ermanimer/log 11 | ``` 12 | 13 | # Features 14 | 15 | **log** is a simple logging package for Go. 16 | 17 | - You can set output 18 | - You can set internal error output (slog writes Log method's errors to internal error output instead of returning them.) 19 | - You can set time format and prefixes 20 | - You can set logging level to filter out log messages 21 | - You can set a hook function to be called after each log 22 | 23 | **log** isn't the fastest logging solution, but **log** is efficient while being customizable. Please see [benchmark tests](https://github.com/ermanimer/log#benchmark-tests). 24 | 25 | # Usage 26 | 27 | ```go 28 | package main 29 | 30 | import ( 31 | "os" 32 | 33 | "github.com/ermanimer/log/v2" 34 | ) 35 | 36 | func main() { 37 | // create a new logger instance with output and default parameters 38 | l := log.NewLogger() 39 | 40 | // log a message 41 | l.Debug("this is a debug message") 42 | 43 | // log a formatted message 44 | l.Debugf("this is a %s debug message", "formatted") 45 | } 46 | ``` 47 | 48 | **Output:** 49 | 50 | ```bash 51 | 2021-06-07T16:46:26+03:00 debug this is a debug message 52 | 2021-06-07T16:46:26+03:00 debug this is a formatted debug message 53 | ``` 54 | 55 | # Logging Levels 56 | 57 | - Debug 58 | - Info 59 | - Warning 60 | - Error 61 | - Fatal 62 | 63 | # Default Parameters: 64 | 65 | | Parameter | Value | 66 | |:----------|:-----:| 67 | |Output|os.Stdout| 68 | |Internal Error Output|os.Stderr| 69 | |Time Format|RFC3339| 70 | |Debug Prefix|debug| 71 | |Info Prefix|info| 72 | |Warning Prefix|warning| 73 | |Error Prefix|error| 74 | |Fatal Prefix|fatal| 75 | |Logging Level|Debug| 76 | 77 | # Set Output 78 | 79 | ```go 80 | l.SetOutput(os.Stderr) 81 | ``` 82 | 83 | # Set Internal Error Output 84 | 85 | ```go 86 | l.SetOutput(io.Discard) 87 | ``` 88 | 89 | # Set Logging Level 90 | 91 | ```go 92 | l.SetLoggingLevel(InfoLevel) 93 | ``` 94 | 95 | # Set Time Format 96 | 97 | ```go 98 | l.SetTimeFormat(time.RFC3339Nano) 99 | ``` 100 | 101 | # Set Prefixes 102 | 103 | ```go 104 | l.SetDebugPrefix("DEB") 105 | l.SetInfoPrefix("INF") 106 | l.SetWarningPrefix("WAR") 107 | l.SetErrorPrefix("ERR") 108 | l.SetFatalPrefix("FAT") 109 | ``` 110 | 111 | # Set Hook Function: 112 | 113 | ```go 114 | l.SetHookFunction(func(prefix, message string) { 115 | //you can filter messages with prefix and capture for Sentry.io 116 | }) 117 | ``` 118 | 119 | # Benchmark Tests 120 | 121 | **Test Codes:** 122 | 123 | ```go 124 | func BenchmarkDebug(b *testing.B) { 125 | // create logger 126 | l := NewLogger(ioutil.Discard) 127 | 128 | // start benchmark test 129 | b.RunParallel(func(pb *testing.PB) { 130 | for pb.Next() { 131 | l.Debug("test") 132 | } 133 | }) 134 | } 135 | 136 | func BenchmarkDebugf(b *testing.B) { 137 | // create logger 138 | l := NewLogger(ioutil.Discard) 139 | 140 | // start benchmark test 141 | b.RunParallel(func(pb *testing.PB) { 142 | for pb.Next() { 143 | l.Debugf("%s", "test") 144 | } 145 | }) 146 | } 147 | ``` 148 | **Results:** 149 | 150 | | Function | Time | Bytes Allocated | Objects Allocated | 151 | |:---------|:----:|:---------------:|:-----------------:| 152 | |Debug|410.7 ns/op|4 B/op|1 allocs/op| 153 | |Debugf|408.7 ns/op|4 B/op|1 allocs/op| 154 | |Info|404.0 ns/op|4 B/op|1 allocs/op| 155 | |Infof|403.9 ns/op|4 B/op|1 allocs/op| 156 | |Warning|407.0 ns/op|4 B/op|1 allocs/op| 157 | |Warningf|409.4 ns/op|4 B/op|1 allocs/op| 158 | |Error|404.6 ns/op|4 B/op|1 allocs/op| 159 | |Errorf|406.2 ns/op|4 B/op|1 allocs/op| 160 | |Fatal|402.1 ns/op |4 B/op|1 allocs/op| 161 | |Fatalf|406.0 ns/op|4 B/op|1 allocs/op| 162 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/ermanimer/log/v2 2 | 3 | go 1.17 4 | -------------------------------------------------------------------------------- /logger.go: -------------------------------------------------------------------------------- 1 | package log 2 | 3 | import ( 4 | "fmt" 5 | "io" 6 | "os" 7 | "sync" 8 | "time" 9 | ) 10 | 11 | // default prefixes 12 | const ( 13 | debugPrefix = "debug" 14 | infoPrefix = "info" 15 | warningPrefix = "warning" 16 | errorPrefix = "error" 17 | fatalPrefix = "fatal" 18 | ) 19 | 20 | // logging levels 21 | const ( 22 | DebugLevel = iota 23 | InfoLevel 24 | WarningLevel 25 | ErrorLevel 26 | FatalLevel 27 | ) 28 | 29 | // Logger represents logger 30 | type Logger struct { 31 | mutex *sync.Mutex 32 | output io.Writer 33 | internalErrorOutput io.Writer 34 | buffer []byte 35 | loggingLevel int 36 | timeFormat string 37 | debugPrefix string 38 | infoPrefix string 39 | warningPrefix string 40 | errorPrefix string 41 | fatalPrefix string 42 | exitFunction func() 43 | hookFunction func(prefix, message string) 44 | } 45 | 46 | // NewLogger creates and returns a new logger instance with given output and default parameters 47 | func NewLogger() *Logger { 48 | l := &Logger{ 49 | mutex: &sync.Mutex{}, 50 | output: os.Stdout, 51 | internalErrorOutput: os.Stderr, 52 | loggingLevel: DebugLevel, 53 | timeFormat: time.RFC3339, 54 | debugPrefix: debugPrefix, 55 | infoPrefix: infoPrefix, 56 | warningPrefix: warningPrefix, 57 | errorPrefix: errorPrefix, 58 | fatalPrefix: fatalPrefix, 59 | exitFunction: func() { os.Exit(1) }, 60 | hookFunction: func(prefix, message string) {}, 61 | } 62 | return l 63 | } 64 | 65 | // SetOutput sets output of logger 66 | func (l *Logger) SetOutput(output io.Writer) { 67 | l.mutex.Lock() 68 | defer l.mutex.Unlock() 69 | 70 | l.output = output 71 | } 72 | 73 | // SetInternalErrorOutput sets internal error output of logger 74 | func (l *Logger) SetInternalErrorOutput(internalErrorOutput io.Writer) { 75 | l.mutex.Lock() 76 | defer l.mutex.Unlock() 77 | 78 | l.internalErrorOutput = internalErrorOutput 79 | } 80 | 81 | // SetLoggingLevel sets logging level of logger 82 | func (l *Logger) SetLoggingLevel(loggingLevel int) { 83 | l.mutex.Lock() 84 | defer l.mutex.Unlock() 85 | 86 | l.loggingLevel = loggingLevel 87 | } 88 | 89 | // SetTimeFormat sets time format of logger 90 | func (l *Logger) SetTimeFormat(timeFormat string) { 91 | l.mutex.Lock() 92 | defer l.mutex.Unlock() 93 | 94 | l.timeFormat = timeFormat 95 | } 96 | 97 | // SetDebugPrefix sets debug prefix of logger 98 | func (l *Logger) SetDebugPrefix(debugPrefix string) { 99 | l.mutex.Lock() 100 | defer l.mutex.Unlock() 101 | 102 | l.debugPrefix = debugPrefix 103 | } 104 | 105 | // SetInfoPrefix sets info prefix of logger 106 | func (l *Logger) SetInfoPrefix(infoPrefix string) { 107 | l.mutex.Lock() 108 | defer l.mutex.Unlock() 109 | 110 | l.infoPrefix = infoPrefix 111 | } 112 | 113 | // SetWarningPrefix sets warning prefix of logger 114 | func (l *Logger) SetWarningPrefix(warningPrefix string) { 115 | l.mutex.Lock() 116 | defer l.mutex.Unlock() 117 | 118 | l.warningPrefix = warningPrefix 119 | } 120 | 121 | // SetErrorPrefix sets error prefix of logger 122 | func (l *Logger) SetErrorPrefix(errorPrefix string) { 123 | l.mutex.Lock() 124 | defer l.mutex.Unlock() 125 | 126 | l.errorPrefix = errorPrefix 127 | } 128 | 129 | // SetFatalPrefix sets fatal prefix of logger 130 | func (l *Logger) SetFatalPrefix(fatalPrefix string) { 131 | l.mutex.Lock() 132 | defer l.mutex.Unlock() 133 | 134 | l.fatalPrefix = fatalPrefix 135 | } 136 | 137 | // SetHookFunction sets hook function 138 | func (l *Logger) SetHookFunction(hookFunction func(prefix, message string)) { 139 | l.mutex.Lock() 140 | defer l.mutex.Unlock() 141 | 142 | l.hookFunction = hookFunction 143 | } 144 | 145 | // Debug logs a message with debug prefix 146 | func (l *Logger) Debug(values ...interface{}) { 147 | if l.loggingLevel > DebugLevel { 148 | return 149 | } 150 | 151 | l.log(l.debugPrefix, fmt.Sprint(values...)) 152 | } 153 | 154 | // Debugf logs a formatted message with debug prefix 155 | func (l *Logger) Debugf(format string, values ...interface{}) { 156 | if l.loggingLevel > DebugLevel { 157 | return 158 | } 159 | 160 | l.log(l.debugPrefix, fmt.Sprintf(format, values...)) 161 | } 162 | 163 | // Info logs a message with info prefix 164 | func (l *Logger) Info(values ...interface{}) { 165 | if l.loggingLevel > InfoLevel { 166 | return 167 | } 168 | l.log(l.infoPrefix, fmt.Sprint(values...)) 169 | } 170 | 171 | // Infof logs a formatted message with info prefix 172 | func (l *Logger) Infof(format string, values ...interface{}) { 173 | if l.loggingLevel > InfoLevel { 174 | return 175 | } 176 | 177 | l.log(l.infoPrefix, fmt.Sprintf(format, values...)) 178 | } 179 | 180 | // Warning logs a message with warning prefix 181 | func (l *Logger) Warning(values ...interface{}) { 182 | if l.loggingLevel > WarningLevel { 183 | return 184 | } 185 | l.log(l.warningPrefix, fmt.Sprint(values...)) 186 | } 187 | 188 | // Warningf logs a formatted message with warning prefix 189 | func (l *Logger) Warningf(format string, values ...interface{}) { 190 | if l.loggingLevel > WarningLevel { 191 | return 192 | } 193 | 194 | l.log(l.warningPrefix, fmt.Sprintf(format, values...)) 195 | } 196 | 197 | // Error logs a message with error prefix 198 | func (l *Logger) Error(values ...interface{}) { 199 | if l.loggingLevel > ErrorLevel { 200 | return 201 | } 202 | l.log(l.errorPrefix, fmt.Sprint(values...)) 203 | } 204 | 205 | // Errorf logs a formatted message with error prefix 206 | func (l *Logger) Errorf(format string, values ...interface{}) { 207 | if l.loggingLevel > ErrorLevel { 208 | return 209 | } 210 | 211 | l.log(l.errorPrefix, fmt.Sprintf(format, values...)) 212 | } 213 | 214 | // Fatal logs a message with fatal prefix and calls os.Exit(1) 215 | func (l *Logger) Fatal(values ...interface{}) { 216 | if l.loggingLevel > FatalLevel { 217 | return 218 | } 219 | 220 | l.log(l.fatalPrefix, fmt.Sprint(values...)) 221 | 222 | l.exitFunction() 223 | } 224 | 225 | // Fatalf logs a formatted message with fatal prefix and calls os.Exit(1) 226 | func (l *Logger) Fatalf(format string, values ...interface{}) { 227 | if l.loggingLevel > FatalLevel { 228 | return 229 | } 230 | 231 | l.log(l.fatalPrefix, fmt.Sprintf(format, values...)) 232 | 233 | l.exitFunction() 234 | } 235 | 236 | func (l *Logger) log(prefix, message string) { 237 | l.mutex.Lock() 238 | defer l.mutex.Unlock() 239 | 240 | l.buffer = l.buffer[:0] 241 | 242 | l.buffer = time.Now().AppendFormat(l.buffer, l.timeFormat) 243 | l.buffer = append(l.buffer, " "...) 244 | 245 | l.buffer = append(l.buffer, prefix...) 246 | l.buffer = append(l.buffer, " "...) 247 | 248 | l.buffer = append(l.buffer, message...) 249 | 250 | l.buffer = append(l.buffer, "\n"...) 251 | 252 | _, err := l.output.Write(l.buffer) 253 | if err != nil { 254 | fmt.Fprintf(l.internalErrorOutput, "writing to log's output failed, %s", err.Error()) 255 | } 256 | 257 | l.hookFunction(prefix, message) 258 | } 259 | -------------------------------------------------------------------------------- /logger_test.go: -------------------------------------------------------------------------------- 1 | package log 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "io" 7 | "testing" 8 | "time" 9 | ) 10 | 11 | func TestDebug(t *testing.T) { 12 | output := bytes.NewBuffer([]byte{}) 13 | l := NewLogger() 14 | l.SetOutput(output) 15 | 16 | l.hookFunction = func(prefix, message string) { 17 | t.Logf("hookFunction called (prefix: %s, message: %s)", prefix, message) 18 | } 19 | 20 | prefix := debugPrefix 21 | message := "test" 22 | expected := fmt.Sprintf("%s %s %s\n", time.Now().Format(l.timeFormat), prefix, message) 23 | 24 | l.Debug(message) 25 | 26 | if bytes.Compare(output.Bytes(), []byte(expected)) != 0 { 27 | t.Error("output doesn't match expected") 28 | } 29 | } 30 | 31 | func TestDebugf(t *testing.T) { 32 | output := bytes.NewBuffer([]byte{}) 33 | l := NewLogger() 34 | l.SetOutput(output) 35 | 36 | l.hookFunction = func(prefix, message string) { 37 | t.Logf("hookFunction called (prefix: %s, message: %s)", prefix, message) 38 | } 39 | 40 | prefix := debugPrefix 41 | format := "%s" 42 | message := "test" 43 | formattedMessage := fmt.Sprintf(format, message) 44 | expected := fmt.Sprintf("%s %s %s\n", time.Now().Format(l.timeFormat), prefix, formattedMessage) 45 | 46 | l.Debugf(format, message) 47 | 48 | if bytes.Compare(output.Bytes(), []byte(expected)) != 0 { 49 | t.Error("output doesn't match expected") 50 | } 51 | } 52 | 53 | func TestInfo(t *testing.T) { 54 | output := bytes.NewBuffer([]byte{}) 55 | l := NewLogger() 56 | l.SetOutput(output) 57 | 58 | l.hookFunction = func(prefix, message string) { 59 | t.Logf("hookFunction called (prefix: %s, message: %s)", prefix, message) 60 | } 61 | 62 | prefix := infoPrefix 63 | message := "test" 64 | expected := fmt.Sprintf("%s %s %s\n", time.Now().Format(l.timeFormat), prefix, message) 65 | 66 | l.Info(message) 67 | 68 | if bytes.Compare(output.Bytes(), []byte(expected)) != 0 { 69 | t.Error("output doesn't match expected") 70 | } 71 | } 72 | 73 | func TestInfof(t *testing.T) { 74 | output := bytes.NewBuffer([]byte{}) 75 | l := NewLogger() 76 | l.SetOutput(output) 77 | 78 | l.hookFunction = func(prefix, message string) { 79 | t.Logf("hookFunction called (prefix: %s, message: %s)", prefix, message) 80 | } 81 | 82 | prefix := infoPrefix 83 | format := "%s" 84 | message := "test" 85 | formattedMessage := fmt.Sprintf(format, message) 86 | expected := fmt.Sprintf("%s %s %s\n", time.Now().Format(l.timeFormat), prefix, formattedMessage) 87 | 88 | l.Infof(format, message) 89 | 90 | if bytes.Compare(output.Bytes(), []byte(expected)) != 0 { 91 | t.Error("output doesn't match expected") 92 | } 93 | } 94 | 95 | func TestWarning(t *testing.T) { 96 | output := bytes.NewBuffer([]byte{}) 97 | l := NewLogger() 98 | l.SetOutput(output) 99 | 100 | l.hookFunction = func(prefix, message string) { 101 | t.Logf("hookFunction called (prefix: %s, message: %s)", prefix, message) 102 | } 103 | 104 | prefix := warningPrefix 105 | message := "test" 106 | expected := fmt.Sprintf("%s %s %s\n", time.Now().Format(l.timeFormat), prefix, message) 107 | 108 | l.Warning(message) 109 | 110 | if bytes.Compare(output.Bytes(), []byte(expected)) != 0 { 111 | t.Error("output doesn't match expected") 112 | } 113 | } 114 | 115 | func TestWarningf(t *testing.T) { 116 | output := bytes.NewBuffer([]byte{}) 117 | l := NewLogger() 118 | l.SetOutput(output) 119 | 120 | l.hookFunction = func(prefix, message string) { 121 | t.Logf("hookFunction called (prefix: %s, message: %s)", prefix, message) 122 | } 123 | 124 | prefix := warningPrefix 125 | format := "%s" 126 | message := "test" 127 | formattedMessage := fmt.Sprintf(format, message) 128 | expected := fmt.Sprintf("%s %s %s\n", time.Now().Format(l.timeFormat), prefix, formattedMessage) 129 | 130 | l.Warningf(format, message) 131 | 132 | if bytes.Compare(output.Bytes(), []byte(expected)) != 0 { 133 | t.Error("output doesn't match expected") 134 | } 135 | } 136 | 137 | func TestError(t *testing.T) { 138 | output := bytes.NewBuffer([]byte{}) 139 | l := NewLogger() 140 | l.SetOutput(output) 141 | 142 | l.hookFunction = func(prefix, message string) { 143 | t.Logf("hookFunction called (prefix: %s, message: %s)", prefix, message) 144 | } 145 | 146 | prefix := errorPrefix 147 | message := "test" 148 | expected := fmt.Sprintf("%s %s %s\n", time.Now().Format(l.timeFormat), prefix, message) 149 | 150 | l.Error(message) 151 | 152 | if bytes.Compare(output.Bytes(), []byte(expected)) != 0 { 153 | t.Error("output doesn't match expected") 154 | } 155 | } 156 | 157 | func TestErrorf(t *testing.T) { 158 | output := bytes.NewBuffer([]byte{}) 159 | l := NewLogger() 160 | l.SetOutput(output) 161 | 162 | l.hookFunction = func(prefix, message string) { 163 | t.Logf("hookFunction called (prefix: %s, message: %s)", prefix, message) 164 | } 165 | 166 | prefix := errorPrefix 167 | format := "%s" 168 | message := "test" 169 | formattedMessage := fmt.Sprintf(format, message) 170 | expected := fmt.Sprintf("%s %s %s\n", time.Now().Format(l.timeFormat), prefix, formattedMessage) 171 | 172 | l.Errorf(format, message) 173 | 174 | if bytes.Compare(output.Bytes(), []byte(expected)) != 0 { 175 | t.Error("output doesn't match expected") 176 | } 177 | } 178 | 179 | func TestFatal(t *testing.T) { 180 | output := bytes.NewBuffer([]byte{}) 181 | l := NewLogger() 182 | l.SetOutput(output) 183 | 184 | l.hookFunction = func(prefix, message string) { 185 | t.Logf("hookFunction called (prefix: %s, message: %s)", prefix, message) 186 | } 187 | 188 | l.exitFunction = func() { t.Log("exitFunction called") } 189 | 190 | prefix := fatalPrefix 191 | message := "test" 192 | expected := fmt.Sprintf("%s %s %s\n", time.Now().Format(l.timeFormat), prefix, message) 193 | 194 | l.Fatal(message) 195 | 196 | if bytes.Compare(output.Bytes(), []byte(expected)) != 0 { 197 | t.Error("output doesn't match expected") 198 | } 199 | } 200 | 201 | func TestFatalf(t *testing.T) { 202 | output := bytes.NewBuffer([]byte{}) 203 | l := NewLogger() 204 | l.SetOutput(output) 205 | 206 | l.hookFunction = func(prefix, message string) { 207 | t.Logf("hookFunction called (prefix: %s, message: %s)", prefix, message) 208 | } 209 | 210 | l.exitFunction = func() { t.Log("exitFunction called") } 211 | 212 | prefix := fatalPrefix 213 | format := "%s" 214 | message := "test" 215 | formattedMessage := fmt.Sprintf(format, message) 216 | expected := fmt.Sprintf("%s %s %s\n", time.Now().Format(l.timeFormat), prefix, formattedMessage) 217 | 218 | l.Fatalf(format, message) 219 | 220 | if bytes.Compare(output.Bytes(), []byte(expected)) != 0 { 221 | t.Error("output doesn't match expected") 222 | } 223 | } 224 | 225 | func BenchmarkDebug(b *testing.B) { 226 | l := NewLogger() 227 | l.SetOutput(io.Discard) 228 | 229 | b.RunParallel(func(pb *testing.PB) { 230 | for pb.Next() { 231 | l.Debug("test") 232 | } 233 | }) 234 | } 235 | 236 | func BenchmarkDebugf(b *testing.B) { 237 | l := NewLogger() 238 | l.SetOutput(io.Discard) 239 | 240 | b.RunParallel(func(pb *testing.PB) { 241 | for pb.Next() { 242 | l.Debugf("%s", "test") 243 | } 244 | }) 245 | } 246 | 247 | func BenchmarkInfo(b *testing.B) { 248 | l := NewLogger() 249 | l.SetOutput(io.Discard) 250 | 251 | b.RunParallel(func(pb *testing.PB) { 252 | for pb.Next() { 253 | l.Info("test") 254 | } 255 | }) 256 | } 257 | 258 | func BenchmarkInfof(b *testing.B) { 259 | l := NewLogger() 260 | l.SetOutput(io.Discard) 261 | 262 | b.RunParallel(func(pb *testing.PB) { 263 | for pb.Next() { 264 | l.Infof("%s", "test") 265 | } 266 | }) 267 | } 268 | 269 | func BenchmarkWarning(b *testing.B) { 270 | l := NewLogger() 271 | l.SetOutput(io.Discard) 272 | 273 | b.RunParallel(func(pb *testing.PB) { 274 | for pb.Next() { 275 | l.Warning("test") 276 | } 277 | }) 278 | } 279 | 280 | func BenchmarkWarningf(b *testing.B) { 281 | l := NewLogger() 282 | l.SetOutput(io.Discard) 283 | 284 | b.RunParallel(func(pb *testing.PB) { 285 | for pb.Next() { 286 | l.Warningf("%s", "test") 287 | } 288 | }) 289 | } 290 | 291 | func BenchmarkError(b *testing.B) { 292 | l := NewLogger() 293 | l.SetOutput(io.Discard) 294 | 295 | b.RunParallel(func(pb *testing.PB) { 296 | for pb.Next() { 297 | l.Error("test") 298 | } 299 | }) 300 | } 301 | 302 | func BenchmarkErrorf(b *testing.B) { 303 | l := NewLogger() 304 | l.SetOutput(io.Discard) 305 | 306 | b.RunParallel(func(pb *testing.PB) { 307 | for pb.Next() { 308 | l.Errorf("%s", "test") 309 | } 310 | }) 311 | } 312 | 313 | func BenchmarkFatal(b *testing.B) { 314 | l := NewLogger() 315 | l.SetOutput(io.Discard) 316 | 317 | l.exitFunction = func() {} 318 | 319 | b.RunParallel(func(pb *testing.PB) { 320 | for pb.Next() { 321 | l.Fatal("test") 322 | } 323 | }) 324 | } 325 | 326 | func BenchmarkFatalf(b *testing.B) { 327 | l := NewLogger() 328 | l.SetOutput(io.Discard) 329 | 330 | l.exitFunction = func() {} 331 | 332 | b.RunParallel(func(pb *testing.PB) { 333 | for pb.Next() { 334 | l.Fatalf("%s", "test") 335 | } 336 | }) 337 | } 338 | --------------------------------------------------------------------------------