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.
active/alogs/logger_manager.go

439 lines
8.5 KiB

// ------------------------------------------------------------------------
// Project active2
// Active Thing (activething.com) git.activething.com/go
//
// File name logger_manager.go
// Created by DEV
// Modified 26/04/2024
//
// Copyright 2024 activething.com
// ------------------------------------------------------------------------
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ------------------------------------------------------------------------
package alogs
import (
"errs"
"fmt"
"strings"
"sync"
"sync/atomic"
"syncs/queue"
)
type (
LoggerManager struct {
sync.RWMutex
filters EntryFilters
extenders EntryExtenders
queue queue.GQueue[*Entry]
scopes loggerScopes
loggers []Logger
async bool
chanLog chan *Entry
level Level
name string
state State
count int64
logErrors bool
errors errs.ErrorList
onErrorFn LoggerManagerErrorFnc
onFatalFn LoggerManagerEntryFnc
}
LoggerManagerFnc func(manager *LoggerManager)
LoggerManagerErrorFnc func(manager *LoggerManager, err error)
LoggerManagerEntryFnc func(manager *LoggerManager, entry *Entry)
)
func NewLoggerManager(name string, level Level, options ...LoggerManagerFnc) *LoggerManager {
l := &LoggerManager{
filters : *NewEntryFilters(),
level : level,
state : StateCreated,
logErrors: true,
queue : *queue.NewGQueue[*Entry](false),
}
for _,o := range options {
o(l)
}
return l
}
func (l *LoggerManager) Name() string {
return l.name }
func (l *LoggerManager) Level() Level {
l.RLock()
lv := l.level
l.RUnlock()
return lv
}
func (l *LoggerManager) SetLevel (level Level) {
l.Lock()
l.level = level
l.Unlock()
}
func (l *LoggerManager) Count () int64 {
return atomic.LoadInt64(&l.count) }
func (l *LoggerManager) incCount () {
atomic.AddInt64(&l.count,1) }
func (l *LoggerManager) State () State {
l.RLock()
s := l.state
l.RUnlock()
return s
}
func (l *LoggerManager) Errors () errs.ErrorList {
l.RLock()
ls := l.errors
l.RUnlock()
return ls
}
func (l *LoggerManager) Start () error {
l.Lock()
if l.state == StateStarted {
l.Unlock()
return G.ErrLoggerStarted
}
if l.state == StateStopped {
l.errors = l.errors.Reset()
}
l.state = StateStarted
er := l.handleLoggers(nil,func(c Logger, _ *Entry) error { return c.Start() }, G.FmtMsgStartErr,)
if er != nil {
l.handleQueue()
}
l.Unlock()
return er
}
func (l *LoggerManager) Stop () error {
l.Lock()
if l.state != StateStarted {
l.Unlock()
return G.ErrLoggerNotStarted
}
l.state = StateStopped
er := l.handleLoggers(nil,func(c Logger, _ *Entry) error { return c.Stop() }, G.FmtMsgStopErr)
if er != nil {
l.handleQueue()
}
l.Unlock()
return er
}
func (l *LoggerManager) Flush () error {
l.Lock()
er := l.handleLoggers(nil,func(c Logger,_ *Entry) error { return c.Flush() }, G.FmtMsgFlushErr)
if er != nil {
l.handleQueue()
}
l.Unlock()
return er
}
func (l *LoggerManager) GetLogger(name string) Logger {
l.RLock()
var co Logger
if p := l.findLogger(name); p != -1 {
co = l.loggers[p]
}
l.RUnlock()
return co
}
func (l *LoggerManager) AddLogger(logger Logger) error {
l.Lock()
nm := logger.Name()
if p := l.findLogger(nm); p != -1 {
l.Unlock()
return G.ErrDuplicatedLogger.WrapWithFieldString(errFieldLogger,nm)
}
var er error
l.loggers = append(l.loggers,logger)
if l.state == StateStarted {
er = logger.Start()
}
l.Unlock()
return er
}
func (l *LoggerManager) DelLogger(name string) error {
l.Lock()
p := l.findLogger(name)
if p != -1 {
l.Unlock()
return G.ErrNotExistsLogger.WrapWithFieldString(entryFieldLogger,name)
}
er := l.loggers[p].Stop()
l.loggers = append(l.loggers[:p],l.loggers[p+1:]...)
l.Unlock()
return er
}
func (l *LoggerManager) GetScope(name string) *LoggerScope {
ns := strings.Split(G.ScopeNameTransforms.Transform(name),g.scopeSepStr)
l.RLock()
sc := l.scopes.getScope(ns[0])
if sc != nil && len(ns) > 1 {
sc = sc.getScope(ns[1:])
}
l.RUnlock()
return sc
}
func (l *LoggerManager) AddScope(name string, options ...LoggerScopeFnc) (*LoggerScope,error) {
nm := G.ScopeNameTransforms.Transform(name)
ns := strings.Split(nm,g.scopeSepStr)
l.Lock()
sc := l.scopes.getScope(ns[0])
if sc == nil {
sc = newLoggerScope(nm,l.level,l,"",nil,options)
l.scopes = append(l.scopes,sc)
if len(ns) == 1 {
l.Unlock()
return sc,nil
}
} else if len(ns) == 1 {
l.Unlock()
return nil,G.ErrDuplicatedScope.WrapWithFieldString(errFieldScope,ns[0])
}
l.Unlock()
return sc.newScope(ns[1:],options)
}
func (l *LoggerManager) Fatal(msg string, err error, ops ...EntryFnc){
l.log(LevelFatal,msg,err,ops) }
func (l *LoggerManager) Error(msg string, err error, ops ...EntryFnc){
l.log(LevelError,msg,err,ops) }
func (l *LoggerManager) Warn (msg string, ops ...EntryFnc){
l.log(LevelWarn,msg,nil,ops) }
func (l *LoggerManager) Info (msg string, ops ...EntryFnc){
l.log(LevelInfo,msg,nil,ops) }
func (l *LoggerManager) Debug(msg string, ops ...EntryFnc){
l.log(LevelDebug,msg,nil,ops) }
func (l *LoggerManager) Data (msg string, data any, ops ...EntryFnc){
l.log(LevelData,msg,nil,[]EntryFnc{EntryWithData(data,ops...)}) }
func (l *LoggerManager) Log (entry *Entry) error {
if entry == nil {
return nil
}
l.Lock()
if l.state != StateStarted {
l.Unlock()
return G.ErrLoggerNotStarted
}
if !l.level.Has(entry.Level) {
l.Unlock()
return nil
}
er := l.logEntry(entry,false)
if er != nil {
l.handleQueue()
}
l.Unlock()
return er
}
func (l *LoggerManager) log (level Level, msg string, err error,options []EntryFnc) {
l.Lock()
if l.state != StateStarted || !l.level.Has(level){
l.Unlock()
return
}
er := l.logEntry(AcquireEntry(l,level,msg,err,options...),true)
if er != nil {
l.handleQueue()
}
l.Unlock()
return
}
func (l *LoggerManager) logEntry(entry *Entry, self bool) error {
if !l.filters.Filter(entry) {
return nil
}
if self {
l.incCount()
} else if entry.Logger == nil {
entry.Logger = l
}
l.extenders.ExtendEntry(entry)
er := l.handleLoggers(entry,func(c Logger, e *Entry) error { return c.Log(e) },G.FmtMsgLogErr)
if self {
if entry.Level == LevelFatal && l.onFatalFn != nil {
l.onFatalFn(l, entry)
}
ReleaseEntry(entry)
}
return er
}
func (l *LoggerManager) handleError (err error, entry *Entry) {
if err == nil {
return
}
l.errors = l.errors.Append(err)
if l.logErrors {
if entry == nil {
entry = AcquireEntry(l,LevelError,err.Error(),err)
}
l.queue.Push(entry)
}
if l.onErrorFn != nil {
l.onErrorFn(l,err)
}
}
func (l *LoggerManager) handleQueue() {
for en := l.queue.Pop(); en != nil; {
_ = l.logEntry(en,true)
en = l.queue.Pop()
}
}
func (l *LoggerManager) handleLoggers(entry *Entry, doFn func(c Logger, e *Entry) error, msg string) error {
var el errs.ErrorList
for _,co := range l.loggers {
if er := doFn(co,entry); er != nil {
var en *Entry
nm := co.Name()
ms := fmt.Sprintf(msg,nm)
ne := errs.NewErrMessage(er,msg)
if l.logErrors {
en = AcquireEntry(l,LevelError,ms,ne,
EntryWithExtender(l.extenders),
EntryWithExclude (nm),
EntryWithField (entryFieldLogger,nm,true))
}
l.handleError(er,en)
}
}
return errs.NewErrMultiIf(el)
}
func (l *LoggerManager) findLogger(name string) int {
for i :=0; i < len(l.loggers); i++ {
if l.loggers[i].Name() == name {
return i
}
}
return -1
}
func (l *LoggerManager) runLogger () {
for {
select {
case e := <- l.chanLog :
//todo
}
}
}
func LoggerManagerWithFilters (configFilters EntryFiltersFnc) LoggerManagerFnc {
return func(a *LoggerManager) {
configFilters(&a.filters) } }
func LoggerManagerWithOnFatal (onFatal LoggerManagerEntryFnc) LoggerManagerFnc {
return func(a *LoggerManager) {
a.onFatalFn = onFatal } }
func LoggerManagerWithOnError (onError LoggerManagerErrorFnc) LoggerManagerFnc {
return func(a *LoggerManager) {
a.onErrorFn = onError } }
func LoggerManagerWithExtender (extender ...EntryExtender) LoggerManagerFnc {
return func(a *LoggerManager) {
a.extenders = append(a.extenders,extender...) } }

Powered by TurnKey Linux.