Skip to content

Commit 6953c97

Browse files
committed
First commit for v2
1 parent 5752cc6 commit 6953c97

26 files changed

+1171
-1027
lines changed

README.md

+55-34
Original file line numberDiff line numberDiff line change
@@ -2,43 +2,64 @@
22

33
Yet another Go logger library.
44

5+
### Version 2
6+
7+
The new version of this library implements some breaking changes:
8+
9+
* The initialization options contains some changes. Once the logger is initialized, the rest of the code should be
10+
compatible with the `v1` version.
11+
* Added per-target logging level. Now you can optionally specify a different logging level for console and file logging.
12+
For example, you can just send limited logs to a third-party provider to avoid high costs and keep a detailed local
13+
file log for debugging purposes.
14+
* `timestamp` and `level` fields are always added to a JSON log. DO NOT include them when the input is a struct.
15+
* Verbosity level for the default logger is now `Info` instead of `Warning`.
16+
517
## How to use
618

719
1. Import the library
820

921
```golang
1022
import (
11-
gologger "github.com/randlabs/go-logger"
23+
logger "github.com/randlabs/go-logger/v2"
1224
)
1325
```
1426

15-
2. Then use `gologger.Create` to create a logger object with desired options.
16-
3. Optionally, you can also use the default logger which outputs only to console by accesing `gologger.Default()`.
27+
2. Then use `logger.Create` to create a logger object with desired options.
28+
3. Optionally, you can also use the default logger which outputs only to console by accessing `logger.Default()`.
1729

1830
## Logger options:
1931

2032
The `Options` struct accepts several modifiers that affects the logger behavior:
2133

22-
| Field | Meaning |
23-
|------------------|---------------------------------------------------------|
24-
| `DisableConsole` | Disable console output. |
25-
| `FileLog` | Enable file logging. Optional. Details below. |
26-
| `SysLog` | Enable SysLog logging. Optional. Details below. |
27-
| `Level` | Set the initial logging level to use. |
28-
| `DebugLevel` | Set the initial logging level for debug output to use. |
29-
| `UseLocalTime` | Use the local computer time instead of UTC. |
30-
| `ErrorHandler` | A callback to call if an internal error is encountered. |
34+
| Field | Meaning |
35+
|----------------|---------------------------------------------------------|
36+
| `Console` | Establishes some options for the console output. |
37+
| `File` | Enable file logging. Optional. Details below. |
38+
| `SysLog` | Enable SysLog logging. Optional. Details below. |
39+
| `Level` | Set the initial logging level to use. |
40+
| `DebugLevel` | Set the initial logging level for debug output to use. |
41+
| `UseLocalTime` | Use the local computer time instead of UTC. |
42+
| `ErrorHandler` | A callback to call if an internal error is encountered. |
3143

32-
The `FileOptions` struct accepts the following parameters:
44+
#### ConsoleOptions:
45+
46+
| Field | Meaning |
47+
|--------------|-----------------------------------------------------------------------|
48+
| `Disable` | Disabled console output. |
49+
| `Level` | Optional logging level to use in the console output. |
50+
| `DebugLevel` | Optional logging level for debug output to use in the console output. |
51+
52+
#### FileOptions:
3353

3454
| Field | Meaning |
3555
|--------------|-----------------------------------------------------------------------------|
3656
| `Prefix` | Filename prefix to use when a file is created. Defaults to the binary name. |
3757
| `Directory` | Destination directory to store log files. |
38-
| `DaysToKeep` | Amount of days to keep old logs, |
39-
40-
And the `SysLogOptions` struct accepts the following parameters:
58+
| `DaysToKeep` | Amount of days to keep old logs. |
59+
| `Level` | Optional logging level to use in the file output. |
60+
| `DebugLevel` | Optional logging level for debug output to use in the file output. |
4161

62+
#### SysLogOptions:
4263

