github.com/gitbundle/modules@v0.0.0-20231025071548-85b91c5c3b01/log/multichannel.go (about) 1 // Copyright 2023 The GitBundle Inc. All rights reserved. 2 // Copyright 2017 The Gitea Authors. All rights reserved. 3 // Use of this source code is governed by a MIT-style 4 // license that can be found in the LICENSE file. 5 6 // Copyright 2020 The Gogs Authors. All rights reserved. 7 // Use of this source code is governed by a MIT-style 8 // license that can be found in the LICENSE file. 9 10 package log 11 12 import ( 13 "fmt" 14 "runtime" 15 "strings" 16 "time" 17 ) 18 19 // MultiChannelledLogger is default logger in the GitBundle application. 20 // it can contain several providers and log message into all providers. 21 type MultiChannelledLogger struct { 22 LevelLoggerLogger 23 *MultiChannelledLog 24 bufferLength int64 25 noCaller bool 26 } 27 28 // newLogger initializes and returns a new logger. 29 func newLogger(name string, buffer int64, noCaller bool) *MultiChannelledLogger { 30 l := &MultiChannelledLogger{ 31 MultiChannelledLog: NewMultiChannelledLog(name, buffer), 32 bufferLength: buffer, 33 noCaller: noCaller, 34 } 35 l.LevelLogger = l 36 return l 37 } 38 39 // SetLogger sets new logger instance with given logger provider and config. 40 func (l *MultiChannelledLogger) SetLogger(name, provider, config string) error { 41 eventLogger, err := NewChannelledLog(l.ctx, name, provider, config, l.bufferLength) 42 if err != nil { 43 return fmt.Errorf("Failed to create sublogger (%s): %v", name, err) 44 } 45 46 l.MultiChannelledLog.DelLogger(name) 47 48 err = l.MultiChannelledLog.AddLogger(eventLogger) 49 if err != nil { 50 if IsErrDuplicateName(err) { 51 return fmt.Errorf("Duplicate named sublogger %s %v", name, l.MultiChannelledLog.GetEventLoggerNames()) 52 } 53 return fmt.Errorf("Failed to add sublogger (%s): %v", name, err) 54 } 55 56 return nil 57 } 58 59 // DelLogger deletes a sublogger from this logger. 60 func (l *MultiChannelledLogger) DelLogger(name string) (bool, error) { 61 return l.MultiChannelledLog.DelLogger(name), nil 62 } 63 64 // Log msg at the provided level with the provided caller defined by skip (0 being the function that calls this function) 65 func (l *MultiChannelledLogger) Log(skip int, level Level, format string, v ...interface{}) error { 66 if l.GetLevel() > level { 67 return nil 68 } 69 70 var ( 71 caller string 72 stack string 73 filename string 74 line int 75 pc uintptr 76 ok bool 77 ) 78 79 if !l.noCaller { 80 caller = "?()" 81 pc, filename, line, ok = runtime.Caller(skip + 1) 82 if ok { 83 // Get caller function name. 84 fn := runtime.FuncForPC(pc) 85 if fn != nil { 86 caller = fn.Name() + "()" 87 } 88 } 89 if l.GetStacktraceLevel() <= level { 90 stack = Stack(skip + 1) 91 } 92 } 93 msg := format 94 if len(v) > 0 { 95 msg = ColorSprintf(format, v...) 96 } 97 labels := getGoroutineLabels() 98 if labels != nil { 99 pid, ok := labels["pid"] 100 if ok { 101 msg = "[" + ColorString(FgHiYellow) + pid + ColorString(Reset) + "] " + msg 102 } 103 } 104 105 return l.SendLog(level, caller, strings.TrimPrefix(filename, prefix), line, msg, stack) 106 } 107 108 // SendLog sends a log event at the provided level with the information given 109 func (l *MultiChannelledLogger) SendLog(level Level, caller, filename string, line int, msg, stack string) error { 110 if l.GetLevel() > level { 111 return nil 112 } 113 event := &Event{ 114 level: level, 115 caller: caller, 116 filename: filename, 117 line: line, 118 msg: msg, 119 time: time.Now(), 120 stacktrace: stack, 121 } 122 l.LogEvent(event) 123 return nil 124 }