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"
"sync"
2014-02-12 23:54:09 +04:00
)
2014-03-25 15:47:04 +04:00
var (
2014-07-26 08:24:27 +04:00
loggers [ ] * Logger
GitLogger * Logger
2014-03-25 15:47:04 +04:00
)
2014-02-12 23:54:09 +04:00
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 {
2015-12-07 19:33:04 +03:00
Fatal ( 2 , "Fail to set logger (%s): %v" , mode , err )
2014-06-20 08:25:23 +04:00
}
2014-02-12 23:54:09 +04:00
}
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 ) {
os . MkdirAll ( path . Dir ( logPath ) , os . ModePerm )
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 ) )
}
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
}
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
}
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
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
}
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
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
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 )
}
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
type LogLevel int
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
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
lock sync . Mutex
level int
msg chan * logMsg
outputs map [ string ] LoggerInterface
quit chan bool
}
// newLogger initializes and returns a new logger.
func newLogger ( buffer int64 ) * Logger {
l := & Logger {
msg : make ( chan * logMsg , buffer ) ,
outputs : make ( map [ string ] LoggerInterface ) ,
quit : make ( chan bool ) ,
}
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 {
l . lock . Lock ( )
defer l . lock . Unlock ( )
if log , ok := adapters [ adapter ] ; ok {
lg := log ( )
if err := lg . Init ( config ) ; err != nil {
return err
}
l . outputs [ adapter ] = lg
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 {
l . lock . Lock ( )
defer l . lock . Unlock ( )
if lg , ok := l . outputs [ adapter ] ; ok {
lg . Destroy ( )
delete ( l . outputs , 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
}
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 :
for _ , l := range l . outputs {
2014-08-27 12:39:36 +04:00
if err := l . WriteMsg ( bm . msg , bm . skip , bm . level ) ; err != nil {
fmt . Println ( "ERROR, unable to WriteMsg:" , err )
}
2014-07-26 08:24:27 +04:00
}
case <- l . quit :
return
}
}
}
// Flush flushs all chan data.
func ( l * Logger ) Flush ( ) {
for _ , l := range l . outputs {
l . Flush ( )
}
}
// 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
for _ , l := range l . outputs {
2014-08-27 12:39:36 +04:00
if err := l . WriteMsg ( bm . msg , bm . skip , bm . level ) ; err != nil {
fmt . Println ( "ERROR, unable to WriteMsg:" , err )
}
2014-07-26 08:24:27 +04:00
}
} else {
break
}
}
for _ , l := range l . outputs {
l . Flush ( )
l . Destroy ( )
}
}
func ( l * Logger ) Trace ( format string , v ... interface { } ) {
msg := fmt . Sprintf ( "[T] " + format , v ... )
l . writerMsg ( 0 , TRACE , msg )
}
func ( l * Logger ) Debug ( format string , v ... interface { } ) {
msg := fmt . Sprintf ( "[D] " + format , v ... )
l . writerMsg ( 0 , DEBUG , msg )
}
func ( l * Logger ) Info ( format string , v ... interface { } ) {
msg := fmt . Sprintf ( "[I] " + format , v ... )
l . writerMsg ( 0 , INFO , msg )
}
func ( l * Logger ) Warn ( format string , v ... interface { } ) {
msg := fmt . Sprintf ( "[W] " + format , v ... )
l . writerMsg ( 0 , WARN , msg )
}
func ( l * Logger ) Error ( skip int , format string , v ... interface { } ) {
msg := fmt . Sprintf ( "[E] " + format , v ... )
l . writerMsg ( skip , ERROR , msg )
}
func ( l * Logger ) Critical ( skip int , format string , v ... interface { } ) {
msg := fmt . Sprintf ( "[C] " + format , v ... )
l . writerMsg ( skip , CRITICAL , msg )
}
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
}