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  }