|
3 | 3 |
|
4 | 4 | # log
|
5 | 5 |
|
6 |
| -The log module encompasses methods for comprehensive logging, which comprises a variety of logging levels: |
| 6 | +A flexible, high-performance logging package for Go applications with support for multiple output formats, logging levels, and concurrent operations. |
7 | 7 |
|
8 |
| -- Panic |
9 |
| - Panic typically signifies that something has gone unexpectedly awry. It's primarily utilized to swiftly halt on errors that shouldn't surface during regular operation, or those we aren't equipped to handle smoothly. |
| 8 | +## Features |
10 | 9 |
|
11 |
| -- Fatal |
12 |
| - Fatal corresponds to situations that are immensely disastrous for the application. The application is on the verge of terminating to avert any sort of corruption or severe problem, if feasible. Exit code is 1. |
| 10 | +- **Multiple Log Levels** with clear semantics: |
| 11 | + - `Panic`: For unrecoverable errors that require immediate attention (calls `panic()`) |
| 12 | + - `Fatal`: For critical errors that prevent application startup/operation (calls `os.Exit(1)`) |
| 13 | + - `Error`: For runtime errors that need investigation but don't stop the application |
| 14 | + - `Warn`: For potentially harmful situations |
| 15 | + - `Info`: For general operational information |
| 16 | + - `Debug`: For detailed system state information |
| 17 | + - `Trace`: For ultra-detailed debugging information |
13 | 18 |
|
14 |
| -- Error |
15 |
| - An error represents a significant issue and depicts the failure of something crucial within an application. Contrary to FATAL, the application itself is not doomed. |
| 19 | +- **Flexible Output Configuration**: |
| 20 | + - Multiple simultaneous outputs (console, files, custom writers) |
| 21 | + - Per-output level filtering |
| 22 | + - Text and JSON formats |
| 23 | + - ANSI color support for terminal output |
| 24 | + - Custom prefix support |
| 25 | + - Configurable timestamps and layouts |
16 | 26 |
|
17 |
| -- Warn |
18 |
| - This log level implies that an application might be experiencing a problem and an unusual situation has been detected. It's an unexpected and unusual issue, but no real damage is done, and it's uncertain whether the problem will persist or happen again. |
| 27 | +- **Thread-Safe Operations**: |
| 28 | + - Safe for concurrent use across goroutines |
| 29 | + - Mutex-protected logging operations |
19 | 30 |
|
20 |
| -- Info |
21 |
| - The messages at this level relate to standard application behavior and milestones. They offer a framework of the events that took place. |
| 31 | +- **Performance Optimized**: |
| 32 | + - Minimal allocations |
| 33 | + - Efficient formatting |
| 34 | + - Level-based filtering at source |
22 | 35 |
|
23 |
| -- Debug |
24 |
| - This level is meant to provide more detailed, diagnostic information than the INFO level. |
| 36 | +## Installation |
25 | 37 |
|
26 |
| -- Trace |
27 |
| - This level offers incredibly detailed information, even more so than DEBUG. At this level, every possible detail about the application's behavior should be captured. |
| 38 | +```bash |
| 39 | +go get -u github.com/goloop/log |
| 40 | +``` |
28 | 41 |
|
| 42 | +## Quick Start |
29 | 43 |
|
30 |
| -## Installation |
| 44 | +### Basic Usage |
31 | 45 |
|
32 |
| -To install this module use `go get` as: |
| 46 | +```go |
| 47 | +package main |
33 | 48 |
|
34 |
| -``` |
35 |
| -$ go get -u github.com/goloop/log |
36 |
| -``` |
| 49 | +import "github.com/goloop/log" |
37 | 50 |
|
38 |
| -## Quick Start |
| 51 | +func main() { |
| 52 | + // Create logger with prefix. |
| 53 | + logger := log.New("APP") |
| 54 | + |
| 55 | + // Basic logging. |
| 56 | + logger.Info("Application started") |
| 57 | + logger.Debug("Debug information") |
| 58 | + logger.Error("Something went wrong") |
39 | 59 |
|
40 |
| -To use this module import it as: |
| 60 | + // Formatted logging. |
| 61 | + logger.Infof("User %s logged in", username) |
| 62 | + |
| 63 | + // With newline. |
| 64 | + logger.Errorln("Failed to connect to database") |
| 65 | +} |
| 66 | +``` |
| 67 | + |
| 68 | +### Advanced Configuration |
41 | 69 |
|
42 | 70 | ```go
|
43 | 71 | package main
|
44 | 72 |
|
45 | 73 | import (
|
46 |
| - "os" |
| 74 | + "os" |
| 75 | + "github.com/goloop/log" |
| 76 | + "github.com/goloop/log/layout" |
| 77 | + "github.com/goloop/log/level" |
| 78 | +) |
47 | 79 |
|
48 |
| - "github.com/goloop/log" |
49 |
| - "github.com/goloop/log/layout" |
50 |
| - "github.com/goloop/log/level" |
| 80 | +func main() { |
| 81 | + // Open log file. |
| 82 | + file, err := os.OpenFile("app.log", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) |
| 83 | + if err != nil { |
| 84 | + log.Fatal(err) |
| 85 | + } |
| 86 | + defer file.Close() |
| 87 | + |
| 88 | + // Configure multiple outputs. |
| 89 | + log.SetOutputs( |
| 90 | + // Console output with colors. |
| 91 | + log.Output{ |
| 92 | + Name: "console", |
| 93 | + Writer: os.Stdout, |
| 94 | + Levels: level.Info | level.Warn | level.Error, |
| 95 | + Layouts: layout.Default, |
| 96 | + WithColor: 1, |
| 97 | + TextStyle: 1, |
| 98 | + }, |
| 99 | + // File output in JSON format. |
| 100 | + log.Output{ |
| 101 | + Name: "file", |
| 102 | + Writer: file, |
| 103 | + Levels: level.Error | level.Fatal, |
| 104 | + TextStyle: -1, // JSON format |
| 105 | + WithPrefix: 1, |
| 106 | + }, |
| 107 | + ) |
| 108 | + |
| 109 | + // Use the logger |
| 110 | + log.Info("System initialized") |
| 111 | + log.Error("Database connection failed") |
| 112 | +} |
| 113 | +``` |
51 | 114 |
|
52 |
| - // It is not necessary to import this module, the three-valued logic |
53 |
| - // constants can be represented using integers where: -1 is False, |
54 |
| - // 0 is Unknown, and 1 is True. |
55 |
| - "github.com/goloop/trit" |
| 115 | +### Custom Layout Configuration |
| 116 | + |
| 117 | +```go |
| 118 | +package main |
| 119 | + |
| 120 | +import ( |
| 121 | + "github.com/goloop/log" |
| 122 | + "github.com/goloop/log/layout" |
56 | 123 | )
|
57 | 124 |
|
58 | 125 | func main() {
|
59 |
| - // Open the file in append mode. Create the file if it doesn't exist. |
60 |
| - // Use appropriate permissions in a production setting. |
61 |
| - file, err := os.OpenFile( |
62 |
| - "errors.log", |
63 |
| - os.O_APPEND|os.O_CREATE|os.O_WRONLY, |
64 |
| - 0644, |
65 |
| - ) |
66 |
| - |
67 |
| - if err != nil { |
68 |
| - log.Fatal(err) |
69 |
| - } |
70 |
| - |
71 |
| - // Defer the closing of the file until the function ends. |
72 |
| - defer file.Close() |
73 |
| - |
74 |
| - // Set the outputs of the log to our file. |
75 |
| - // We can set many different outputs to record |
76 |
| - // individual errors, debug or mixed data. |
77 |
| - err = log.SetOutputs( |
78 |
| - log.Output{ |
79 |
| - Name: "stdout", |
80 |
| - Writer: os.Stdout, |
81 |
| - Levels: level.Debug | level.Info | level.Warn | level.Error, |
82 |
| - Layouts: layout.Default, |
83 |
| - WithColor: 1, // or trit.True, see github.com/goloop/trit |
84 |
| - }, |
85 |
| - log.Output{ |
86 |
| - Name: "errorsJSONFile", |
87 |
| - Writer: file, |
88 |
| - Levels: level.Warn | level.Error, // only errors and warnings |
89 |
| - Layouts: layout.Default, |
90 |
| - TextStyle: trit.False, // or just -1 |
91 |
| - }, |
92 |
| - ) |
93 |
| - |
94 |
| - if err != nil { |
95 |
| - log.Fatal(err) |
96 |
| - } |
97 |
| - |
98 |
| - // A message will be output to a file and to the console. |
99 |
| - // * stdout and errorsJSONFile has Error level. |
100 |
| - log.Errorln("This is a test log message with ERROR.") |
101 |
| - |
102 |
| - // A message will be output to the console only. |
103 |
| - // * stdout has Debug level, but errorsJSONFile has not. |
104 |
| - log.Debugln("This is a test log message with DEBUG.") |
| 126 | + logger := log.New("APP") |
| 127 | + |
| 128 | + // Configure custom layout. |
| 129 | + logger.SetOutputs(log.Output{ |
| 130 | + Name: "custom", |
| 131 | + Writer: os.Stdout, |
| 132 | + Layouts: layout.FullFilePath | layout.FuncName | layout.LineNumber, |
| 133 | + }) |
| 134 | + |
| 135 | + logger.Info("Custom layout message") |
| 136 | +} |
| 137 | +``` |
| 138 | + |
| 139 | +## Output Formats |
| 140 | + |
| 141 | +### Text Format (Default) |
| 142 | +``` |
| 143 | +APP: 2023/12/02 15:04:05 INFO main.go:42 Starting application |
| 144 | +``` |
| 145 | + |
| 146 | +### JSON Format |
| 147 | +```json |
| 148 | +{ |
| 149 | + "prefix": "APP", |
| 150 | + "timestamp": "2023/12/02 15:04:05", |
| 151 | + "level": "INFO", |
| 152 | + "file": "main.go", |
| 153 | + "line": 42, |
| 154 | + "message": "Starting application" |
| 155 | +} |
| 156 | +``` |
| 157 | + |
| 158 | +## Performance Considerations |
| 159 | + |
| 160 | +- Use appropriate log levels in production (typically Info and above) |
| 161 | +- Consider using JSON format only when structured logging is required |
| 162 | +- Disable debug/trace levels in production for optimal performance |
| 163 | +- Use formatted logging (`Infof`, etc.) only when necessary |
| 164 | + |
| 165 | +## Advanced Features |
| 166 | + |
| 167 | +### Stack Frame Skipping |
| 168 | + |
| 169 | +```go |
| 170 | +logger := log.New("APP") |
| 171 | +logger.SetSkipStackFrames(2) // skip wrapper functions |
| 172 | +``` |
| 173 | + |
| 174 | +### Multiple Prefix Support |
| 175 | + |
| 176 | +```go |
| 177 | +logger := log.New("APP", "SERVICE", "API") // Results in "APP-SERVICE-API" |
| 178 | +``` |
| 179 | + |
| 180 | +### Custom Writers |
| 181 | + |
| 182 | +```go |
| 183 | +type CustomWriter struct { |
| 184 | + // implementation |
105 | 185 | }
|
| 186 | + |
| 187 | +func (w *CustomWriter) Write(p []byte) (n int, err error) { |
| 188 | + // custom write logic. |
| 189 | + return len(p), nil |
| 190 | +} |
| 191 | + |
| 192 | +logger.SetOutputs(log.Output{ |
| 193 | + Name: "custom", |
| 194 | + Writer: &CustomWriter{}, |
| 195 | + Levels: level.Info, |
| 196 | +}) |
| 197 | +``` |
| 198 | + |
| 199 | +## Managing Outputs |
| 200 | + |
| 201 | +The logger provides several methods to manage outputs: |
| 202 | + |
| 203 | +### Get Current Outputs |
| 204 | +```go |
| 205 | +// Get all outputs. |
| 206 | +outputs := logger.Outputs() |
| 207 | + |
| 208 | +// Get specific outputs by name. |
| 209 | +stdoutOutput := logger.Outputs("stdout") |
106 | 210 | ```
|
107 | 211 |
|
| 212 | +### Edit Outputs |
| 213 | +```go |
| 214 | +// Change output configuration. |
| 215 | +logger.EditOutputs(log.Output{ |
| 216 | + Name: "stdout", |
| 217 | + Levels: level.Error | level.Fatal, // change levels |
| 218 | + WithColor: 1, // enable colors |
| 219 | +}) |
| 220 | + |
| 221 | +// Disable specific output. |
| 222 | +logger.EditOutputs(log.Output{ |
| 223 | + Name: "stdout", |
| 224 | + Enabled: -1, // or trit.False |
| 225 | +}) |
| 226 | +``` |
| 227 | + |
| 228 | +### Delete Outputs |
| 229 | +```go |
| 230 | +// Remove specific outputs, |
| 231 | +logger.DeleteOutputs("stdout", "file") |
| 232 | + |
| 233 | +// Or disable all logging by removing all outputs. |
| 234 | +logger.DeleteOutputs(logger.Outputs()...) |
| 235 | +``` |
| 236 | + |
| 237 | +### Set New Outputs |
| 238 | +```go |
| 239 | +// Replace all outputs with new ones. |
| 240 | +logger.SetOutputs( |
| 241 | + log.Output{ |
| 242 | + Name: "console", |
| 243 | + Writer: os.Stdout, |
| 244 | + Levels: level.Info | level.Warn, |
| 245 | + }, |
| 246 | + log.Output{ |
| 247 | + Name: "errors", |
| 248 | + Writer: errorFile, |
| 249 | + Levels: level.Error | level.Fatal, |
| 250 | + }, |
| 251 | +) |
| 252 | +``` |
| 253 | + |
| 254 | +## Why use this logger? |
| 255 | + |
| 256 | +- Flexible configuration |
| 257 | +- High performance |
| 258 | +- Multiple output support |
| 259 | +- Structured logging support |
| 260 | +- Thread safety |
| 261 | +- Comprehensive logging levels |
| 262 | + |
| 263 | +## Related Projects |
| 264 | + |
| 265 | +- [goloop/g](https://github.com/goloop/g) - Common utilities |
| 266 | +- [goloop/trit](https://github.com/goloop/trit) - Three-valued logic |
| 267 | + |
| 268 | + |
| 269 | +## Contributing |
| 270 | + |
| 271 | +Contributions are welcome! Please feel free to submit a Pull Request. |
| 272 | + |
| 273 | +## License |
| 274 | + |
| 275 | +This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details. |
| 276 | + |
| 277 | + |
0 commit comments