github.com/voedger/voedger@v0.0.0-20240520144910-273e84102129/pkg/goutils/logger/impl.go (about)

     1  /*
     2   * Copyright (c) 2020-present unTill Pro, Ltd.
     3   * @author Maxim Geraskin
     4   *
     5   * This source code is licensed under the MIT license found in the
     6   * LICENSE file in the root directory of this source tree.
     7   */
     8  
     9  package logger
    10  
    11  import (
    12  	"fmt"
    13  	"runtime"
    14  	"strings"
    15  	"sync/atomic"
    16  )
    17  
    18  const (
    19  	globalSkipStackFramesCount = 4
    20  )
    21  
    22  const (
    23  	errorPrefix   = "*****"
    24  	warningPrefix = "!!!"
    25  	infoPrefix    = "==="
    26  	verbosePrefix = "---"
    27  	tracePrefix   = "..."
    28  )
    29  
    30  var globalLogPrinter = logPrinter{logLevel: LogLevelInfo}
    31  
    32  type logPrinter struct {
    33  	logLevel TLogLevel
    34  }
    35  
    36  func isEnabled(logLevel TLogLevel) bool {
    37  	curLogLevel := TLogLevel(atomic.LoadInt32((*int32)(&globalLogPrinter.logLevel)))
    38  	return curLogLevel >= logLevel
    39  }
    40  
    41  func (p *logPrinter) getFuncName(skipCount int) (funcName string, line int) {
    42  	var fn string
    43  	pc, _, line, ok := runtime.Caller(skipCount)
    44  	details := runtime.FuncForPC(pc)
    45  	if ok && details != nil {
    46  		elems := strings.Split(details.Name(), "/")
    47  		if len(elems) > 0 {
    48  			fn = elems[len(elems)-1]
    49  		}
    50  	}
    51  	return fn, line
    52  }
    53  
    54  func (p *logPrinter) getFormattedMsg(msgType string, funcName string, line int, args ...interface{}) string {
    55  	out := "01/02 15:04:05.000"
    56  	out += ": " + msgType
    57  	out += fmt.Sprintf(": [%v:%v]:", funcName, line)
    58  	if len(args) > 0 {
    59  		var s string
    60  		for _, arg := range args {
    61  			s += fmt.Sprint(" ", arg)
    62  		}
    63  		out += s
    64  	}
    65  	return out
    66  }
    67  
    68  func (p *logPrinter) print(skipStackFrames int, level TLogLevel, msgType string, args ...interface{}) {
    69  	funcName, line := p.getFuncName(skipStackFrames + globalSkipStackFramesCount)
    70  	out := p.getFormattedMsg(msgType, funcName, line, args...)
    71  
    72  	PrintLine(level, out)
    73  }
    74  
    75  func getLevelPrefix(level TLogLevel) string {
    76  	switch level {
    77  	case LogLevelError:
    78  		return errorPrefix
    79  	case LogLevelWarning:
    80  		return warningPrefix
    81  	case LogLevelInfo:
    82  		return infoPrefix
    83  	case LogLevelVerbose:
    84  		return verbosePrefix
    85  	case LogLevelTrace:
    86  		return tracePrefix
    87  	}
    88  	return ""
    89  }
    90  
    91  func printIfLevel(skipStackFrames int, level TLogLevel, args ...interface{}) {
    92  	if isEnabled(level) {
    93  		globalLogPrinter.print(skipStackFrames, level, getLevelPrefix(level), args...)
    94  	}
    95  }