Skip to content

Commit b538f05

Browse files
authored
Merge pull request #36 from dl1998/add-channel-lock
Update async loggers to prevent opening multiple channels
2 parents ad413cb + e5a8287 commit b538f05

File tree

10 files changed

+1435
-1414
lines changed

10 files changed

+1435
-1414
lines changed

README.md

Lines changed: 90 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -44,38 +44,38 @@ Default logger could be used like in the following example:
4444

4545
- Standard logger
4646

47-
```go
48-
logger.Warning("Message for logging: %s.", "my message")
49-
```
47+
```go
48+
logger.Warning("Message for logging: %s.", "my message")
49+
```
5050

5151
- Structured logger
5252

53-
```go
54-
structuredlogger.Warning("message", "My message.")
55-
```
56-
57-
or
58-
59-
```go
60-
structuredlogger.Warning(map[string]string{
61-
"message": "My message.",
62-
})
63-
```
53+
```go
54+
structuredlogger.Warning("message", "My message.")
55+
```
56+
57+
or
58+
59+
```go
60+
structuredlogger.Warning(map[string]string{
61+
"message": "My message.",
62+
})
63+
```
6464

6565
By default, root logger prints on console only, and starting from Warning level. It could be changed by setting logging
6666
level:
6767

6868
- Standard logger
6969

70-
```go
71-
logger.Configure(logger.NewConfiguration(logger.WithFromLevel(level.All)))
72-
```
70+
```go
71+
logger.Configure(logger.NewConfiguration(logger.WithFromLevel(level.All)))
72+
```
7373

7474
- Structured logger
7575

76-
```go
77-
structuredlogger.Configure(logger.NewConfiguration(logger.WithFromLevel(level.All)))
78-
```
76+
```go
77+
structuredlogger.Configure(logger.NewConfiguration(logger.WithFromLevel(level.All)))
78+
```
7979

8080
After changing log level to "All" it will print messages for any level.
8181

@@ -89,57 +89,57 @@ All options available for the configuration are:
8989

9090
- For Standard Logger
9191

92-
| Method | Default | Description |
93-
|----------------|:-----------------------------:|------------------------------------------------------------------------------------|
94-
| WithFromLevel | level.Warning | Set logging level from which logger should log messages. |
95-
| WithToLevel | level.Null | Set logging level till which logger should log messages. |
96-
| WithTemplate | "%(level):%(name):%(message)" | Set template for logging message. |
97-
| WithFile | "" | Set file where to log messages, if not set, then logging to file will be disabled. |
98-
| WithName | "root" | Set logger name. |
99-
| WithTimeFormat | time.RFC3339 | Set time format for logging message. |
92+
| Method | Default | Description |
93+
|----------------|:-----------------------------:|------------------------------------------------------------------------------------|
94+
| WithFromLevel | level.Warning | Set logging level from which logger should log messages. |
95+
| WithToLevel | level.Null | Set logging level till which logger should log messages. |
96+
| WithTemplate | "%(level):%(name):%(message)" | Set template for logging message. |
97+
| WithFile | "" | Set file where to log messages, if not set, then logging to file will be disabled. |
98+
| WithName | "root" | Set logger name. |
99+
| WithTimeFormat | time.RFC3339 | Set time format for logging message. |
100100

101101
- For Structured Logger
102102

103-
| Method | Default | Description |
104-
|-----------------------|:-------------------------------------------------------------------------------------------------------------------:|---------------------------------------------------------------------------------------------------------------------------------------|
105-
| WithFromLevel | level.Warning | Set logging level from which logger should log messages. |
106-
| WithToLevel | level.Null | Set logging level till which logger should log messages. |
107-
| WithTemplate | map[string]string {<br/>"timestamp": "%(timestamp)",<br/>"level": "%(level)",<br/>"name": "%(name)",<br/>} | Set template for logging structure. |
108-
| WithFile | "" | Set file where to log messages, if not set, then logging to file will be disabled. |
109-
| WithFormat | "json" | Set format for structured logging.<br/><br/>Could be one of the following<br/><ul><li>json</li><li>key-value</li></ul> |
110-
| WithPretty | false | Set if json message should be pretty printed.<br/>*Option works only with "json" format.* |
111-
| WithKeyValueDelimiter | "=" | Set key-value delimiter (eg. "key=value", where '=' is the delimiter).<br/>*Option works only with "key-value" format.* |
112-
| WithPairSeparator | " " | Set key-value separator (eg. "key1=value1,key2=value2", where ',' is the separator).<br/>*Option works only with "key-value" format.* |
113-
| WithName | "root" | Set logger name. |
114-
| WithTimeFormat | time.RFC3339 | Set time format for logging message. |
103+
| Method | Default | Description |
104+
|-----------------------|:-------------------------------------------------------------------------------------------------------------------:|---------------------------------------------------------------------------------------------------------------------------------------|
105+
| WithFromLevel | level.Warning | Set logging level from which logger should log messages. |
106+
| WithToLevel | level.Null | Set logging level till which logger should log messages. |
107+
| WithTemplate | map[string]string {<br/>"timestamp": "%(timestamp)",<br/>"level": "%(level)",<br/>"name": "%(name)",<br/>} | Set template for logging structure. |
108+
| WithFile | "" | Set file where to log messages, if not set, then logging to file will be disabled. |
109+
| WithFormat | "json" | Set format for structured logging.<br/><br/>Could be one of the following<br/><ul><li>json</li><li>key-value</li></ul> |
110+
| WithPretty | false | Set if json message should be pretty printed.<br/>*Option works only with "json" format.* |
111+
| WithKeyValueDelimiter | "=" | Set key-value delimiter (eg. "key=value", where '=' is the delimiter).<br/>*Option works only with "key-value" format.* |
112+
| WithPairSeparator | " " | Set key-value separator (eg. "key1=value1,key2=value2", where ',' is the separator).<br/>*Option works only with "key-value" format.* |
113+
| WithName | "root" | Set logger name. |
114+
| WithTimeFormat | time.RFC3339 | Set time format for logging message. |
115115

