1
0
Fork 0
forked from forgejo/forgejo
This commit is contained in:
techknowlogick 2021-02-28 18:08:33 -05:00 committed by GitHub
parent 030646eea4
commit 47f6a4ec3f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
947 changed files with 26119 additions and 7062 deletions

View file

@ -67,113 +67,64 @@ var _LEVEL_MAP = map[string]Level{
"none": NONE,
}
// cache logging enablement to improve runtime performance (reduces from multiple tests to a single test on each call)
var (
cachedDebug bool
cachedTrace bool
cachedRequest bool
cachedInfo bool
cachedWarn bool
cachedError bool
cachedSevere bool
cachedFatal bool
)
// maintain the cached logging state
func cacheLoggingChange() {
cachedDebug = !skipLogging(DEBUG)
cachedTrace = !skipLogging(TRACE)
cachedRequest = !skipLogging(REQUEST)
cachedInfo = !skipLogging(INFO)
cachedWarn = !skipLogging(WARN)
cachedError = !skipLogging(ERROR)
cachedSevere = !skipLogging(SEVERE)
cachedFatal = !skipLogging(FATAL)
}
func ParseLevel(name string) (level Level, ok bool) {
level, ok = _LEVEL_MAP[strings.ToLower(name)]
return
}
/*
Pair supports logging of key-value pairs. Keys beginning with _ are
reserved for the logger, e.g. _time, _level, _msg, and _rlevel. The
Pair APIs are designed to avoid heap allocation and garbage
collection.
*/
type Pairs []Pair
type Pair struct {
Name string
Value interface{}
}
/*
Map allows key-value pairs to be specified using map literals or data
structures. For example:
Errorm(msg, Map{...})
Map incurs heap allocation and garbage collection, so the Pair APIs
should be preferred.
*/
type Map map[string]interface{}
// Logger provides a common interface for logging libraries
type Logger interface {
/*
These APIs write all the given pairs in addition to standard logger keys.
*/
Logp(level Level, msg string, kv ...Pair)
// Higher performance
Loga(level Level, f func() string)
Debuga(f func() string)
Tracea(f func() string)
Requesta(rlevel Level, f func() string)
Infoa(f func() string)
Warna(f func() string)
Errora(f func() string)
Severea(f func() string)
Fatala(f func() string)
Debugp(msg string, kv ...Pair)
Tracep(msg string, kv ...Pair)
Requestp(rlevel Level, msg string, kv ...Pair)
Infop(msg string, kv ...Pair)
Warnp(msg string, kv ...Pair)
Errorp(msg string, kv ...Pair)
Severep(msg string, kv ...Pair)
Fatalp(msg string, kv ...Pair)
/*
These APIs write the fields in the given kv Map in addition to standard logger keys.
*/
Logm(level Level, msg string, kv Map)
Debugm(msg string, kv Map)
Tracem(msg string, kv Map)
Requestm(rlevel Level, msg string, kv Map)
Infom(msg string, kv Map)
Warnm(msg string, kv Map)
Errorm(msg string, kv Map)
Severem(msg string, kv Map)
Fatalm(msg string, kv Map)
/*
These APIs only write _msg, _time, _level, and other logger keys. If
the msg contains other fields, use the Pair or Map APIs instead.
*/
// Printf style
Logf(level Level, fmt string, args ...interface{})
Debugf(fmt string, args ...interface{})
Tracef(fmt string, args ...interface{})
Requestf(rlevel Level, fmt string, args ...interface{})
Infof(fmt string, args ...interface{})
Warnf(fmt string, args ...interface{})
Errorf(fmt string, args ...interface{})
Severef(fmt string, args ...interface{})
Fatalf(fmt string, args ...interface{})
/*
These APIs control the logging level
*/
SetLevel(Level) // Set the logging level
Level() Level // Get the current logging level
Level() Level // Get the current logging level
}
var logger Logger = nil
@ -205,169 +156,96 @@ func SetLogger(newLogger Logger) {
} else {
curLevel = newLogger.Level()
}
cacheLoggingChange()
}
func Logp(level Level, msg string, kv ...Pair) {
// we are using deferred unlocking here throughout as we have to do this
// for the anonymous function variants even though it would be more efficient
// to not do this for the printf style variants
// anonymous function variants
func Loga(level Level, f func() string) {
if skipLogging(level) {
return
}
loggerMutex.Lock()
defer loggerMutex.Unlock()
logger.Logp(level, msg, kv...)
logger.Loga(level, f)
}
func Debugp(msg string, kv ...Pair) {
if skipLogging(DEBUG) {
func Debuga(f func() string) {
if !cachedDebug {
return
}
loggerMutex.Lock()
defer loggerMutex.Unlock()
logger.Debugp(msg, kv...)
logger.Debuga(f)
}
func Tracep(msg string, kv ...Pair) {
if skipLogging(TRACE) {
func Tracea(f func() string) {
if !cachedTrace {
return
}
loggerMutex.Lock()
defer loggerMutex.Unlock()
logger.Tracep(msg, kv...)
logger.Tracea(f)
}
func Requestp(rlevel Level, msg string, kv ...Pair) {
if skipLogging(REQUEST) {
func Requesta(rlevel Level, f func() string) {
if !cachedRequest {
return
}
loggerMutex.Lock()
defer loggerMutex.Unlock()
logger.Requestp(rlevel, msg, kv...)
logger.Requesta(rlevel, f)
}
func Infop(msg string, kv ...Pair) {
if skipLogging(INFO) {
func Infoa(f func() string) {
if !cachedInfo {
return
}
loggerMutex.Lock()
defer loggerMutex.Unlock()
logger.Infop(msg, kv...)
logger.Infoa(f)
}
func Warnp(msg string, kv ...Pair) {
if skipLogging(WARN) {
func Warna(f func() string) {
if !cachedWarn {
return
}
loggerMutex.Lock()
defer loggerMutex.Unlock()
logger.Warnp(msg, kv...)
logger.Warna(f)
}
func Errorp(msg string, kv ...Pair) {
if skipLogging(ERROR) {
func Errora(f func() string) {
if !cachedError {
return
}
loggerMutex.Lock()
defer loggerMutex.Unlock()
logger.Errorp(msg, kv...)
logger.Errora(f)
}
func Severep(msg string, kv ...Pair) {
if skipLogging(SEVERE) {
func Severea(f func() string) {
if !cachedSevere {
return
}
loggerMutex.Lock()
defer loggerMutex.Unlock()
logger.Severep(msg, kv...)
logger.Severea(f)
}
func Fatalp(msg string, kv ...Pair) {
if skipLogging(FATAL) {
func Fatala(f func() string) {
if !cachedFatal {
return
}
loggerMutex.Lock()
defer loggerMutex.Unlock()
logger.Fatalp(msg, kv...)
logger.Fatala(f)
}
func Logm(level Level, msg string, kv Map) {
if skipLogging(level) {
return
}
loggerMutex.Lock()
defer loggerMutex.Unlock()
logger.Logm(level, msg, kv)
}
func Debugm(msg string, kv Map) {
if skipLogging(DEBUG) {
return
}
loggerMutex.Lock()
defer loggerMutex.Unlock()
logger.Debugm(msg, kv)
}
func Tracem(msg string, kv Map) {
if skipLogging(TRACE) {
return
}
loggerMutex.Lock()
defer loggerMutex.Unlock()
logger.Tracem(msg, kv)
}
func Requestm(rlevel Level, msg string, kv Map) {
if skipLogging(REQUEST) {
return
}
loggerMutex.Lock()
defer loggerMutex.Unlock()
logger.Requestm(rlevel, msg, kv)
}
func Infom(msg string, kv Map) {
if skipLogging(INFO) {
return
}
loggerMutex.Lock()
defer loggerMutex.Unlock()
logger.Infom(msg, kv)
}
func Warnm(msg string, kv Map) {
if skipLogging(WARN) {
return
}
loggerMutex.Lock()
defer loggerMutex.Unlock()
logger.Warnm(msg, kv)
}
func Errorm(msg string, kv Map) {
if skipLogging(ERROR) {
return
}
loggerMutex.Lock()
defer loggerMutex.Unlock()
logger.Errorm(msg, kv)
}
func Severem(msg string, kv Map) {
if skipLogging(SEVERE) {
return
}
loggerMutex.Lock()
defer loggerMutex.Unlock()
logger.Severem(msg, kv)
}
func Fatalm(msg string, kv Map) {
if skipLogging(FATAL) {
return
}
loggerMutex.Lock()
defer loggerMutex.Unlock()
logger.Fatalm(msg, kv)
}
// printf-style variants
func Logf(level Level, fmt string, args ...interface{}) {
if skipLogging(level) {
@ -379,7 +257,7 @@ func Logf(level Level, fmt string, args ...interface{}) {
}
func Debugf(fmt string, args ...interface{}) {
if skipLogging(DEBUG) {
if !cachedDebug {
return
}
loggerMutex.Lock()
@ -388,7 +266,7 @@ func Debugf(fmt string, args ...interface{}) {
}
func Tracef(fmt string, args ...interface{}) {
if skipLogging(TRACE) {
if !cachedTrace {
return
}
loggerMutex.Lock()
@ -397,7 +275,7 @@ func Tracef(fmt string, args ...interface{}) {
}
func Requestf(rlevel Level, fmt string, args ...interface{}) {
if skipLogging(REQUEST) {
if !cachedRequest {
return
}
loggerMutex.Lock()
@ -406,7 +284,7 @@ func Requestf(rlevel Level, fmt string, args ...interface{}) {
}
func Infof(fmt string, args ...interface{}) {
if skipLogging(INFO) {
if !cachedInfo {
return
}
loggerMutex.Lock()
@ -415,7 +293,7 @@ func Infof(fmt string, args ...interface{}) {
}
func Warnf(fmt string, args ...interface{}) {
if skipLogging(WARN) {
if !cachedWarn {
return
}
loggerMutex.Lock()
@ -424,7 +302,7 @@ func Warnf(fmt string, args ...interface{}) {
}
func Errorf(fmt string, args ...interface{}) {
if skipLogging(ERROR) {
if !cachedError {
return
}
loggerMutex.Lock()
@ -433,7 +311,7 @@ func Errorf(fmt string, args ...interface{}) {
}
func Severef(fmt string, args ...interface{}) {
if skipLogging(SEVERE) {
if !cachedSevere {
return
}
loggerMutex.Lock()
@ -442,7 +320,7 @@ func Severef(fmt string, args ...interface{}) {
}
func Fatalf(fmt string, args ...interface{}) {
if skipLogging(FATAL) {
if !cachedFatal {
return
}
loggerMutex.Lock()
@ -455,6 +333,7 @@ func SetLevel(level Level) {
defer loggerMutex.Unlock()
logger.SetLevel(level)
curLevel = level
cacheLoggingChange()
}
func LogLevel() Level {

View file

@ -10,11 +10,11 @@
package logging
import (
"bytes"
"encoding/json"
"fmt"
"io"
"log"
"strings"
"time"
)
@ -50,115 +50,61 @@ func NewLogger(out io.Writer, lvl Level, fmtLogging LogEntryFormatter, fmtArgs .
return logger
}
func (gl *goLogger) Logp(level Level, msg string, kv ...Pair) {
// anonymous function variants
func (gl *goLogger) Loga(level Level, f func() string) {
if gl.logger == nil {
return
}
if level <= gl.level {
e := newLogEntry(msg, level)
copyPairs(e, kv)
gl.log(e)
gl.log(level, NONE, f())
}
}
func (gl *goLogger) Debugp(msg string, kv ...Pair) {
gl.Logp(DEBUG, msg, kv...)
func (gl *goLogger) Debuga(f func() string) {
gl.Loga(DEBUG, f)
}
func (gl *goLogger) Tracep(msg string, kv ...Pair) {
gl.Logp(TRACE, msg, kv...)
func (gl *goLogger) Tracea(f func() string) {
gl.Loga(TRACE, f)
}
func (gl *goLogger) Requestp(rlevel Level, msg string, kv ...Pair) {
func (gl *goLogger) Requesta(rlevel Level, f func() string) {
if gl.logger == nil {
return
}
if REQUEST <= gl.level {
e := newLogEntry(msg, REQUEST)
e.Rlevel = rlevel
copyPairs(e, kv)
gl.log(e)
gl.log(REQUEST, rlevel, f())
}
}
func (gl *goLogger) Infop(msg string, kv ...Pair) {
gl.Logp(INFO, msg, kv...)
func (gl *goLogger) Infoa(f func() string) {
gl.Loga(INFO, f)
}
func (gl *goLogger) Warnp(msg string, kv ...Pair) {
gl.Logp(WARN, msg, kv...)
func (gl *goLogger) Warna(f func() string) {
gl.Loga(WARN, f)
}
func (gl *goLogger) Errorp(msg string, kv ...Pair) {
gl.Logp(ERROR, msg, kv...)
func (gl *goLogger) Errora(f func() string) {
gl.Loga(ERROR, f)
}
func (gl *goLogger) Severep(msg string, kv ...Pair) {
gl.Logp(SEVERE, msg, kv...)
func (gl *goLogger) Severea(f func() string) {
gl.Loga(SEVERE, f)
}
func (gl *goLogger) Fatalp(msg string, kv ...Pair) {
gl.Logp(FATAL, msg, kv...)
func (gl *goLogger) Fatala(f func() string) {
gl.Loga(FATAL, f)
}
func (gl *goLogger) Logm(level Level, msg string, kv Map) {
if gl.logger == nil {
return
}
if level <= gl.level {
e := newLogEntry(msg, level)
e.Data = kv
gl.log(e)
}
}
func (gl *goLogger) Debugm(msg string, kv Map) {
gl.Logm(DEBUG, msg, kv)
}
func (gl *goLogger) Tracem(msg string, kv Map) {
gl.Logm(TRACE, msg, kv)
}
func (gl *goLogger) Requestm(rlevel Level, msg string, kv Map) {
if gl.logger == nil {
return
}
if REQUEST <= gl.level {
e := newLogEntry(msg, REQUEST)
e.Rlevel = rlevel
e.Data = kv
gl.log(e)
}
}
func (gl *goLogger) Infom(msg string, kv Map) {
gl.Logm(INFO, msg, kv)
}
func (gl *goLogger) Warnm(msg string, kv Map) {
gl.Logm(WARN, msg, kv)
}
func (gl *goLogger) Errorm(msg string, kv Map) {
gl.Logm(ERROR, msg, kv)
}
func (gl *goLogger) Severem(msg string, kv Map) {
gl.Logm(SEVERE, msg, kv)
}
func (gl *goLogger) Fatalm(msg string, kv Map) {
gl.Logm(FATAL, msg, kv)
}
// printf-style variants
func (gl *goLogger) Logf(level Level, format string, args ...interface{}) {
if gl.logger == nil {
return
}
if level <= gl.level {
e := newLogEntry(fmt.Sprintf(format, args...), level)
gl.log(e)
gl.log(level, NONE, fmt.Sprintf(format, args...))
}
}
@ -175,9 +121,7 @@ func (gl *goLogger) Requestf(rlevel Level, format string, args ...interface{}) {
return
}
if REQUEST <= gl.level {
e := newLogEntry(fmt.Sprintf(format, args...), REQUEST)
e.Rlevel = rlevel
gl.log(e)
gl.log(REQUEST, rlevel, fmt.Sprintf(format, args...))
}
}
@ -209,37 +153,13 @@ func (gl *goLogger) SetLevel(level Level) {
gl.level = level
}
func (gl *goLogger) log(newEntry *logEntry) {
s := gl.entryFormatter.format(newEntry)
gl.logger.Print(s)
}
type logEntry struct {
Time string
Level Level
Rlevel Level
Message string
Data Map
}
func newLogEntry(msg string, level Level) *logEntry {
return &logEntry{
Time: time.Now().Format("2006-01-02T15:04:05.000-07:00"), // time.RFC3339 with milliseconds
Level: level,
Rlevel: NONE,
Message: msg,
}
}
func copyPairs(newEntry *logEntry, pairs []Pair) {
newEntry.Data = make(Map, len(pairs))
for _, p := range pairs {
newEntry.Data[p.Name] = p.Value
}
func (gl *goLogger) log(level Level, rlevel Level, msg string) {
tm := time.Now().Format("2006-01-02T15:04:05.000-07:00") // time.RFC3339 with milliseconds
gl.logger.Print(gl.entryFormatter.format(tm, level, rlevel, msg))
}
type formatter interface {
format(*logEntry) string
format(string, Level, Level, string) string
}
type textFormatter struct {
@ -247,24 +167,20 @@ type textFormatter struct {
// ex. 2016-02-10T09:15:25.498-08:00 [INFO] This is a message from test in text format
func (*textFormatter) format(newEntry *logEntry) string {
b := &bytes.Buffer{}
appendValue(b, newEntry.Time)
if newEntry.Rlevel != NONE {
fmt.Fprintf(b, "[%s,%s] ", newEntry.Level.String(), newEntry.Rlevel.String())
func (*textFormatter) format(tm string, level Level, rlevel Level, msg string) string {
b := &strings.Builder{}
appendValue(b, tm)
if rlevel != NONE {
fmt.Fprintf(b, "[%s,%s] ", level.String(), rlevel.String())
} else {
fmt.Fprintf(b, "[%s] ", newEntry.Level.String())
}
appendValue(b, newEntry.Message)
for key, value := range newEntry.Data {
appendKeyValue(b, key, value)
fmt.Fprintf(b, "[%s] ", level.String())
}
appendValue(b, msg)
b.WriteByte('\n')
s := bytes.NewBuffer(b.Bytes())
return s.String()
return b.String()
}
func appendValue(b *bytes.Buffer, value interface{}) {
func appendValue(b *strings.Builder, value interface{}) {
if _, ok := value.(string); ok {
fmt.Fprintf(b, "%s ", value)
} else {
@ -277,23 +193,19 @@ type keyvalueFormatter struct {
// ex. _time=2016-02-10T09:15:25.498-08:00 _level=INFO _msg=This is a message from test in key-value format
func (*keyvalueFormatter) format(newEntry *logEntry) string {
b := &bytes.Buffer{}
appendKeyValue(b, _TIME, newEntry.Time)
appendKeyValue(b, _LEVEL, newEntry.Level.String())
if newEntry.Rlevel != NONE {
appendKeyValue(b, _RLEVEL, newEntry.Rlevel.String())
}
appendKeyValue(b, _MSG, newEntry.Message)
for key, value := range newEntry.Data {
appendKeyValue(b, key, value)
func (*keyvalueFormatter) format(tm string, level Level, rlevel Level, msg string) string {
b := &strings.Builder{}
appendKeyValue(b, _TIME, tm)
appendKeyValue(b, _LEVEL, level.String())
if rlevel != NONE {
appendKeyValue(b, _RLEVEL, rlevel.String())
}
appendKeyValue(b, _MSG, msg)
b.WriteByte('\n')
s := bytes.NewBuffer(b.Bytes())
return s.String()
return b.String()
}
func appendKeyValue(b *bytes.Buffer, key, value interface{}) {
func appendKeyValue(b *strings.Builder, key, value interface{}) {
if _, ok := value.(string); ok {
fmt.Fprintf(b, "%v=%s ", key, value)
} else {
@ -306,19 +218,19 @@ type jsonFormatter struct {
// ex. {"_level":"INFO","_msg":"This is a message from test in json format","_time":"2016-02-10T09:12:59.518-08:00"}
func (*jsonFormatter) format(newEntry *logEntry) string {
if newEntry.Data == nil {
newEntry.Data = make(Map, 5)
func (*jsonFormatter) format(tm string, level Level, rlevel Level, msg string) string {
data := make(map[string]interface{}, 4)
data[_TIME] = tm
data[_LEVEL] = level.String()
if rlevel != NONE {
data[_RLEVEL] = rlevel.String()
}
newEntry.Data[_TIME] = newEntry.Time
newEntry.Data[_LEVEL] = newEntry.Level.String()
if newEntry.Rlevel != NONE {
newEntry.Data[_RLEVEL] = newEntry.Rlevel.String()
}
newEntry.Data[_MSG] = newEntry.Message
serialized, _ := json.Marshal(newEntry.Data)
s := bytes.NewBuffer(append(serialized, '\n'))
return s.String()
data[_MSG] = msg
serialized, _ := json.Marshal(data)
var b strings.Builder
b.Write(serialized)
b.WriteByte('\n')
return b.String()
}
type ComponentCallback func() string
@ -345,21 +257,17 @@ func (level Level) UniformString() string {
return _LEVEL_UNIFORM[level]
}
func (uf *uniformFormatter) format(newEntry *logEntry) string {
b := &bytes.Buffer{}
appendValue(b, newEntry.Time)
func (uf *uniformFormatter) format(tm string, level Level, rlevel Level, msg string) string {
b := &strings.Builder{}
appendValue(b, tm)
component := uf.callback()
if newEntry.Rlevel != NONE {
if rlevel != NONE {
// not really any accommodation for a composite level in the uniform standard; just output as abbr,abbr
fmt.Fprintf(b, "%s,%s %s ", newEntry.Level.UniformString(), newEntry.Rlevel.UniformString(), component)
fmt.Fprintf(b, "%s,%s %s ", level.UniformString(), rlevel.UniformString(), component)
} else {
fmt.Fprintf(b, "%s %s ", newEntry.Level.UniformString(), component)
}
appendValue(b, newEntry.Message)
for key, value := range newEntry.Data {
appendKeyValue(b, key, value)
fmt.Fprintf(b, "%s %s ", level.UniformString(), component)
}
appendValue(b, msg)
b.WriteByte('\n')
s := bytes.NewBuffer(b.Bytes())
return s.String()
return b.String()
}