You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

event.go 8.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395
  1. // Copyright 2019 The Gitea Authors. All rights reserved.
  2. // Use of this source code is governed by a MIT-style
  3. // license that can be found in the LICENSE file.
  4. package log
  5. import (
  6. "fmt"
  7. "sync"
  8. "time"
  9. )
  10. // Event represents a logging event
  11. type Event struct {
  12. level Level
  13. msg string
  14. caller string
  15. filename string
  16. line int
  17. time time.Time
  18. stacktrace string
  19. }
  20. // EventLogger represents the behaviours of a logger
  21. type EventLogger interface {
  22. LogEvent(event *Event) error
  23. Close()
  24. Flush()
  25. GetLevel() Level
  26. GetStacktraceLevel() Level
  27. GetName() string
  28. ReleaseReopen() error
  29. }
  30. // ChannelledLog represents a cached channel to a LoggerProvider
  31. type ChannelledLog struct {
  32. name string
  33. provider string
  34. queue chan *Event
  35. loggerProvider LoggerProvider
  36. flush chan bool
  37. close chan bool
  38. closed chan bool
  39. }
  40. // NewChannelledLog a new logger instance with given logger provider and config.
  41. func NewChannelledLog(name, provider, config string, bufferLength int64) (*ChannelledLog, error) {
  42. if log, ok := providers[provider]; ok {
  43. l := &ChannelledLog{
  44. queue: make(chan *Event, bufferLength),
  45. flush: make(chan bool),
  46. close: make(chan bool),
  47. closed: make(chan bool),
  48. }
  49. l.loggerProvider = log()
  50. if err := l.loggerProvider.Init(config); err != nil {
  51. return nil, err
  52. }
  53. l.name = name
  54. l.provider = provider
  55. go l.Start()
  56. return l, nil
  57. }
  58. return nil, ErrUnknownProvider{provider}
  59. }
  60. // Start processing the ChannelledLog
  61. func (l *ChannelledLog) Start() {
  62. for {
  63. select {
  64. case event, ok := <-l.queue:
  65. if !ok {
  66. l.closeLogger()
  67. return
  68. }
  69. l.loggerProvider.LogEvent(event)
  70. case _, ok := <-l.flush:
  71. if !ok {
  72. l.closeLogger()
  73. return
  74. }
  75. l.loggerProvider.Flush()
  76. case <-l.close:
  77. l.closeLogger()
  78. return
  79. }
  80. }
  81. }
  82. // LogEvent logs an event to this ChannelledLog
  83. func (l *ChannelledLog) LogEvent(event *Event) error {
  84. select {
  85. case l.queue <- event:
  86. return nil
  87. case <-time.After(60 * time.Second):
  88. // We're blocked!
  89. return ErrTimeout{
  90. Name: l.name,
  91. Provider: l.provider,
  92. }
  93. }
  94. }
  95. func (l *ChannelledLog) closeLogger() {
  96. l.loggerProvider.Flush()
  97. l.loggerProvider.Close()
  98. l.closed <- true
  99. }
  100. // Close this ChannelledLog
  101. func (l *ChannelledLog) Close() {
  102. l.close <- true
  103. <-l.closed
  104. }
  105. // Flush this ChannelledLog
  106. func (l *ChannelledLog) Flush() {
  107. l.flush <- true
  108. }
  109. // ReleaseReopen this ChannelledLog
  110. func (l *ChannelledLog) ReleaseReopen() error {
  111. return l.loggerProvider.ReleaseReopen()
  112. }
  113. // GetLevel gets the level of this ChannelledLog
  114. func (l *ChannelledLog) GetLevel() Level {
  115. return l.loggerProvider.GetLevel()
  116. }
  117. // GetStacktraceLevel gets the level of this ChannelledLog
  118. func (l *ChannelledLog) GetStacktraceLevel() Level {
  119. return l.loggerProvider.GetStacktraceLevel()
  120. }
  121. // GetName returns the name of this ChannelledLog
  122. func (l *ChannelledLog) GetName() string {
  123. return l.name
  124. }
  125. // MultiChannelledLog represents a cached channel to a LoggerProvider
  126. type MultiChannelledLog struct {
  127. name string
  128. bufferLength int64
  129. queue chan *Event
  130. mutex sync.Mutex
  131. loggers map[string]EventLogger
  132. flush chan bool
  133. close chan bool
  134. started bool
  135. level Level
  136. stacktraceLevel Level
  137. closed chan bool
  138. paused chan bool
  139. }
  140. // NewMultiChannelledLog a new logger instance with given logger provider and config.
  141. func NewMultiChannelledLog(name string, bufferLength int64) *MultiChannelledLog {
  142. m := &MultiChannelledLog{
  143. name: name,
  144. queue: make(chan *Event, bufferLength),
  145. flush: make(chan bool),
  146. bufferLength: bufferLength,
  147. loggers: make(map[string]EventLogger),
  148. level: NONE,
  149. stacktraceLevel: NONE,
  150. close: make(chan bool),
  151. closed: make(chan bool),
  152. paused: make(chan bool),
  153. }
  154. return m
  155. }
  156. // AddLogger adds a logger to this MultiChannelledLog
  157. func (m *MultiChannelledLog) AddLogger(logger EventLogger) error {
  158. m.mutex.Lock()
  159. name := logger.GetName()
  160. if _, has := m.loggers[name]; has {
  161. m.mutex.Unlock()
  162. return ErrDuplicateName{name}
  163. }
  164. m.loggers[name] = logger
  165. if logger.GetLevel() < m.level {
  166. m.level = logger.GetLevel()
  167. }
  168. if logger.GetStacktraceLevel() < m.stacktraceLevel {
  169. m.stacktraceLevel = logger.GetStacktraceLevel()
  170. }
  171. m.mutex.Unlock()
  172. go m.Start()
  173. return nil
  174. }
  175. // DelLogger removes a sub logger from this MultiChannelledLog
  176. // NB: If you delete the last sublogger this logger will simply drop
  177. // log events
  178. func (m *MultiChannelledLog) DelLogger(name string) bool {
  179. m.mutex.Lock()
  180. logger, has := m.loggers[name]
  181. if !has {
  182. m.mutex.Unlock()
  183. return false
  184. }
  185. delete(m.loggers, name)
  186. m.internalResetLevel()
  187. m.mutex.Unlock()
  188. logger.Flush()
  189. logger.Close()
  190. return true
  191. }
  192. // GetEventLogger returns a sub logger from this MultiChannelledLog
  193. func (m *MultiChannelledLog) GetEventLogger(name string) EventLogger {
  194. m.mutex.Lock()
  195. defer m.mutex.Unlock()
  196. return m.loggers[name]
  197. }
  198. // GetEventLoggerNames returns a list of names
  199. func (m *MultiChannelledLog) GetEventLoggerNames() []string {
  200. m.mutex.Lock()
  201. defer m.mutex.Unlock()
  202. var keys []string
  203. for k := range m.loggers {
  204. keys = append(keys, k)
  205. }
  206. return keys
  207. }
  208. func (m *MultiChannelledLog) closeLoggers() {
  209. m.mutex.Lock()
  210. for _, logger := range m.loggers {
  211. logger.Flush()
  212. logger.Close()
  213. }
  214. m.mutex.Unlock()
  215. m.closed <- true
  216. }
  217. // Pause pauses this Logger
  218. func (m *MultiChannelledLog) Pause() {
  219. m.paused <- true
  220. }
  221. // Resume resumes this Logger
  222. func (m *MultiChannelledLog) Resume() {
  223. m.paused <- false
  224. }
  225. // ReleaseReopen causes this logger to tell its subloggers to release and reopen
  226. func (m *MultiChannelledLog) ReleaseReopen() error {
  227. m.mutex.Lock()
  228. defer m.mutex.Unlock()
  229. var accumulatedErr error
  230. for _, logger := range m.loggers {
  231. if err := logger.ReleaseReopen(); err != nil {
  232. if accumulatedErr == nil {
  233. accumulatedErr = fmt.Errorf("Error whilst reopening: %s Error: %v", logger.GetName(), err)
  234. } else {
  235. accumulatedErr = fmt.Errorf("Error whilst reopening: %s Error: %v & %v", logger.GetName(), err, accumulatedErr)
  236. }
  237. }
  238. }
  239. return accumulatedErr
  240. }
  241. // Start processing the MultiChannelledLog
  242. func (m *MultiChannelledLog) Start() {
  243. m.mutex.Lock()
  244. if m.started {
  245. m.mutex.Unlock()
  246. return
  247. }
  248. m.started = true
  249. m.mutex.Unlock()
  250. paused := false
  251. for {
  252. if paused {
  253. select {
  254. case paused = <-m.paused:
  255. if !paused {
  256. m.ResetLevel()
  257. }
  258. case _, ok := <-m.flush:
  259. if !ok {
  260. m.closeLoggers()
  261. return
  262. }
  263. m.mutex.Lock()
  264. for _, logger := range m.loggers {
  265. logger.Flush()
  266. }
  267. m.mutex.Unlock()
  268. case <-m.close:
  269. m.closeLoggers()
  270. return
  271. }
  272. continue
  273. }
  274. select {
  275. case paused = <-m.paused:
  276. if paused && m.level < INFO {
  277. m.level = INFO
  278. }
  279. case event, ok := <-m.queue:
  280. if !ok {
  281. m.closeLoggers()
  282. return
  283. }
  284. m.mutex.Lock()
  285. for _, logger := range m.loggers {
  286. err := logger.LogEvent(event)
  287. if err != nil {
  288. fmt.Println(err)
  289. }
  290. }
  291. m.mutex.Unlock()
  292. case _, ok := <-m.flush:
  293. if !ok {
  294. m.closeLoggers()
  295. return
  296. }
  297. m.mutex.Lock()
  298. for _, logger := range m.loggers {
  299. logger.Flush()
  300. }
  301. m.mutex.Unlock()
  302. case <-m.close:
  303. m.closeLoggers()
  304. return
  305. }
  306. }
  307. }
  308. // LogEvent logs an event to this MultiChannelledLog
  309. func (m *MultiChannelledLog) LogEvent(event *Event) error {
  310. select {
  311. case m.queue <- event:
  312. return nil
  313. case <-time.After(100 * time.Millisecond):
  314. // We're blocked!
  315. return ErrTimeout{
  316. Name: m.name,
  317. Provider: "MultiChannelledLog",
  318. }
  319. }
  320. }
  321. // Close this MultiChannelledLog
  322. func (m *MultiChannelledLog) Close() {
  323. m.close <- true
  324. <-m.closed
  325. }
  326. // Flush this ChannelledLog
  327. func (m *MultiChannelledLog) Flush() {
  328. m.flush <- true
  329. }
  330. // GetLevel gets the level of this MultiChannelledLog
  331. func (m *MultiChannelledLog) GetLevel() Level {
  332. return m.level
  333. }
  334. // GetStacktraceLevel gets the level of this MultiChannelledLog
  335. func (m *MultiChannelledLog) GetStacktraceLevel() Level {
  336. return m.stacktraceLevel
  337. }
  338. func (m *MultiChannelledLog) internalResetLevel() Level {
  339. m.level = NONE
  340. for _, logger := range m.loggers {
  341. level := logger.GetLevel()
  342. if level < m.level {
  343. m.level = level
  344. }
  345. level = logger.GetStacktraceLevel()
  346. if level < m.stacktraceLevel {
  347. m.stacktraceLevel = level
  348. }
  349. }
  350. return m.level
  351. }
  352. // ResetLevel will reset the level of this MultiChannelledLog
  353. func (m *MultiChannelledLog) ResetLevel() Level {
  354. m.mutex.Lock()
  355. defer m.mutex.Unlock()
  356. return m.internalResetLevel()
  357. }
  358. // GetName gets the name of this MultiChannelledLog
  359. func (m *MultiChannelledLog) GetName() string {
  360. return m.name
  361. }