github.com/imran-kn/cilium-fork@v1.6.9/pkg/debug/subsystem.go (about) 1 // Copyright 2018 Authors of Cilium 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package debug 16 17 import ( 18 "fmt" 19 20 "github.com/cilium/cilium/pkg/lock" 21 ) 22 23 // StatusFunc is a function returning the debug status of a subsytem. It is 24 // passed into RegisterStatusFunc(). 25 type StatusFunc func() string 26 27 // StatusMap is the collection of debug status of all subsystems. The key is 28 // the subsystem name. The value is the subsystem debug status. 29 type StatusMap map[string]string 30 31 // StatusObject is the interface an object must impelement to be able to be 32 // passed into RegisterStatusObject(). 33 type StatusObject interface { 34 // DebugStatus() is the equivalent of StatusFunc. It must return the 35 // debug status as a string. 36 DebugStatus() string 37 } 38 39 type functionMap map[string]StatusFunc 40 41 type statusFunctions struct { 42 functions functionMap 43 mutex lock.RWMutex 44 } 45 46 func newStatusFunctions() statusFunctions { 47 return statusFunctions{ 48 functions: functionMap{}, 49 } 50 } 51 52 func (s *statusFunctions) register(name string, fn StatusFunc) error { 53 s.mutex.Lock() 54 defer s.mutex.Unlock() 55 56 if _, ok := s.functions[name]; ok { 57 return fmt.Errorf("subsystem already registered") 58 } 59 60 s.functions[name] = fn 61 62 return nil 63 } 64 65 func (s *statusFunctions) registerStatusObject(name string, obj StatusObject) error { 66 return s.register(name, func() string { return obj.DebugStatus() }) 67 } 68 69 func (s *statusFunctions) collectStatus() StatusMap { 70 fnCopy := functionMap{} 71 72 // Make a copy to not hold the mutex while collecting the status 73 s.mutex.RLock() 74 for name, fn := range s.functions { 75 fnCopy[name] = fn 76 } 77 s.mutex.RUnlock() 78 79 status := StatusMap{} 80 81 for name, fn := range fnCopy { 82 status[name] = fn() 83 } 84 85 return status 86 } 87 88 var globalStatusFunctions = newStatusFunctions() 89 90 // RegisterStatusFunc registers a subsystem and associates a status function to 91 // call for debug status collection 92 func RegisterStatusFunc(name string, fn StatusFunc) error { 93 return globalStatusFunctions.register(name, fn) 94 } 95 96 // RegisterStatusObject registers a subsystem and associated a status object on 97 // which DebugStatus() is called to collect debug status 98 func RegisterStatusObject(name string, obj StatusObject) error { 99 return globalStatusFunctions.registerStatusObject(name, obj) 100 } 101 102 // CollectSubsystemStatus collects the status of all subsystems and returns it 103 func CollectSubsystemStatus() StatusMap { 104 return globalStatusFunctions.collectStatus() 105 }