* 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.
+ *
+ * This source code is part of the near-RT RIC (RAN Intelligent Controller)
+ * platform project (RICP).
*/
// Package golog implements a simple structured logging with MDC (Mapped Diagnostics Context) support.
"encoding/json"
"fmt"
"io"
+ "io/ioutil"
+ "k8s.io/utils/inotify"
"os"
+ "path/filepath"
+ "strconv"
+ "strings"
"sync"
+ "syscall"
"time"
)
// MdcLogger is the logger instance, created with InitLogger() function.
type MdcLogger struct {
- proc string
- writer io.Writer
- mdc map[string]string
- mutex sync.Mutex
- level Level
+ proc string
+ writer io.Writer
+ mdc map[string]string
+ mutex sync.Mutex
+ level Level
+ init_done int
}
type logEntry struct {
}
func initLogger(proc string, writer io.Writer) (*MdcLogger, error) {
- return &MdcLogger{proc: proc, writer: writer, mdc: make(map[string]string), level: DEBUG}, nil
+ return &MdcLogger{proc: proc, writer: writer, mdc: make(map[string]string), level: DEBUG, init_done: 0}, nil
}
// InitLogger is the init routine which returns a new logger instance.
defer l.mutex.Unlock()
l.mdc = make(map[string]string)
}
+
+func (l *MdcLogger) MdcUpdate(key string, value string) {
+ _, ok := l.MdcGet(key)
+ if ok {
+ l.MdcRemove(key)
+ }
+ l.MdcAdd(key, value)
+}
+
+func (l *MdcLogger) ParseFileContent(fileName string) {
+ data, err := ioutil.ReadFile(fileName)
+ if err != nil {
+ fmt.Println("File reading error", err)
+ return
+ }
+ for _, lineData := range strings.Split(string(data), "\n") {
+ if strings.Contains(lineData, "log-level:") {
+ var level = ERR
+ strList := strings.Split(lineData, ":")
+ if strings.Contains(strings.ToUpper(strList[1]), "DEBUG") {
+ level = DEBUG
+ } else if strings.Contains(strings.ToUpper(strList[1]), "INFO") {
+ level = INFO
+ } else if strings.Contains(strings.ToUpper(strList[1]), "ERR") {
+ level = ERR
+ } else if strings.Contains(strings.ToUpper(strList[1]), "WARN") {
+ level = WARN
+ }
+ l.LevelSet(level)
+ }
+ }
+}
+
+func (l *MdcLogger) watch_changes(watcher *inotify.Watcher, fileName string) {
+ for {
+ select {
+ case ev := <-watcher.Event:
+ if strings.Contains(ev.Name, filepath.Dir(fileName)) {
+ l.ParseFileContent(fileName)
+ }
+ case err := <-watcher.Error:
+ fmt.Println("error:", err)
+ }
+ }
+}
+
+func (l *MdcLogger) readEnvVar(envKey string) string {
+ envValue, provided := os.LookupEnv(envKey)
+ if !provided {
+ envValue = ""
+ }
+ return envValue
+}
+
+func (l *MdcLogger) Mdclog_format_initialize(logFileMonitor int) int {
+ ret := -1
+ logFields := []string{"SYSTEM_NAME", "HOST_NAME", "SERVICE_NAME", "CONTAINER_NAME", "POD_NAME"}
+ for _, envKey := range logFields {
+ envValue := l.readEnvVar(envKey)
+ l.MdcUpdate(envKey, envValue)
+ }
+ l.MdcUpdate("PID", strconv.Itoa(os.Getpid()))
+ if logFileMonitor > 0 {
+ watchPath := l.readEnvVar("CONFIG_MAP_NAME")
+ _, err := os.Stat(watchPath)
+ if !os.IsNotExist(err) {
+ if l.init_done == 0 {
+ l.mutex.Lock()
+ l.init_done = 1
+ l.mutex.Unlock()
+ watcher, err := inotify.NewWatcher()
+ if err != nil {
+ return -1
+ }
+ err = watcher.AddWatch(filepath.Dir(watchPath), syscall.IN_CLOSE_WRITE|syscall.IN_CREATE|syscall.IN_CLOSE)
+ if err != nil {
+ return -1
+ }
+ l.ParseFileContent(watchPath)
+ go l.watch_changes(watcher, watchPath)
+ ret = 0
+ }
+ }
+ }
+ return ret
+}