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  }