4364
| Field | Meaning |
4465
|-----------------------|-------------------------------------------------------------------------------------------|
@@ -50,6 +71,8 @@ And the `SysLogOptions` struct accepts the following parameters:
5071
| `UseRFC5424` | Send messages in the new RFC 5424 format instead of the original RFC 3164 specification. |
5172
| `MaxMessageQueueSize` | Set the maximum amount of messages to keep in memory if connection to the server is lost. |
5273
| `TlsConfig` | An optional pointer to a `tls.Config` object to provide the TLS configuration for use. |
74+
| `Level` | Optional logging level to use in the syslog output. |
75+
| `DebugLevel` | Optional logging level for debug output to use in the syslog output. |
5376

5477
## Example
5578

@@ -58,10 +81,8 @@ package example
5881

5982
import (
6083
"fmt"
61-
"os"
62-
"path/filepath"
6384

64-
gologger "github.com/randlabs/go-logger"
85+
logger "github.com/randlabs/go-logger/v2"
6586
)
6687

6788
// Define a custom JSON message. Timestamp and level will be automatically added by the logger.
@@ -71,43 +92,43 @@ type JsonMessage struct {
7192

7293
func main() {
7394
// Create the logger
74-
logger, err := gologger.Create(gologger.Options{
75-
FileLog: &gologger.FileOptions{
95+
lg, err := logger.Create(logger.Options{
96+
File: &logger.FileOptions{
7697
Directory: "./logs",
7798
DaysToKeep: 7,
7899
},
79-
Level: gologger.LogLevelDebug,
100+
Level: logger.LogLevelDebug,
80101
DebugLevel: 1,
81102
})
82103
if err != nil {
83104
// Use default logger to send the error
84-
gologger.Default().Error(fmt.Sprintf("unable to initialize. [%v]", err))
105+
logger.Default().Error(fmt.Sprintf("unable to initialize. [%v]", err))
85106
return
86107
}
87108
// Defer logger shut down
88-
defer logger.Destroy()
109+
defer lg.Destroy()
89110

90111
// Send some logs using the plain text format
91-
logger.Error("This is an error message sample")
92-
logger.Warning("This is a warning message sample")
93-
logger.Info("This is an information message sample")
94-
logger.Debug(1, "This is a debug message sample at level 1 which should be printed")
95-
logger.Debug(2, "This is a debug message sample at level 2 which should NOT be printed")
112+
lg.Error("This is an error message sample")
113+
lg.Warning("This is a warning message sample")
114+
lg.Info("This is an information message sample")
115+
lg.Debug(1, "This is a debug message sample at level 1 which should be printed")
116+
lg.Debug(2, "This is a debug message sample at level 2 which should NOT be printed")
96117

97118
// Send some other logs using the JSON format
98-
logger.Error(JsonMessage{
119+
lg.Error(JsonMessage{
99120
Message: "This is an error message sample",
100121
})
101-
logger.Warning(JsonMessage{
122+
lg.Warning(JsonMessage{
102123
Message: "This is a warning message sample",
103124
})
104-
logger.Info(JsonMessage{
125+
lg.Info(JsonMessage{
105126
Message: "This is an information message sample",
106127
})
107-
logger.Debug(1, JsonMessage{
128+
lg.Debug(1, JsonMessage{
108129
Message: "This is a debug message sample at level 1 which should be printed",
109130
})
110-
logger.Debug(2, JsonMessage{
131+
lg.Debug(2, JsonMessage{
111132
Message: "This is a debug message sample at level 2 which should NOT be printed",
112133
})
113134
}

console.go

+142
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
package go_logger
2+
3+
import (
4+
"fmt"
5+
"io"
6+
"os"
7+
"sync"
8+
"time"
9+
10+
"github.com/gookit/color"
11+
)
12+
13+
//------------------------------------------------------------------------------
14+
15+
// ConsoleOptions specifies the console logger settings to use when it is created.
16+
type ConsoleOptions struct {
17+
// Disable console output.
18+
Disable bool `json:"disable,omitempty"`
19+
20+
// Set the initial logging level to use.
21+
Level *LogLevel `json:"level,omitempty"`
22+
23+
// Set the initial logging level for debug output to use.
24+
DebugLevel *uint `json:"debugLevel,omitempty"`
25+
}
26+
27+
type consoleAdapter struct {
28+
themedLevels [4]string
29+
globals globalOptions
30+
}
31+
32+
//------------------------------------------------------------------------------
33+
34+
var consoleMtx = sync.Mutex{}
35+
36+
//------------------------------------------------------------------------------
37+
38+
func createConsoleAdapter(opts ConsoleOptions, glbOpts globalOptions) internalLogger {
39+
// Create console adapter
40+
lg := &consoleAdapter{
41+
globals: glbOpts,
42+
}
43+
44+
if color.IsSupportColor() {
45+
lg.themedLevels[0] = color.Error.Sprintf("[ERROR]")
46+
lg.themedLevels[1] = color.Warn.Sprintf("[WARN]")
47+
lg.themedLevels[2] = color.Info.Sprintf("[INFO]")
48+
lg.themedLevels[3] = color.Debug.Sprintf("[DEBUG]")
49+
} else {
50+
lg.themedLevels[0] = "[ERROR]"
51+
lg.themedLevels[1] = "[WARN]"
52+
lg.themedLevels[2] = "[INFO]"
53+
lg.themedLevels[3] = "[DEBUG]"
54+
}
55+
56+
// Set output level based on globals or overrides
57+
if opts.Level != nil {
58+
lg.globals.Level = *opts.Level
59+
lg.globals.DebugLevel = 1
60+
}
61+
if opts.DebugLevel != nil {
62+
lg.globals.DebugLevel = *opts.DebugLevel
63+
}
64+
65+
// Done
66+
return lg
67+
}
68+
69+
func (lg *consoleAdapter) class() string {
70+
return "console"
71+
}
72+
73+
func (lg *consoleAdapter) destroy() {
74+
// Do nothing
75+
}
76+
77+
func (lg *consoleAdapter) setLevel(level LogLevel, debugLevel uint) {
78+
lg.globals.Level = level
79+
lg.globals.DebugLevel = debugLevel
80+
}
81+
82+
func (lg *consoleAdapter) logError(now time.Time, msg string, raw bool) {
83+
if lg.globals.Level >= LogLevelError {
84+
if !raw {
85+
consolePrint(os.Stderr, now, lg.themedLevels[0], msg)
86+
} else {
87+
consolePrintRAW(os.Stderr, msg)
88+
}
89+
}
90+
}
91+
92+
func (lg *consoleAdapter) logWarning(now time.Time, msg string, raw bool) {
93+
if lg.globals.Level >= LogLevelWarning {
94+
if !raw {
95+
consolePrint(os.Stderr, now, lg.themedLevels[1], msg)
96+
} else {
97+
consolePrintRAW(os.Stderr, msg)
98+
}
99+
}
100+
}
101+
102+
func (lg *consoleAdapter) logInfo(now time.Time, msg string, raw bool) {
103+
if lg.globals.Level >= LogLevelInfo {
104+
if !raw {
105+
consolePrint(os.Stdout, now, lg.themedLevels[2], msg)
106+
} else {
107+
consolePrintRAW(os.Stdout, msg)
108+
}
109+
}
110+
}
111+
112+
func (lg *consoleAdapter) logDebug(level uint, now time.Time, msg string, raw bool) {
113+
if lg.globals.Level >= LogLevelDebug && lg.globals.DebugLevel >= level {
114+
if !raw {
115+
consolePrint(os.Stdout, now, lg.themedLevels[3], msg)
116+
} else {
117+
consolePrintRAW(os.Stdout, msg)
118+
}
119+
}
120+
}
121+
122+
func consolePrint(w io.Writer, now time.Time, themedLevel string, msg string) {
123+
// Lock console access
124+
consoleMtx.Lock()
125+
126+
// Print the message prefixed with the timestamp and level
127+
_, _ = fmt.Fprintf(w, "%v %v %v\n", now.Format("2006-01-02 15:04:05.000"), themedLevel, msg)
128+
129+
// Unlock console access
130+
consoleMtx.Unlock()
131+
}
132+
133+
func consolePrintRAW(w io.Writer, msg string) {
134+
// Lock console access
135+
consoleMtx.Lock()
136+
137+
// Print the message with extra payload
138+
_, _ = fmt.Fprintf(w, "%v\n", msg)
139+
140+
// Unlock console access
141+
consoleMtx.Unlock()
142+
}

0 commit comments

Comments
 (0)