116116
### Custom Logger
117117

118118
Alternatively you could create application logger. To do this you would need to create a new logger.
119119

120120
- Standard logger
121121

122-
```go
123-
applicationLogger := logger.New("application-logger", time.RFC3339)
124-
```
122+
```go
123+
applicationLogger := logger.New("application-logger", time.RFC3339)
124+
```
125125

126126
- Standard async logger
127127

128-
```go
129-
applicationLogger := logger.NewAsyncLogger("application-logger", time.RFC3339, 100)
130-
```
128+
```go
129+
applicationLogger := logger.NewAsyncLogger("application-logger", time.RFC3339, 100)
130+
```
131131

132132
- Structured logger
133133

134-
```go
135-
applicationLogger := structuredlogger.New("application-logger", time.RFC3339)
136-
```
134+
```go
135+
applicationLogger := structuredlogger.New("application-logger", time.RFC3339)
136+
```
137137

138138
- Structured async logger
139139

140-
```go
141-
applicationLogger := structuredlogger.NewAsyncLogger("application-logger", time.RFC3339, 100)
142-
```
140+
```go
141+
applicationLogger := structuredlogger.NewAsyncLogger("application-logger", time.RFC3339, 100)
142+
```
143143

144144
After this you need to set up it, for this create a new formatter that says how to log the message by providing a
145145
template.
@@ -161,28 +161,28 @@ Available template options:
161161

162162
- Standard logger
163163

164-
```go
165-
applicationFormatter := formatter.New("%(datetime) [%(level)] %(message)")
166-
```
164+
```go
165+
applicationFormatter := formatter.New("%(datetime) [%(level)] %(message)")
166+
```
167167

168168
- Structured logger
169169
- JSON format
170170

171-
```go
172-
applicationFormatter := formatter.NewJSON(map[string]string{
173-
"time": "%(timestamp)",
174-
"level": "%(level)",
175-
}, false)
176-
```
171+
```go
172+
applicationFormatter := formatter.NewJSON(map[string]string{
173+
"time": "%(timestamp)",
174+
"level": "%(level)",
175+
}, false)
176+
```
177177

178178
- Key-Value format
179179

180-
```go
181-
applicationFormatter := formatter.NewKeyValue(map[string]string{
182-
"time": "%(timestamp)",
183-
"level": "%(level)",
184-
}, "=", " ")
185-
```
180+
```go
181+
applicationFormatter := formatter.NewKeyValue(map[string]string{
182+
"time": "%(timestamp)",
183+
"level": "%(level)",
184+
}, "=", " ")
185+
```
186186

187187
After creation of the formatter, you need to create a new handler that tells where to write log messages.
188188

