2014-02-12 23:54:09 +04: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 (
2014-06-20 09:14:54 +04:00
"fmt"
2014-05-26 04:11:25 +04:00
"os"
2014-06-20 09:14:54 +04:00
"path"
2014-07-26 08:24:27 +04:00
"path/filepath"
"runtime"
"strings"
2017-04-03 05:22:26 +03:00
"golang.org/x/sync/syncmap"
2014-02-12 23:54:09 +04:00
)
2014-03-25 15:47:04 +04:00
var (
2016-11-26 14:53:29 +03:00
loggers [ ] * Logger
// GitLogger logger for git
2014-07-26 08:24:27 +04:00
GitLogger * Logger
2014-03-25 15:47:04 +04:00
)
2014-02-12 23:54:09 +04:00
2016-11-26 14:53:29 +03:00
// NewLogger create a logger
2014-03-19 12:08:25 +04:00
func NewLogger ( bufLen int64 , mode , config string ) {
2014-07-26 08:24:27 +04:00
logger := newLogger ( bufLen )
2014-05-11 22:37:12 +04:00
isExist := false
2016-07-15 12:06:17 +03:00
for i , l := range loggers {
2014-07-26 08:24:27 +04:00
if l . adapter == mode {
2014-05-11 22:37:12 +04:00
isExist = true
2016-07-15 12:06:17 +03:00
loggers [ i ] = logger
2014-05-11 22:37:12 +04:00
}
}
if ! isExist {
loggers = append ( loggers , logger )
}
2014-06-20 08:25:23 +04:00
if err := logger . SetLogger ( mode , config ) ; err != nil {
2017-01-29 23:13:57 +03:00
Fatal ( 2 , "Failed to set logger (%s): %v" , mode , err )
2014-06-20 08:25:23 +04:00
}
2014-02-12 23:54:09 +04:00
}
2017-01-17 09:02:35 +03:00
// DelLogger removes loggers that are for the given mode
func DelLogger ( mode string ) error {
for _ , l := range loggers {
2017-04-03 05:22:26 +03:00
if _ , ok := l . outputs . Load ( mode ) ; ok {
2017-01-17 09:02:35 +03:00
return l . DelLogger ( mode )
}
}
2017-04-03 05:22:26 +03:00
2017-01-17 09:02:35 +03:00
Trace ( "Log adapter %s not found, no need to delete" , mode )
return nil
}
2016-11-26 14:53:29 +03:00
// NewGitLogger create a logger for git
2016-02-16 07:11:22 +03:00
// FIXME: use same log level as other loggers.
2014-06-20 09:14:54 +04:00
func NewGitLogger ( logPath string ) {
2016-12-01 02:56:15 +03:00
path := path . Dir ( logPath )
if err := os . MkdirAll ( path , os . ModePerm ) ; err != nil {
2017-01-29 23:13:57 +03:00
Fatal ( 4 , "Failed to create dir %s: %v" , path , err )
2016-12-01 02:56:15 +03:00
}
2014-07-26 08:24:27 +04:00
GitLogger = newLogger ( 0 )
2014-06-20 09:14:54 +04:00
GitLogger . SetLogger ( "file" , fmt . Sprintf ( ` { "level":0,"filename":"%s","rotate":false} ` , logPath ) )
}
2016-11-26 14:53:29 +03:00
// Trace records trace log
2014-02-19 02:48:02 +04:00
func Trace ( format string , v ... interface { } ) {
2014-05-11 22:37:12 +04:00
for _ , logger := range loggers {
logger . Trace ( format , v ... )
}
2014-02-19 02:48:02 +04:00
}
2016-11-26 14:53:29 +03:00
// Debug records debug log
2014-03-23 20:16:17 +04:00
func Debug ( format string , v ... interface { } ) {
2014-05-11 22:37:12 +04:00
for _ , logger := range loggers {
logger . Debug ( format , v ... )
}
2014-03-23 20:16:17 +04:00
}
2016-11-26 14:53:29 +03:00
// Info records info log
2014-02-12 23:54:09 +04:00
func Info ( format string , v ... interface { } ) {
2014-05-11 22:37:12 +04:00
for _ , logger := range loggers {
logger . Info ( format , v ... )
}
2014-02-12 23:54:09 +04:00
}
2014-02-19 02:31:16 +04:00
2017-03-15 03:52:01 +03:00
// Warn records warning log
2014-07-26 08:24:27 +04:00
func Warn ( format string , v ... interface { } ) {
2014-05-11 22:37:12 +04:00
for _ , logger := range loggers {
2014-07-26 08:24:27 +04:00
logger . Warn ( format , v ... )
2014-05-11 22:37:12 +04:00
}
2014-02-19 02:31:16 +04:00
}
2016-11-26 14:53:29 +03:00
// Error records error log
2014-07-26 08:24:27 +04:00
func Error ( skip int , format string , v ... interface { } ) {
2014-05-11 22:37:12 +04:00
for _ , logger := range loggers {
2014-07-26 08:24:27 +04:00
logger . Error ( skip , format , v ... )
2014-05-11 22:37:12 +04:00
}
2014-02-19 02:31:16 +04:00
}
2014-02-19 02:48:02 +04:00
2016-11-26 14:53:29 +03:00
// Critical records critical log
2014-07-26 08:24:27 +04:00
func Critical ( skip int , format string , v ... interface { } ) {
2014-05-11 22:37:12 +04:00
for _ , logger := range loggers {
2014-07-26 08:24:27 +04:00
logger . Critical ( skip , format , v ... )
2014-05-11 22:37:12 +04:00
}
2014-02-19 02:48:02 +04:00
}
2014-05-26 04:11:25 +04:00
2016-11-26 14:53:29 +03:00
// Fatal records error log and exit process
2014-07-26 08:24:27 +04:00
func Fatal ( skip int , format string , v ... interface { } ) {
Error ( skip , format , v ... )
2014-05-26 04:11:25 +04:00
for _ , l := range loggers {
l . Close ( )
}
2014-07-26 08:24:27 +04:00
os . Exit ( 1 )
}
2016-11-26 14:53:29 +03:00
// Close closes all the loggers
2014-09-23 01:30:58 +04:00
func Close ( ) {
for _ , l := range loggers {
l . Close ( )
}
}
2014-07-27 02:37:18 +04:00
// .___ __ _____
// | | _____/ |_ ____________/ ____\____ ____ ____
// | |/ \ __\/ __ \_ __ \ __\\__ \ _/ ___\/ __ \
// | | | \ | \ ___/| | \/| | / __ \\ \__\ ___/
// |___|___| /__| \___ >__| |__| (____ /\___ >___ >
// \/ \/ \/ \/ \/
2014-07-26 08:24:27 +04:00
2016-11-26 14:53:29 +03:00
// LogLevel level type for log
//type LogLevel int
2014-07-26 08:24:27 +04:00
2016-11-26 14:53:29 +03:00
// log levels
2014-07-26 08:24:27 +04:00
const (
TRACE = iota
DEBUG
INFO
WARN
ERROR
CRITICAL
FATAL
)
// LoggerInterface represents behaviors of a logger provider.
type LoggerInterface interface {
Init ( config string ) error
WriteMsg ( msg string , skip , level int ) error
Destroy ( )
Flush ( )
}
type loggerType func ( ) LoggerInterface
2019-02-06 06:06:41 +03:00
// LoggerAsWriter is a io.Writer shim around the gitea log
type LoggerAsWriter struct {
level int
}
// NewLoggerAsWriter creates a Writer representation of the logger with setable log level
func NewLoggerAsWriter ( level string ) * LoggerAsWriter {
l := & LoggerAsWriter { }
switch strings . ToUpper ( level ) {
case "TRACE" :
l . level = TRACE
case "DEBUG" :
l . level = DEBUG
case "INFO" :
l . level = INFO
case "WARN" :
l . level = WARN
case "ERROR" :
l . level = ERROR
case "CRITICAL" :
l . level = CRITICAL
case "FATAL" :
l . level = FATAL
default :
l . level = INFO
}
return l
}
// Write implements the io.Writer interface to allow spoofing of macaron
func ( l * LoggerAsWriter ) Write ( p [ ] byte ) ( int , error ) {
l . Log ( string ( p ) )
return len ( p ) , nil
}
// Log takes a given string and logs it at the set log-level
func ( l * LoggerAsWriter ) Log ( msg string ) {
for _ , logger := range loggers {
logger . writerMsg ( 0 , l . level , msg )
}
}
2014-07-26 08:24:27 +04:00
var adapters = make ( map [ string ] loggerType )
// Register registers given logger provider to adapters.
func Register ( name string , log loggerType ) {
if log == nil {
panic ( "log: register provider is nil" )
}
if _ , dup := adapters [ name ] ; dup {
panic ( "log: register called twice for provider \"" + name + "\"" )
}
adapters [ name ] = log
}
type logMsg struct {
skip , level int
msg string
}
// Logger is default logger in beego application.
// it can contain several providers and log message into all providers.
type Logger struct {
adapter string
level int
msg chan * logMsg
2017-04-03 05:22:26 +03:00
outputs syncmap . Map
2014-07-26 08:24:27 +04:00
quit chan bool
}
// newLogger initializes and returns a new logger.
func newLogger ( buffer int64 ) * Logger {
l := & Logger {
2017-04-03 05:22:26 +03:00
msg : make ( chan * logMsg , buffer ) ,
quit : make ( chan bool ) ,
2014-07-26 08:24:27 +04:00
}
go l . StartLogger ( )
return l
}
2014-12-07 04:22:48 +03:00
// SetLogger sets new logger instance with given logger adapter and config.
2014-07-26 08:24:27 +04:00
func ( l * Logger ) SetLogger ( adapter string , config string ) error {
if log , ok := adapters [ adapter ] ; ok {
lg := log ( )
if err := lg . Init ( config ) ; err != nil {
return err
}
2017-04-03 05:22:26 +03:00
l . outputs . Store ( adapter , lg )
2014-07-26 08:24:27 +04:00
l . adapter = adapter
} else {
2014-07-27 02:37:18 +04:00
panic ( "log: unknown adapter \"" + adapter + "\" (forgotten register?)" )
2014-07-26 08:24:27 +04:00
}
return nil
}
// DelLogger removes a logger adapter instance.
func ( l * Logger ) DelLogger ( adapter string ) error {
2017-04-03 05:22:26 +03:00
if lg , ok := l . outputs . Load ( adapter ) ; ok {
lg . ( LoggerInterface ) . Destroy ( )
l . outputs . Delete ( adapter )
2014-07-26 08:24:27 +04:00
} else {
2014-07-27 02:37:18 +04:00
panic ( "log: unknown adapter \"" + adapter + "\" (forgotten register?)" )
2014-07-26 08:24:27 +04:00
}
return nil
}
func ( l * Logger ) writerMsg ( skip , level int , msg string ) error {
if l . level > level {
return nil
}
lm := & logMsg {
skip : skip ,
level : level ,
}
// Only error information needs locate position for debugging.
if lm . level >= ERROR {
pc , file , line , ok := runtime . Caller ( skip )
if ok {
// Get caller function name.
fn := runtime . FuncForPC ( pc )
var fnName string
if fn == nil {
fnName = "?()"
} else {
fnName = strings . TrimLeft ( filepath . Ext ( fn . Name ( ) ) , "." ) + "()"
}
2015-07-26 17:06:28 +03:00
fileName := file
if len ( fileName ) > 20 {
fileName = "..." + fileName [ len ( fileName ) - 20 : ]
}
lm . msg = fmt . Sprintf ( "[%s:%d %s] %s" , fileName , line , fnName , msg )
2014-07-26 08:24:27 +04:00
} else {
lm . msg = msg
}
} else {
lm . msg = msg
}
l . msg <- lm
return nil
}
// StartLogger starts logger chan reading.
func ( l * Logger ) StartLogger ( ) {
for {
select {
case bm := <- l . msg :
2017-04-03 05:22:26 +03:00
l . outputs . Range ( func ( k , v interface { } ) bool {
if err := v . ( LoggerInterface ) . WriteMsg ( bm . msg , bm . skip , bm . level ) ; err != nil {
2014-08-27 12:39:36 +04:00
fmt . Println ( "ERROR, unable to WriteMsg:" , err )
}
2017-04-03 05:22:26 +03:00
return true
} )
2014-07-26 08:24:27 +04:00
case <- l . quit :
return
}
}
}
2017-03-15 03:52:01 +03:00
// Flush flushes all chan data.
2014-07-26 08:24:27 +04:00
func ( l * Logger ) Flush ( ) {
2017-04-03 05:22:26 +03:00
l . outputs . Range ( func ( k , v interface { } ) bool {
v . ( LoggerInterface ) . Flush ( )
return true
} )
2014-07-26 08:24:27 +04:00
}
// Close closes logger, flush all chan data and destroy all adapter instances.
func ( l * Logger ) Close ( ) {
l . quit <- true
for {
if len ( l . msg ) > 0 {
bm := <- l . msg
2017-04-03 05:22:26 +03:00
l . outputs . Range ( func ( k , v interface { } ) bool {
if err := v . ( LoggerInterface ) . WriteMsg ( bm . msg , bm . skip , bm . level ) ; err != nil {
2014-08-27 12:39:36 +04:00
fmt . Println ( "ERROR, unable to WriteMsg:" , err )
}
2017-04-03 05:22:26 +03:00
return true
} )
2014-07-26 08:24:27 +04:00
} else {
break
}
}
2017-04-03 05:22:26 +03:00
l . outputs . Range ( func ( k , v interface { } ) bool {
v . ( LoggerInterface ) . Flush ( )
v . ( LoggerInterface ) . Destroy ( )
return true
} )
2014-07-26 08:24:27 +04:00
}
2016-11-26 14:53:29 +03:00
// Trace records trace log
2014-07-26 08:24:27 +04:00
func ( l * Logger ) Trace ( format string , v ... interface { } ) {
msg := fmt . Sprintf ( "[T] " + format , v ... )
l . writerMsg ( 0 , TRACE , msg )
}
2016-11-26 14:53:29 +03:00
// Debug records debug log
2014-07-26 08:24:27 +04:00
func ( l * Logger ) Debug ( format string , v ... interface { } ) {
msg := fmt . Sprintf ( "[D] " + format , v ... )
l . writerMsg ( 0 , DEBUG , msg )
}
2016-11-26 14:53:29 +03:00
// Info records information log
2014-07-26 08:24:27 +04:00
func ( l * Logger ) Info ( format string , v ... interface { } ) {
msg := fmt . Sprintf ( "[I] " + format , v ... )
l . writerMsg ( 0 , INFO , msg )
}
2017-03-15 03:52:01 +03:00
// Warn records warning log
2014-07-26 08:24:27 +04:00
func ( l * Logger ) Warn ( format string , v ... interface { } ) {
msg := fmt . Sprintf ( "[W] " + format , v ... )
l . writerMsg ( 0 , WARN , msg )
}
2016-11-26 14:53:29 +03:00
// Error records error log
2014-07-26 08:24:27 +04:00
func ( l * Logger ) Error ( skip int , format string , v ... interface { } ) {
msg := fmt . Sprintf ( "[E] " + format , v ... )
l . writerMsg ( skip , ERROR , msg )
}
2016-11-26 14:53:29 +03:00
// Critical records critical log
2014-07-26 08:24:27 +04:00
func ( l * Logger ) Critical ( skip int , format string , v ... interface { } ) {
msg := fmt . Sprintf ( "[C] " + format , v ... )
l . writerMsg ( skip , CRITICAL , msg )
}
2016-11-26 14:53:29 +03:00
// Fatal records error log and exit the process
2014-07-26 08:24:27 +04:00
func ( l * Logger ) Fatal ( skip int , format string , v ... interface { } ) {
msg := fmt . Sprintf ( "[F] " + format , v ... )
l . writerMsg ( skip , FATAL , msg )
l . Close ( )
os . Exit ( 1 )
2014-05-26 04:11:25 +04:00
}