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