2014-02-12 14:54:09 -05:00
// Copyright 2014 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package log
import (
2020-07-06 01:07:07 +01:00
"fmt"
2014-05-25 20:11:25 -04:00
"os"
2014-07-26 00:24:27 -04:00
"runtime"
"strings"
2019-09-17 17:39:37 +08:00
"sync"
2014-02-12 14:54:09 -05:00
)
2019-09-17 17:39:37 +08:00
type loggerMap struct {
sync . Map
}
2020-10-31 05:36:46 +00:00
func ( m * loggerMap ) Load ( k string ) ( * MultiChannelledLogger , bool ) {
2019-09-17 17:39:37 +08:00
v , ok := m . Map . Load ( k )
if ! ok {
return nil , false
}
2020-10-31 05:36:46 +00:00
l , ok := v . ( * MultiChannelledLogger )
2019-09-17 17:39:37 +08:00
return l , ok
}
2020-10-31 05:36:46 +00:00
func ( m * loggerMap ) Store ( k string , v * MultiChannelledLogger ) {
2019-09-17 17:39:37 +08:00
m . Map . Store ( k , v )
}
func ( m * loggerMap ) Delete ( k string ) {
m . Map . Delete ( k )
}
2014-03-25 07:47:04 -04:00
var (
2019-04-02 08:48:31 +01:00
// DEFAULT is the name of the default logger
DEFAULT = "default"
// NamedLoggers map of named loggers
2019-09-17 17:39:37 +08:00
NamedLoggers loggerMap
2019-06-01 16:00:21 +01:00
prefix string
2014-03-25 07:47:04 -04:00
)
2014-02-12 14:54:09 -05:00
2019-04-02 08:48:31 +01:00
// NewLogger create a logger for the default logger
2020-10-31 05:36:46 +00:00
func NewLogger ( bufLen int64 , name , provider , config string ) * MultiChannelledLogger {
2019-04-02 08:48:31 +01:00
err := NewNamedLogger ( DEFAULT , bufLen , name , provider , config )
if err != nil {
CriticalWithSkip ( 1 , "Unable to create default logger: %v" , err )
panic ( err )
2014-05-11 14:37:12 -04:00
}
2019-09-17 17:39:37 +08:00
l , _ := NamedLoggers . Load ( DEFAULT )
return l
2019-04-02 08:48:31 +01:00
}
// NewNamedLogger creates a new named logger for a given configuration
func NewNamedLogger ( name string , bufLen int64 , subname , provider , config string ) error {
2019-09-17 17:39:37 +08:00
logger , ok := NamedLoggers . Load ( name )
2019-04-02 08:48:31 +01:00
if ! ok {
logger = newLogger ( name , bufLen )
2019-09-17 17:39:37 +08:00
NamedLoggers . Store ( name , logger )
2014-05-11 14:37:12 -04:00
}
2019-04-02 08:48:31 +01:00
return logger . SetLogger ( subname , provider , config )
}
// DelNamedLogger closes and deletes the named logger
func DelNamedLogger ( name string ) {
2019-09-17 17:39:37 +08:00
l , ok := NamedLoggers . Load ( name )
2019-04-02 08:48:31 +01:00
if ok {
2019-09-17 17:39:37 +08:00
NamedLoggers . Delete ( name )
2019-04-02 08:48:31 +01:00
l . Close ( )
2014-06-20 00:25:23 -04:00
}
2014-02-12 14:54:09 -05:00
}
2019-04-02 08:48:31 +01:00
// DelLogger removes the named sublogger from the default logger
func DelLogger ( name string ) error {
2019-09-17 17:39:37 +08:00
logger , _ := NamedLoggers . Load ( DEFAULT )
2019-04-02 08:48:31 +01:00
found , err := logger . DelLogger ( name )
if ! found {
Trace ( "Log %s not found, no need to delete" , name )
2017-01-17 07:02:35 +01:00
}
2019-04-02 08:48:31 +01:00
return err
}
2017-04-03 10:22:26 +08:00
2019-04-02 08:48:31 +01:00
// GetLogger returns either a named logger or the default logger
2020-10-31 05:36:46 +00:00
func GetLogger ( name string ) * MultiChannelledLogger {
2019-09-17 17:39:37 +08:00
logger , ok := NamedLoggers . Load ( name )
2019-04-02 08:48:31 +01:00
if ok {
return logger
}
2019-09-17 17:39:37 +08:00
logger , _ = NamedLoggers . Load ( DEFAULT )
return logger
2017-01-17 07:02:35 +01:00
}
2019-04-02 08:48:31 +01:00
// GetLevel returns the minimum logger level
func GetLevel ( ) Level {
2019-09-17 17:39:37 +08:00
l , _ := NamedLoggers . Load ( DEFAULT )
return l . GetLevel ( )
2019-04-02 08:48:31 +01:00
}
// GetStacktraceLevel returns the minimum logger level
func GetStacktraceLevel ( ) Level {
2019-09-17 17:39:37 +08:00
l , _ := NamedLoggers . Load ( DEFAULT )
return l . GetStacktraceLevel ( )
2014-06-20 01:14:54 -04:00
}
2016-11-26 19:53:29 +08:00
// Trace records trace log
2014-02-18 17:48:02 -05:00
func Trace ( format string , v ... interface { } ) {
2019-04-02 08:48:31 +01:00
Log ( 1 , TRACE , format , v ... )
}
// IsTrace returns true if at least one logger is TRACE
func IsTrace ( ) bool {
return GetLevel ( ) <= TRACE
2014-02-18 17:48:02 -05:00
}
2016-11-26 19:53:29 +08:00
// Debug records debug log
2014-03-23 12:16:17 -04:00
func Debug ( format string , v ... interface { } ) {
2019-04-02 08:48:31 +01:00
Log ( 1 , DEBUG , format , v ... )
2014-03-23 12:16:17 -04:00
}
2019-04-02 08:48:31 +01:00
// IsDebug returns true if at least one logger is DEBUG
func IsDebug ( ) bool {
return GetLevel ( ) <= DEBUG
2014-02-12 14:54:09 -05:00
}
2014-02-18 17:31:16 -05:00
2019-04-02 08:48:31 +01:00
// Info records info log
func Info ( format string , v ... interface { } ) {
Log ( 1 , INFO , format , v ... )
2014-02-18 17:31:16 -05:00
}
2019-04-02 08:48:31 +01:00
// IsInfo returns true if at least one logger is INFO
func IsInfo ( ) bool {
return GetLevel ( ) <= INFO
2014-02-18 17:31:16 -05:00
}
2014-02-18 17:48:02 -05:00
2019-04-02 08:48:31 +01:00
// Warn records warning log
func Warn ( format string , v ... interface { } ) {
Log ( 1 , WARN , format , v ... )
2014-02-18 17:48:02 -05:00
}
2014-05-25 20:11:25 -04:00
2019-04-02 08:48:31 +01:00
// IsWarn returns true if at least one logger is WARN
func IsWarn ( ) bool {
return GetLevel ( ) <= WARN
2014-07-26 00:24:27 -04:00
}
2019-04-02 08:48:31 +01:00
// Error records error log
func Error ( format string , v ... interface { } ) {
Log ( 1 , ERROR , format , v ... )
2014-09-22 17:30:58 -04:00
}
2019-04-02 08:48:31 +01:00
// ErrorWithSkip records error log from "skip" calls back from this function
func ErrorWithSkip ( skip int , format string , v ... interface { } ) {
Log ( skip + 1 , ERROR , format , v ... )
2014-07-26 00:24:27 -04:00
}
2019-04-02 08:48:31 +01:00
// IsError returns true if at least one logger is ERROR
func IsError ( ) bool {
return GetLevel ( ) <= ERROR
2019-02-06 03:06:41 +00:00
}
2019-04-02 08:48:31 +01:00
// Critical records critical log
func Critical ( format string , v ... interface { } ) {
Log ( 1 , CRITICAL , format , v ... )
2019-02-06 03:06:41 +00:00
}
2019-04-02 08:48:31 +01:00
// CriticalWithSkip records critical log from "skip" calls back from this function
func CriticalWithSkip ( skip int , format string , v ... interface { } ) {
Log ( skip + 1 , CRITICAL , format , v ... )
2019-02-06 03:06:41 +00:00
}
2019-04-02 08:48:31 +01:00
// IsCritical returns true if at least one logger is CRITICAL
func IsCritical ( ) bool {
return GetLevel ( ) <= CRITICAL
2019-02-06 03:06:41 +00:00
}
2019-04-02 08:48:31 +01:00
// Fatal records fatal log and exit process
func Fatal ( format string , v ... interface { } ) {
Log ( 1 , FATAL , format , v ... )
Close ( )
os . Exit ( 1 )
2014-07-26 00:24:27 -04:00
}
2019-04-02 08:48:31 +01:00
// FatalWithSkip records fatal log from "skip" calls back from this function
func FatalWithSkip ( skip int , format string , v ... interface { } ) {
Log ( skip + 1 , FATAL , format , v ... )
Close ( )
os . Exit ( 1 )
2014-07-26 00:24:27 -04:00
}
2019-04-02 08:48:31 +01:00
// IsFatal returns true if at least one logger is FATAL
func IsFatal ( ) bool {
return GetLevel ( ) <= FATAL
2014-07-26 00:24:27 -04:00
}
2020-07-06 01:07:07 +01:00
// Pause pauses all the loggers
func Pause ( ) {
NamedLoggers . Range ( func ( key , value interface { } ) bool {
2020-10-31 05:36:46 +00:00
logger := value . ( * MultiChannelledLogger )
2020-07-06 01:07:07 +01:00
logger . Pause ( )
logger . Flush ( )
return true
} )
}
// Resume resumes all the loggers
func Resume ( ) {
NamedLoggers . Range ( func ( key , value interface { } ) bool {
2020-10-31 05:36:46 +00:00
logger := value . ( * MultiChannelledLogger )
2020-07-06 01:07:07 +01:00
logger . Resume ( )
return true
} )
}
// ReleaseReopen releases and reopens logging files
func ReleaseReopen ( ) error {
var accumulatedErr error
NamedLoggers . Range ( func ( key , value interface { } ) bool {
2020-10-31 05:36:46 +00:00
logger := value . ( * MultiChannelledLogger )
2020-07-06 01:07:07 +01:00
if err := logger . ReleaseReopen ( ) ; err != nil {
if accumulatedErr == nil {
accumulatedErr = fmt . Errorf ( "Error reopening %s: %v" , key . ( string ) , err )
} else {
accumulatedErr = fmt . Errorf ( "Error reopening %s: %v & %v" , key . ( string ) , err , accumulatedErr )
}
}
return true
} )
return accumulatedErr
}
2019-04-02 08:48:31 +01:00
// Close closes all the loggers
func Close ( ) {
2019-09-17 17:39:37 +08:00
l , ok := NamedLoggers . Load ( DEFAULT )
2019-04-02 08:48:31 +01:00
if ! ok {
return
2014-07-26 00:24:27 -04:00
}
2019-09-17 17:39:37 +08:00
NamedLoggers . Delete ( DEFAULT )
2019-04-02 08:48:31 +01:00
l . Close ( )
2014-07-26 00:24:27 -04:00
}
2019-04-02 08:48:31 +01:00
// Log a message with defined skip and at logging level
// A skip of 0 refers to the caller of this command
func Log ( skip int , level Level , format string , v ... interface { } ) {
2019-09-17 17:39:37 +08:00
l , ok := NamedLoggers . Load ( DEFAULT )
2019-04-02 08:48:31 +01:00
if ok {
l . Log ( skip + 1 , level , format , v ... )
2014-07-26 00:24:27 -04:00
}
}
2019-04-02 08:48:31 +01:00
// LoggerAsWriter is a io.Writer shim around the gitea log
type LoggerAsWriter struct {
2020-10-31 05:36:46 +00:00
ourLoggers [ ] * MultiChannelledLogger
2019-04-02 08:48:31 +01:00
level Level
2014-07-26 00:24:27 -04:00
}
2019-04-02 08:48:31 +01:00
// NewLoggerAsWriter creates a Writer representation of the logger with setable log level
2020-10-31 05:36:46 +00:00
func NewLoggerAsWriter ( level string , ourLoggers ... * MultiChannelledLogger ) * LoggerAsWriter {
2019-04-02 08:48:31 +01:00
if len ( ourLoggers ) == 0 {
2019-09-17 17:39:37 +08:00
l , _ := NamedLoggers . Load ( DEFAULT )
2020-10-31 05:36:46 +00:00
ourLoggers = [ ] * MultiChannelledLogger { l }
2014-07-26 00:24:27 -04:00
}
2019-04-02 08:48:31 +01:00
l := & LoggerAsWriter {
ourLoggers : ourLoggers ,
level : FromString ( level ) ,
2014-07-26 00:24:27 -04:00
}
2019-04-02 08:48:31 +01:00
return l
2014-07-26 00:24:27 -04:00
}
2021-01-29 23:35:30 +08:00
// Write implements the io.Writer interface to allow spoofing of chi
2019-04-02 08:48:31 +01:00
func ( l * LoggerAsWriter ) Write ( p [ ] byte ) ( int , error ) {
for _ , logger := range l . ourLoggers {
// Skip = 3 because this presumes that we have been called by log.Println()
// If the caller has used log.Output or the like this will be wrong
logger . Log ( 3 , l . level , string ( p ) )
2014-07-26 00:24:27 -04:00
}
2019-04-02 08:48:31 +01:00
return len ( p ) , nil
2014-07-26 00:24:27 -04:00
}
2019-04-02 08:48:31 +01:00
// Log takes a given string and logs it at the set log-level
func ( l * LoggerAsWriter ) Log ( msg string ) {
for _ , logger := range l . ourLoggers {
// Set the skip to reference the call just above this
2019-06-12 21:41:28 +02:00
_ = logger . Log ( 1 , l . level , msg )
2019-04-02 08:48:31 +01:00
}
2014-07-26 00:24:27 -04:00
}
2019-04-02 08:48:31 +01:00
func init ( ) {
_ , filename , _ , _ := runtime . Caller ( 0 )
prefix = strings . TrimSuffix ( filename , "modules/log/log.go" )
2022-01-20 19:41:25 +08:00
if prefix == filename {
// in case the source code file is moved, we can not trim the suffix, the code above should also be updated.
panic ( "unable to detect correct package prefix, please update file: " + filename )
}
2014-05-25 20:11:25 -04:00
}