// ------------------------------------------------------------------------ // Project atila // Active Thing (activething.com) git.activething.com/go // // File name scope.go // Created by DEV // Modified 22/02/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 logs import ( "activething.com/go/gogo/core/opts" "fmt" "strings" ) type ( Scope struct { loggerLevel level Level mode ScopeMode path string nodes [][]byte parent Loggable children []*Scope aggregators EntryAggregators } ) func newScope (name string, level Level, parent Loggable, path string, nodes [][]byte, options ...opts.OptionFnc[Scope]) *Scope { if path != "" { path = fmt.Sprintf("%s%c%s",path,scopeSep,name) } else { path = name } return opts.Apply[Scope](&Scope { loggerLevel: *newLoggerLevel(name,level), parent : parent, nodes : append(nodes,[]byte(name)), path : path, }, options ...) } func (s *Scope) Mode () (m ScopeMode) { s.mux.RLock() m = s.mode s.mux.RUnlock() return } func (s *Scope) SetMode(mode ScopeMode) { s.mux.Lock() s.mode = mode s.mux.Unlock() } func (s *Scope) Level() Level { return s.level } func (s *Scope) Path () string { return s.path } func (s *Scope) Nodes () [][]byte { return s.nodes } func (s *Scope) NewChildScope (path string, options ...opts.OptionFnc[Scope]) (*Scope,error) { s.mux.Lock() sc,er := s.newChildScope(strings.Split(strings.ToLower(path),string(scopeSep)),options ...) s.mux.Unlock() return sc,er } func (s *Scope) newChildScope (path []string, options ...opts.OptionFnc[Scope])(*Scope,error){ sc := s.getChildScope(path[0]) if sc == nil { sc = newScope(path[0],s.level, s, s.path, s.nodes, options ...) s.children = append (s.children, sc) if len(path) == 1 { return sc, nil } } else if len(path) == 1 { return nil,G.ErrDuplicatedScope } return sc.newChildScope(path[1:],options...) } func (s *Scope) GetScope (name string) *Scope { return s.getScope(strings.Split(strings.ToLower(name),string(scopeSep))) } func (s *Scope) getScope (nodes []string) *Scope { s.mux.RLock() sc := s.getChildScope(nodes[0]) if sc != nil { if len(nodes) > 1 { sc = sc.getScope(nodes[1:]) } } s.mux.RUnlock() return sc } func (s *Scope) getChildScope (name string) *Scope { if i := s.findChildScope(name); i != -1 { return s.children[i] } return nil } func (s *Scope) findChildScope (name string) int { for i,s := range s.children { if name == s.name { return i } } return -1 } func (s *Scope) Log (entry *Entry) error { s.mux.Lock() if s.mode.IsFilter() && s.level.Has(entry.Level) { s.mux.Unlock() return nil } if s.mode.IsCascade() { s.aggregators.Apply(entry) } s.mux.Unlock() return s.parent.Log(entry) } func (s *Scope) log(lvl Level, msg string, err error,options ...EntryFnc){ s.mux.Lock() if !s.level.Has(lvl) { s.mux.Unlock() return } en := s.aggregators.Apply(NewEntry(nil,lvl,msg,err,options...)) en.Scope = s.path en.Scopes= s.nodes s.mux.Unlock() s.parent.Log(en) G.entryPool.Put(en) }