code.gitea.io/gitea@v1.22.3/modules/log/manager.go (about) 1 // Copyright 2023 The Gitea Authors. All rights reserved. 2 // SPDX-License-Identifier: MIT 3 4 package log 5 6 import ( 7 "context" 8 "fmt" 9 "sync" 10 "sync/atomic" 11 ) 12 13 const DEFAULT = "default" 14 15 // LoggerManager manages loggers and shared event writers 16 type LoggerManager struct { 17 ctx context.Context 18 ctxCancel context.CancelFunc 19 20 mu sync.Mutex 21 writers map[string]EventWriter 22 loggers map[string]*LoggerImpl 23 defaultLogger atomic.Pointer[LoggerImpl] 24 25 pauseMu sync.RWMutex 26 pauseChan chan struct{} 27 } 28 29 // GetLogger returns a logger with the given name. If the logger doesn't exist, a new empty one will be created. 30 func (m *LoggerManager) GetLogger(name string) *LoggerImpl { 31 if name == DEFAULT { 32 if logger := m.defaultLogger.Load(); logger != nil { 33 return logger 34 } 35 } 36 37 m.mu.Lock() 38 defer m.mu.Unlock() 39 40 logger := m.loggers[name] 41 if logger == nil { 42 logger = NewLoggerWithWriters(m.ctx, name) 43 m.loggers[name] = logger 44 if name == DEFAULT { 45 m.defaultLogger.Store(logger) 46 } 47 } 48 49 return logger 50 } 51 52 // PauseAll pauses all event writers 53 func (m *LoggerManager) PauseAll() { 54 m.pauseMu.Lock() 55 m.pauseChan = make(chan struct{}) 56 m.pauseMu.Unlock() 57 } 58 59 // ResumeAll resumes all event writers 60 func (m *LoggerManager) ResumeAll() { 61 m.pauseMu.Lock() 62 close(m.pauseChan) 63 m.pauseChan = nil 64 m.pauseMu.Unlock() 65 } 66 67 // GetPauseChan returns a channel for writer pausing 68 func (m *LoggerManager) GetPauseChan() chan struct{} { 69 m.pauseMu.RLock() 70 defer m.pauseMu.RUnlock() 71 return m.pauseChan 72 } 73 74 // Close closes the logger manager, all loggers and writers will be closed, the messages are flushed. 75 func (m *LoggerManager) Close() { 76 m.mu.Lock() 77 defer m.mu.Unlock() 78 79 for _, logger := range m.loggers { 80 logger.Close() 81 } 82 m.loggers = map[string]*LoggerImpl{} 83 84 for _, writer := range m.writers { 85 eventWriterStopWait(writer) 86 } 87 m.writers = map[string]EventWriter{} 88 89 m.ctxCancel() 90 } 91 92 // DumpLoggers returns a map of all loggers and their event writers, for debugging and display purposes. 93 func (m *LoggerManager) DumpLoggers() map[string]any { 94 m.mu.Lock() 95 defer m.mu.Unlock() 96 97 dump := map[string]any{} 98 for name, logger := range m.loggers { 99 loggerDump := map[string]any{ 100 "IsEnabled": logger.IsEnabled(), 101 "EventWriters": logger.DumpWriters(), 102 } 103 dump[name] = loggerDump 104 } 105 return dump 106 } 107 108 // NewSharedWriter creates a new shared event writer, it can be used by multiple loggers, and a shared writer won't be closed if a logger is closed. 109 func (m *LoggerManager) NewSharedWriter(writerName, writerType string, mode WriterMode) (writer EventWriter, err error) { 110 m.mu.Lock() 111 defer m.mu.Unlock() 112 113 if _, ok := m.writers[writerName]; ok { 114 return nil, fmt.Errorf("log event writer %q has been added before", writerName) 115 } 116 117 if writer, err = NewEventWriter(writerName, writerType, mode); err != nil { 118 return nil, err 119 } 120 121 m.writers[writerName] = writer 122 eventWriterStartGo(m.ctx, writer, true) 123 return writer, nil 124 } 125 126 func (m *LoggerManager) GetSharedWriter(writerName string) EventWriter { 127 m.mu.Lock() 128 defer m.mu.Unlock() 129 return m.writers[writerName] 130 } 131 132 var loggerManager = NewManager() 133 134 func GetManager() *LoggerManager { 135 return loggerManager 136 } 137 138 func NewManager() *LoggerManager { 139 m := &LoggerManager{writers: map[string]EventWriter{}, loggers: map[string]*LoggerImpl{}} 140 m.ctx, m.ctxCancel = newProcessTypedContext(context.Background(), "LoggerManager") 141 return m 142 }