forked from gitea/gitea
143 lines
3.3 KiB
Go
143 lines
3.3 KiB
Go
|
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||
|
// SPDX-License-Identifier: MIT
|
||
|
|
||
|
package log
|
||
|
|
||
|
import (
|
||
|
"context"
|
||
|
"fmt"
|
||
|
"sync"
|
||
|
"sync/atomic"
|
||
|
)
|
||
|
|
||
|
const DEFAULT = "default"
|
||
|
|
||
|
// LoggerManager manages loggers and shared event writers
|
||
|
type LoggerManager struct {
|
||
|
ctx context.Context
|
||
|
ctxCancel context.CancelFunc
|
||
|
|
||
|
mu sync.Mutex
|
||
|
writers map[string]EventWriter
|
||
|
loggers map[string]*LoggerImpl
|
||
|
defaultLogger atomic.Pointer[LoggerImpl]
|
||
|
|
||
|
pauseMu sync.RWMutex
|
||
|
pauseChan chan struct{}
|
||
|
}
|
||
|
|
||
|
// GetLogger returns a logger with the given name. If the logger doesn't exist, a new empty one will be created.
|
||
|
func (m *LoggerManager) GetLogger(name string) *LoggerImpl {
|
||
|
if name == DEFAULT {
|
||
|
if logger := m.defaultLogger.Load(); logger != nil {
|
||
|
return logger
|
||
|
}
|
||
|
}
|
||
|
|
||
|
m.mu.Lock()
|
||
|
defer m.mu.Unlock()
|
||
|
|
||
|
logger := m.loggers[name]
|
||
|
if logger == nil {
|
||
|
logger = NewLoggerWithWriters(m.ctx)
|
||
|
m.loggers[name] = logger
|
||
|
if name == DEFAULT {
|
||
|
m.defaultLogger.Store(logger)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return logger
|
||
|
}
|
||
|
|
||
|
// PauseAll pauses all event writers
|
||
|
func (m *LoggerManager) PauseAll() {
|
||
|
m.pauseMu.Lock()
|
||
|
m.pauseChan = make(chan struct{})
|
||
|
m.pauseMu.Unlock()
|
||
|
}
|
||
|
|
||
|
// ResumeAll resumes all event writers
|
||
|
func (m *LoggerManager) ResumeAll() {
|
||
|
m.pauseMu.Lock()
|
||
|
close(m.pauseChan)
|
||
|
m.pauseChan = nil
|
||
|
m.pauseMu.Unlock()
|
||
|
}
|
||
|
|
||
|
// GetPauseChan returns a channel for writer pausing
|
||
|
func (m *LoggerManager) GetPauseChan() chan struct{} {
|
||
|
m.pauseMu.RLock()
|
||
|
defer m.pauseMu.RUnlock()
|
||
|
return m.pauseChan
|
||
|
}
|
||
|
|
||
|
// Close closes the logger manager, all loggers and writers will be closed, the messages are flushed.
|
||
|
func (m *LoggerManager) Close() {
|
||
|
m.mu.Lock()
|
||
|
defer m.mu.Unlock()
|
||
|
|
||
|
for _, logger := range m.loggers {
|
||
|
logger.Close()
|
||
|
}
|
||
|
m.loggers = map[string]*LoggerImpl{}
|
||
|
|
||
|
for _, writer := range m.writers {
|
||
|
eventWriterStopWait(writer)
|
||
|
}
|
||
|
m.writers = map[string]EventWriter{}
|
||
|
|
||
|
m.ctxCancel()
|
||
|
}
|
||
|
|
||
|
// DumpLoggers returns a map of all loggers and their event writers, for debugging and display purposes.
|
||
|
func (m *LoggerManager) DumpLoggers() map[string]any {
|
||
|
m.mu.Lock()
|
||
|
defer m.mu.Unlock()
|
||
|
|
||
|
dump := map[string]any{}
|
||
|
for name, logger := range m.loggers {
|
||
|
loggerDump := map[string]any{
|
||
|
"IsEnabled": logger.IsEnabled(),
|
||
|
"EventWriters": logger.DumpWriters(),
|
||
|
}
|
||
|
dump[name] = loggerDump
|
||
|
}
|
||
|
return dump
|
||
|
}
|
||
|
|
||
|
// 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.
|
||
|
func (m *LoggerManager) NewSharedWriter(writerName, writerType string, mode WriterMode) (writer EventWriter, err error) {
|
||
|
m.mu.Lock()
|
||
|
defer m.mu.Unlock()
|
||
|
|
||
|
if _, ok := m.writers[writerName]; ok {
|
||
|
return nil, fmt.Errorf("log event writer %q has been added before", writerName)
|
||
|
}
|
||
|
|
||
|
if writer, err = NewEventWriter(writerName, writerType, mode); err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
m.writers[writerName] = writer
|
||
|
eventWriterStartGo(m.ctx, writer, true)
|
||
|
return writer, nil
|
||
|
}
|
||
|
|
||
|
func (m *LoggerManager) GetSharedWriter(writerName string) EventWriter {
|
||
|
m.mu.Lock()
|
||
|
defer m.mu.Unlock()
|
||
|
return m.writers[writerName]
|
||
|
}
|
||
|
|
||
|
var loggerManager = NewManager()
|
||
|
|
||
|
func GetManager() *LoggerManager {
|
||
|
return loggerManager
|
||
|
}
|
||
|
|
||
|
func NewManager() *LoggerManager {
|
||
|
m := &LoggerManager{writers: map[string]EventWriter{}, loggers: map[string]*LoggerImpl{}}
|
||
|
m.ctx, m.ctxCancel = context.WithCancel(context.Background())
|
||
|
return m
|
||
|
}
|