@@ -193,23 +193,23 @@ There are three predefined types of handler (for standard and structured logger
193193
- Console Handler - it takes log level starting from which it would log messages, log level till which it would log
194194
messages, and formatter that tells how to log message. It logs messages to standard output.
195195

196-
```go
197-
newConsoleHandler := handler.NewConsoleHandler(level.Debug, level.Null, applicationFormatter)
198-
```
196+
```go
197+
newConsoleHandler := handler.NewConsoleHandler(level.Debug, level.Null, applicationFormatter)
198+
```
199199

200200
- Console Error Handler - it takes log level starting from which it would log messages, log level till which it would
201201
log messages, and formatter that tells how to log message. It logs messages to error output.
202202

203-
```go
204-
newConsoleErrorHandler := handler.NewConsoleErrorHandler(level.Debug, level.Null, applicationFormatter)
205-
```
203+
```go
204+
newConsoleErrorHandler := handler.NewConsoleErrorHandler(level.Debug, level.Null, applicationFormatter)
205+
```
206206

207207
- File Handler - it takes log level starting from which it would log messages, log level till which it would
208208
log messages, formatter that tells how to log message, and path to the file where to log those data.
209209

210-
```go
211-
newFileHandler := handler.NewFileHandler(level.Debug, level.Null, applicationFormatter, "system.log")
212-
```
210+
```go
211+
newFileHandler := handler.NewFileHandler(level.Debug, level.Null, applicationFormatter, "system.log")
212+
```
213213

214214
You could create your custom handler:
215215

@@ -236,27 +236,27 @@ arguments.
236236

237237
- Standard logger
238238

239-
```go
240-
applicationLogger.Info("My message: %s.", "logged using application logger")
241-
```
239+
```go
240+
applicationLogger.Info("My message: %s.", "logged using application logger")
241+
```
242242

243243
- Standard async logger
244244

245-
```go
246-
applicationLogger.Info("My message: %s.", "logged using application async logger")
247-
248-
// Wait for all messages to be logged before exiting the program.
249-
applicationLogger.WaitToFinishLogging()
250-
```
245+
```go
246+
applicationLogger.Info("My message: %s.", "logged using application async logger")
247+
248+
// Wait for all messages to be logged before exiting the program.
249+
applicationLogger.WaitToFinishLogging()
250+
```
251251

252252
- Structured logger
253-
- Varargs
253+
- Varargs
254254

255255
```go
256256
applicationLogger.Info("message", "Logged using structured logger with varargs.")
257257
```
258258

259-
- Map
259+
- Map
260260

261261
```go
262262
applicationLogger.Info(map[string]string{
@@ -310,7 +310,9 @@ applicationLogger.WaitToFinishLogging()
310310
applicationLogger.Close()
311311
312312
// Open the logger with a new message queue size.
313-
applicationLogger.Open(100)
313+
if err := applicationLogger.Open(100); err != nil {
314+
panic(err)
315+
}
314316
```
315317

316318
*Note: if you assign a new message queue size that is smaller than the number of messages sent to the queue, the logger

docs/architecture/diagrams/plantuml/class_diagram.plantuml

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -230,23 +230,24 @@ package pkg {
230230
struct baseAsyncLogger implements baseLoggerInterface {
231231
~ *baseLogger
232232
~ messageQueue : chan logrecord.Interface
233+
~ isChannelOpen : bool
233234
~ waitGroup sync.WaitGroup
234235
~ startListeningMessages()
235236
+ WaitToFinishLogging()
236-
+ Open(queueSize : int)
237+
+ Open(queueSize : int) : error
237238
+ Close()
238239
+ Log(level : level.Level, message : string, parameters : ...any)
239240
}
240241
interface AsyncLoggerInterface extends Interface {
241242
+ Interface
242243
+ WaitToFinishLogging()
243-
+ Open(queueSize : int)
244+
+ Open(queueSize : int) : error
244245
+ Close()
245246
}
246247
struct AsyncLogger implements AsyncLoggerInterface {
247248
+ *Logger
248249
+ WaitToFinishLogging()
249-
+ Open(queueSize : int)
250+
+ Open(queueSize : int) : error
250251
+ Close()
251252
}
252253
struct Configuration {
@@ -458,23 +459,24 @@ package pkg {
458459
struct baseAsyncLogger implements baseLoggerInterface {
459460
~ *baseLogger
460461
~ messageQueue : chan logrecord.Interface
462+
~ isChannelOpen : bool
461463
~ waitGroup sync.WaitGroup
462464
~ startListeningMessages()
463465
+ WaitToFinishLogging()
464-
+ Open(queueSize : int)
466+
+ Open(queueSize : int) : error
465467
+ Close()
466468
+ Log(level : level.Level, parameters : ...any)
467469
}
468470
interface AsyncLoggerInterface extends Interface {
469471
+ Interface
470472
+ WaitToFinishLogging()
471-
+ Open(queueSize : int)
473+
+ Open(queueSize : int) : error
472474
+ Close()
473475
}
474476
struct AsyncLogger implements AsyncLoggerInterface {
475477
+ *Logger
476478
+ WaitToFinishLogging()
477-
+ Open(queueSize : int)
479+
+ Open(queueSize : int) : error
478480
+ Close()
479481
}
480482
struct Configuration {
968 Bytes
Loading

0 commit comments

Comments
 (0)