/
log_context.go
111 lines (94 loc) · 2.34 KB
/
log_context.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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
package log4g
import (
"errors"
"strconv"
"github.com/jrivets/gorivets"
)
type logContext struct {
loggerName string
appenders []Appender
inherited bool
blocking bool
eventsCh chan *Event
controlCh chan bool
sync bool
}
func newLogContext(loggerName string, appenders []Appender, inherited, blocking bool, bufSize int) (*logContext, error) {
if bufSize < 0 {
return nil, errors.New("Cannot create channel with negative size=" + strconv.Itoa(bufSize))
}
if appenders == nil || len(appenders) == 0 {
return nil, errors.New("At least one appender should be in Log Context")
}
eventsCh := make(chan *Event, bufSize)
controlCh := make(chan bool, 1)
lc := &logContext{loggerName, appenders, inherited, blocking, eventsCh, controlCh, blocking && bufSize == 0}
go func() {
defer onStop(controlCh)
for {
le, ok := <-eventsCh
if !ok {
break
}
lc.onEvent(le)
}
}()
return lc, nil
}
// Processing go routine finalizer
func onStop(controlCh chan bool) {
controlCh <- true
close(controlCh)
}
func getLogLevelContext(loggerName string, logContexts *gorivets.SortedSlice) *logContext {
lProvider := getNearestAncestor(&logContext{loggerName: loggerName}, logContexts)
if lProvider == nil {
return nil
}
return lProvider.(*logContext)
}
// log() function sends the logEvent to all the logContext appenders.
// It returns true if the logEvent was sent and false if the context is shut down or
// the context is non-blocking (allows to lost log messages in case of overflow)
func (lc *logContext) log(le *Event) (result bool) {
// Channel can be already closed, so end quietly
result = false
defer gorivets.EndQuietly()
if lc.sync {
lc.onEvent(le)
return true
}
if lc.blocking {
lc.eventsCh <- le
return true
}
select {
case lc.eventsCh <- le:
return true
default:
}
return false
}
// Called from processing go routine
func (lc *logContext) onEvent(le *Event) {
appenders := lc.appenders
if len(appenders) == 1 {
appenders[0].Append(le)
return
}
for _, a := range appenders {
a.Append(le)
}
}
func (lc *logContext) shutdown() {
close(lc.eventsCh)
<-lc.controlCh
}
// logNameProvider implementation
func (lc *logContext) name() string {
return lc.loggerName
}
// Comparable implementation
func (lc *logContext) Compare(other gorivets.Comparable) int {
return compare(lc, other.(*logContext))
}