-
Notifications
You must be signed in to change notification settings - Fork 1
/
Log.go
76 lines (64 loc) · 1.91 KB
/
Log.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
package log
import (
"fmt"
"io"
"sync/atomic"
)
const (
// How many log messages can be buffered until the call blocks
bufferCapacity = 1024
)
// Log is a log data source used for a specific part of your application,
// e.g. "web", "database", "api" or other categories. It can be connected
// to multiple writers.
type Log struct {
writers atomic.Value
messages chan []byte
}
// New creates a new Log.
func New() *Log {
log := &Log{
messages: make(chan []byte, bufferCapacity),
}
log.writers.Store([]io.Writer{})
go func() {
for msg := range log.messages {
log.write(msg)
}
}()
return log
}
// AddWriter adds an output to the log.
func (log *Log) AddWriter(writer io.Writer) {
newWriters := append(log.writers.Load().([]io.Writer), writer)
log.writers.Store(newWriters)
}
// Info writes non-critical information to the log.
// Unlike Error, it does not guarantee that the message will have been
// written persistenly to disk at the time this function returns.
func (log *Log) Info(format string, values ...interface{}) {
fmt.Fprintf(log, format+"\n", values...)
}
// Error writes critical information to the log.
// It will instantly flush the I/O buffers and guarantees that the message
// will have been written persistenly to disk at the time this function returns.
func (log *Log) Error(format string, values ...interface{}) {
fmt.Fprintf(log, format+"\n", values...)
// TODO: Flush.
}
// Write implements the io.Writer interface.
// As long as buffer capacity is available,
// this call will not block and have O(1) behaviour,
// regardless of how many writers are used.
func (log *Log) Write(b []byte) (n int, err error) {
tmp := make([]byte, len(b))
copy(tmp, b)
log.messages <- tmp
return len(b), nil
}
// write writes the given slice of bytes to all registered writers immediately.
func (log *Log) write(b []byte) {
for _, writer := range log.writers.Load().([]io.Writer) {
_, _ = writer.Write(b)
}
}