mirror of https://github.com/gogits/gogs.git
Unknwon
8 years ago
66 changed files with 198 additions and 1033 deletions
File diff suppressed because one or more lines are too long
@ -1,104 +0,0 @@
|
||||
// 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 ( |
||||
"encoding/json" |
||||
"io" |
||||
"log" |
||||
"net" |
||||
) |
||||
|
||||
// ConnWriter implements LoggerInterface.
|
||||
// it writes messages in keep-live tcp connection.
|
||||
type ConnWriter struct { |
||||
lg *log.Logger |
||||
innerWriter io.WriteCloser |
||||
ReconnectOnMsg bool `json:"reconnectOnMsg"` |
||||
Reconnect bool `json:"reconnect"` |
||||
Net string `json:"net"` |
||||
Addr string `json:"addr"` |
||||
Level int `json:"level"` |
||||
} |
||||
|
||||
// create new ConnWrite returning as LoggerInterface.
|
||||
func NewConn() LoggerInterface { |
||||
conn := new(ConnWriter) |
||||
conn.Level = TRACE |
||||
return conn |
||||
} |
||||
|
||||
// init connection writer with json config.
|
||||
// json config only need key "level".
|
||||
func (cw *ConnWriter) Init(jsonconfig string) error { |
||||
return json.Unmarshal([]byte(jsonconfig), cw) |
||||
} |
||||
|
||||
// write message in connection.
|
||||
// if connection is down, try to re-connect.
|
||||
func (cw *ConnWriter) WriteMsg(msg string, skip, level int) error { |
||||
if cw.Level > level { |
||||
return nil |
||||
} |
||||
if cw.neddedConnectOnMsg() { |
||||
if err := cw.connect(); err != nil { |
||||
return err |
||||
} |
||||
} |
||||
|
||||
if cw.ReconnectOnMsg { |
||||
defer cw.innerWriter.Close() |
||||
} |
||||
cw.lg.Println(msg) |
||||
return nil |
||||
} |
||||
|
||||
func (_ *ConnWriter) Flush() { |
||||
} |
||||
|
||||
// destroy connection writer and close tcp listener.
|
||||
func (cw *ConnWriter) Destroy() { |
||||
if cw.innerWriter == nil { |
||||
return |
||||
} |
||||
cw.innerWriter.Close() |
||||
} |
||||
|
||||
func (cw *ConnWriter) connect() error { |
||||
if cw.innerWriter != nil { |
||||
cw.innerWriter.Close() |
||||
cw.innerWriter = nil |
||||
} |
||||
|
||||
conn, err := net.Dial(cw.Net, cw.Addr) |
||||
if err != nil { |
||||
return err |
||||
} |
||||
|
||||
if tcpConn, ok := conn.(*net.TCPConn); ok { |
||||
tcpConn.SetKeepAlive(true) |
||||
} |
||||
|
||||
cw.innerWriter = conn |
||||
cw.lg = log.New(conn, "", log.Ldate|log.Ltime) |
||||
return nil |
||||
} |
||||
|
||||
func (cw *ConnWriter) neddedConnectOnMsg() bool { |
||||
if cw.Reconnect { |
||||
cw.Reconnect = false |
||||
return true |
||||
} |
||||
|
||||
if cw.innerWriter == nil { |
||||
return true |
||||
} |
||||
|
||||
return cw.ReconnectOnMsg |
||||
} |
||||
|
||||
func init() { |
||||
Register("conn", NewConn) |
||||
} |
@ -1,73 +0,0 @@
|
||||
// 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 ( |
||||
"encoding/json" |
||||
"log" |
||||
"os" |
||||
"runtime" |
||||
) |
||||
|
||||
type Brush func(string) string |
||||
|
||||
func NewBrush(color string) Brush { |
||||
pre := "\033[" |
||||
reset := "\033[0m" |
||||
return func(text string) string { |
||||
return pre + color + "m" + text + reset |
||||
} |
||||
} |
||||
|
||||
var colors = []Brush{ |
||||
NewBrush("1;36"), // Trace cyan
|
||||
NewBrush("1;34"), // Debug blue
|
||||
NewBrush("1;32"), // Info green
|
||||
NewBrush("1;33"), // Warn yellow
|
||||
NewBrush("1;31"), // Error red
|
||||
NewBrush("1;35"), // Critical purple
|
||||
NewBrush("1;31"), // Fatal red
|
||||
} |
||||
|
||||
// ConsoleWriter implements LoggerInterface and writes messages to terminal.
|
||||
type ConsoleWriter struct { |
||||
lg *log.Logger |
||||
Level int `json:"level"` |
||||
} |
||||
|
||||
// create ConsoleWriter returning as LoggerInterface.
|
||||
func NewConsole() LoggerInterface { |
||||
return &ConsoleWriter{ |
||||
lg: log.New(os.Stdout, "", log.Ldate|log.Ltime), |
||||
Level: TRACE, |
||||
} |
||||
} |
||||
|
||||
func (cw *ConsoleWriter) Init(config string) error { |
||||
return json.Unmarshal([]byte(config), cw) |
||||
} |
||||
|
||||
func (cw *ConsoleWriter) WriteMsg(msg string, skip, level int) error { |
||||
if cw.Level > level { |
||||
return nil |
||||
} |
||||
if runtime.GOOS == "windows" { |
||||
cw.lg.Println(msg) |
||||
} else { |
||||
cw.lg.Println(colors[level](msg)) |
||||
} |
||||
return nil |
||||
} |
||||
|
||||
func (_ *ConsoleWriter) Flush() { |
||||
|
||||
} |
||||
|
||||
func (_ *ConsoleWriter) Destroy() { |
||||
} |
||||
|
||||
func init() { |
||||
Register("console", NewConsole) |
||||
} |
@ -1,243 +0,0 @@
|
||||
// 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 ( |
||||
"encoding/json" |
||||
"errors" |
||||
"fmt" |
||||
"io/ioutil" |
||||
"log" |
||||
"os" |
||||
"path/filepath" |
||||
"strings" |
||||
"sync" |
||||
"time" |
||||
) |
||||
|
||||
// FileLogWriter implements LoggerInterface.
|
||||
// It writes messages by lines limit, file size limit, or time frequency.
|
||||
type FileLogWriter struct { |
||||
*log.Logger |
||||
mw *MuxWriter |
||||
// The opened file
|
||||
Filename string `json:"filename"` |
||||
|
||||
Maxlines int `json:"maxlines"` |
||||
maxlines_curlines int |
||||
|
||||
// Rotate at size
|
||||
Maxsize int `json:"maxsize"` |
||||
maxsize_cursize int |
||||
|
||||
// Rotate daily
|
||||
Daily bool `json:"daily"` |
||||
Maxdays int64 `json:"maxdays"` |
||||
daily_opendate int |
||||
|
||||
Rotate bool `json:"rotate"` |
||||
|
||||
startLock sync.Mutex // Only one log can write to the file
|
||||
|
||||
Level int `json:"level"` |
||||
} |
||||
|
||||
// an *os.File writer with locker.
|
||||
type MuxWriter struct { |
||||
sync.Mutex |
||||
fd *os.File |
||||
} |
||||
|
||||
// write to os.File.
|
||||
func (l *MuxWriter) Write(b []byte) (int, error) { |
||||
l.Lock() |
||||
defer l.Unlock() |
||||
return l.fd.Write(b) |
||||
} |
||||
|
||||
// set os.File in writer.
|
||||
func (l *MuxWriter) SetFd(fd *os.File) { |
||||
if l.fd != nil { |
||||
l.fd.Close() |
||||
} |
||||
l.fd = fd |
||||
} |
||||
|
||||
// create a FileLogWriter returning as LoggerInterface.
|
||||
func NewFileWriter() LoggerInterface { |
||||
w := &FileLogWriter{ |
||||
Filename: "", |
||||
Maxlines: 1000000, |
||||
Maxsize: 1 << 28, //256 MB
|
||||
Daily: true, |
||||
Maxdays: 7, |
||||
Rotate: true, |
||||
Level: TRACE, |
||||
} |
||||
// use MuxWriter instead direct use os.File for lock write when rotate
|
||||
w.mw = new(MuxWriter) |
||||
// set MuxWriter as Logger's io.Writer
|
||||
w.Logger = log.New(w.mw, "", log.Ldate|log.Ltime) |
||||
return w |
||||
} |
||||
|
||||
// Init file logger with json config.
|
||||
// config like:
|
||||
// {
|
||||
// "filename":"log/gogs.log",
|
||||
// "maxlines":10000,
|
||||
// "maxsize":1<<30,
|
||||
// "daily":true,
|
||||
// "maxdays":15,
|
||||
// "rotate":true
|
||||
// }
|
||||
func (w *FileLogWriter) Init(config string) error { |
||||
if err := json.Unmarshal([]byte(config), w); err != nil { |
||||
return err |
||||
} |
||||
if len(w.Filename) == 0 { |
||||
return errors.New("config must have filename") |
||||
} |
||||
return w.StartLogger() |
||||
} |
||||
|
||||
// start file logger. create log file and set to locker-inside file writer.
|
||||
func (w *FileLogWriter) StartLogger() error { |
||||
fd, err := w.createLogFile() |
||||
if err != nil { |
||||
return err |
||||
} |
||||
w.mw.SetFd(fd) |
||||
if err = w.initFd(); err != nil { |
||||
return err |
||||
} |
||||
return nil |
||||
} |
||||
|
||||
func (w *FileLogWriter) docheck(size int) { |
||||
w.startLock.Lock() |
||||
defer w.startLock.Unlock() |
||||
if w.Rotate && ((w.Maxlines > 0 && w.maxlines_curlines >= w.Maxlines) || |
||||
(w.Maxsize > 0 && w.maxsize_cursize >= w.Maxsize) || |
||||
(w.Daily && time.Now().Day() != w.daily_opendate)) { |
||||
if err := w.DoRotate(); err != nil { |
||||
fmt.Fprintf(os.Stderr, "FileLogWriter(%q): %s\n", w.Filename, err) |
||||
return |
||||
} |
||||
} |
||||
w.maxlines_curlines++ |
||||
w.maxsize_cursize += size |
||||
} |
||||
|
||||
// write logger message into file.
|
||||
func (w *FileLogWriter) WriteMsg(msg string, skip, level int) error { |
||||
if level < w.Level { |
||||
return nil |
||||
} |
||||
n := 24 + len(msg) // 24 stand for the length "2013/06/23 21:00:22 [T] "
|
||||
w.docheck(n) |
||||
w.Logger.Println(msg) |
||||
return nil |
||||
} |
||||
|
||||
func (w *FileLogWriter) createLogFile() (*os.File, error) { |
||||
// Open the log file
|
||||
return os.OpenFile(w.Filename, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0660) |
||||
} |
||||
|
||||
func (w *FileLogWriter) initFd() error { |
||||
fd := w.mw.fd |
||||
finfo, err := fd.Stat() |
||||
if err != nil { |
||||
return fmt.Errorf("get stat: %s\n", err) |
||||
} |
||||
w.maxsize_cursize = int(finfo.Size()) |
||||
w.daily_opendate = time.Now().Day() |
||||
if finfo.Size() > 0 { |
||||
content, err := ioutil.ReadFile(w.Filename) |
||||
if err != nil { |
||||
return err |
||||
} |
||||
w.maxlines_curlines = len(strings.Split(string(content), "\n")) |
||||
} else { |
||||
w.maxlines_curlines = 0 |
||||
} |
||||
return nil |
||||
} |
||||
|
||||
// DoRotate means it need to write file in new file.
|
||||
// new file name like xx.log.2013-01-01.2
|
||||
func (w *FileLogWriter) DoRotate() error { |
||||
_, err := os.Lstat(w.Filename) |
||||
if err == nil { // file exists
|
||||
// Find the next available number
|
||||
num := 1 |
||||
fname := "" |
||||
for ; err == nil && num <= 999; num++ { |
||||
fname = w.Filename + fmt.Sprintf(".%s.%03d", time.Now().Format("2006-01-02"), num) |
||||
_, err = os.Lstat(fname) |
||||
} |
||||
// return error if the last file checked still existed
|
||||
if err == nil { |
||||
return fmt.Errorf("rotate: cannot find free log number to rename %s\n", w.Filename) |
||||
} |
||||
|
||||
// block Logger's io.Writer
|
||||
w.mw.Lock() |
||||
defer w.mw.Unlock() |
||||
|
||||
fd := w.mw.fd |
||||
fd.Close() |
||||
|
||||
// close fd before rename
|
||||
// Rename the file to its newfound home
|
||||
if err = os.Rename(w.Filename, fname); err != nil { |
||||
return fmt.Errorf("Rotate: %s\n", err) |
||||
} |
||||
|
||||
// re-start logger
|
||||
if err = w.StartLogger(); err != nil { |
||||
return fmt.Errorf("Rotate StartLogger: %s\n", err) |
||||
} |
||||
|
||||
go w.deleteOldLog() |
||||
} |
||||
|
||||
return nil |
||||
} |
||||
|
||||
func (w *FileLogWriter) deleteOldLog() { |
||||
dir := filepath.Dir(w.Filename) |
||||
filepath.Walk(dir, func(path string, info os.FileInfo, err error) (returnErr error) { |
||||
defer func() { |
||||
if r := recover(); r != nil { |
||||
returnErr = fmt.Errorf("Unable to delete old log '%s', error: %+v", path, r) |
||||
} |
||||
}() |
||||
|
||||
if !info.IsDir() && info.ModTime().Unix() < (time.Now().Unix()-60*60*24*w.Maxdays) { |
||||
if strings.HasPrefix(filepath.Base(path), filepath.Base(w.Filename)) { |
||||
os.Remove(path) |
||||
} |
||||
} |
||||
return returnErr |
||||
}) |
||||
} |
||||
|
||||
// destroy file logger, close file writer.
|
||||
func (w *FileLogWriter) Destroy() { |
||||
w.mw.fd.Close() |
||||
} |
||||
|
||||
// flush file logger.
|
||||
// there are no buffering messages in file logger in memory.
|
||||
// flush file means sync file from disk.
|
||||
func (w *FileLogWriter) Flush() { |
||||
w.mw.fd.Sync() |
||||
} |
||||
|
||||
func init() { |
||||
Register("file", NewFileWriter) |
||||
} |
@ -1,312 +0,0 @@
|
||||
// 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 ( |
||||
"fmt" |
||||
"os" |
||||
"path" |
||||
"path/filepath" |
||||
"runtime" |
||||
"strings" |
||||
"sync" |
||||
) |
||||
|
||||
var ( |
||||
loggers []*Logger |
||||
GitLogger *Logger |
||||
) |
||||
|
||||
func NewLogger(bufLen int64, mode, config string) { |
||||
logger := newLogger(bufLen) |
||||
|
||||
isExist := false |
||||
for i, l := range loggers { |
||||
if l.adapter == mode { |
||||
isExist = true |
||||
loggers[i] = logger |
||||
} |
||||
} |
||||
if !isExist { |
||||
loggers = append(loggers, logger) |
||||
} |
||||
if err := logger.SetLogger(mode, config); err != nil { |
||||
Fatal(2, "Fail to set logger (%s): %v", mode, err) |
||||
} |
||||
} |
||||
|
||||
// FIXME: use same log level as other loggers.
|
||||
func NewGitLogger(logPath string) { |
||||
os.MkdirAll(path.Dir(logPath), os.ModePerm) |
||||
GitLogger = newLogger(0) |
||||
GitLogger.SetLogger("file", fmt.Sprintf(`{"level":0,"filename":"%s","rotate":false}`, logPath)) |
||||
} |
||||
|
||||
func Trace(format string, v ...interface{}) { |
||||
for _, logger := range loggers { |
||||
logger.Trace(format, v...) |
||||
} |
||||
} |
||||
|
||||
func Debug(format string, v ...interface{}) { |
||||
for _, logger := range loggers { |
||||
logger.Debug(format, v...) |
||||
} |
||||
} |
||||
|
||||
func Info(format string, v ...interface{}) { |
||||
for _, logger := range loggers { |
||||
logger.Info(format, v...) |
||||
} |
||||
} |
||||
|
||||
func Warn(format string, v ...interface{}) { |
||||
for _, logger := range loggers { |
||||
logger.Warn(format, v...) |
||||
} |
||||
} |
||||
|
||||
func Error(skip int, format string, v ...interface{}) { |
||||
for _, logger := range loggers { |
||||
logger.Error(skip, format, v...) |
||||
} |
||||
} |
||||
|
||||
func Critical(skip int, format string, v ...interface{}) { |
||||
for _, logger := range loggers { |
||||
logger.Critical(skip, format, v...) |
||||
} |
||||
} |
||||
|
||||
func Fatal(skip int, format string, v ...interface{}) { |
||||
Error(skip, format, v...) |
||||
for _, l := range loggers { |
||||
l.Close() |
||||
} |
||||
os.Exit(1) |
||||
} |
||||
|
||||
func Close() { |
||||
for _, l := range loggers { |
||||
l.Close() |
||||
} |
||||
} |
||||
|
||||
// .___ __ _____
|
||||
// | | _____/ |_ ____________/ ____\____ ____ ____
|
||||
// | |/ \ __\/ __ \_ __ \ __\\__ \ _/ ___\/ __ \
|
||||
// | | | \ | \ ___/| | \/| | / __ \\ \__\ ___/
|
||||
// |___|___| /__| \___ >__| |__| (____ /\___ >___ >
|
||||
// \/ \/ \/ \/ \/
|
||||
|
||||
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 |
||||
} |
||||
|
||||
// SetLogger sets new logger instance with given logger adapter and config.
|
||||
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 { |
||||
panic("log: unknown adapter \"" + adapter + "\" (forgotten register?)") |
||||
} |
||||
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 { |
||||
panic("log: unknown adapter \"" + adapter + "\" (forgotten register?)") |
||||
} |
||||
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()), ".") + "()" |
||||
} |
||||
|
||||
fileName := file |
||||
if len(fileName) > 20 { |
||||
fileName = "..." + fileName[len(fileName)-20:] |
||||
} |
||||
lm.msg = fmt.Sprintf("[%s:%d %s] %s", fileName, line, fnName, msg) |
||||
} 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 { |
||||
if err := l.WriteMsg(bm.msg, bm.skip, bm.level); err != nil { |
||||
fmt.Println("ERROR, unable to WriteMsg:", err) |
||||
} |
||||
} |
||||
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 { |
||||
if err := l.WriteMsg(bm.msg, bm.skip, bm.level); err != nil { |
||||
fmt.Println("ERROR, unable to WriteMsg:", err) |
||||
} |
||||
} |
||||
} 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) |
||||
} |
@ -1,87 +0,0 @@
|
||||
// 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 ( |
||||
"encoding/json" |
||||
"fmt" |
||||
"net/smtp" |
||||
"strings" |
||||
"time" |
||||
) |
||||
|
||||
const ( |
||||
subjectPhrase = "Diagnostic message from server" |
||||
) |
||||
|
||||
// smtpWriter implements LoggerInterface and is used to send emails via given SMTP-server.
|
||||
type SmtpWriter struct { |
||||
Username string `json:"Username"` |
||||
Password string `json:"password"` |
||||
Host string `json:"Host"` |
||||
Subject string `json:"subject"` |
||||
RecipientAddresses []string `json:"sendTos"` |
||||
Level int `json:"level"` |
||||
} |
||||
|
||||
// create smtp writer.
|
||||
func NewSmtpWriter() LoggerInterface { |
||||
return &SmtpWriter{Level: TRACE} |
||||
} |
||||
|
||||
// init smtp writer with json config.
|
||||
// config like:
|
||||
// {
|
||||
// "Username":"example@gmail.com",
|
||||
// "password:"password",
|
||||
// "host":"smtp.gmail.com:465",
|
||||
// "subject":"email title",
|
||||
// "sendTos":["email1","email2"],
|
||||
// "level":LevelError
|
||||
// }
|
||||
func (sw *SmtpWriter) Init(jsonconfig string) error { |
||||
return json.Unmarshal([]byte(jsonconfig), sw) |
||||
} |
||||
|
||||
// write message in smtp writer.
|
||||
// it will send an email with subject and only this message.
|
||||
func (s *SmtpWriter) WriteMsg(msg string, skip, level int) error { |
||||
if level < s.Level { |
||||
return nil |
||||
} |
||||
|
||||
hp := strings.Split(s.Host, ":") |
||||
|
||||
// Set up authentication information.
|
||||
auth := smtp.PlainAuth( |
||||
"", |
||||
s.Username, |
||||
s.Password, |
||||
hp[0], |
||||
) |
||||
// Connect to the server, authenticate, set the sender and recipient,
|
||||
// and send the email all in one step.
|
||||
content_type := "Content-Type: text/plain" + "; charset=UTF-8" |
||||
mailmsg := []byte("To: " + strings.Join(s.RecipientAddresses, ";") + "\r\nFrom: " + s.Username + "<" + s.Username + |
||||
">\r\nSubject: " + s.Subject + "\r\n" + content_type + "\r\n\r\n" + fmt.Sprintf(".%s", time.Now().Format("2006-01-02 15:04:05")) + msg) |
||||
|
||||
return smtp.SendMail( |
||||
s.Host, |
||||
auth, |
||||
s.Username, |
||||
s.RecipientAddresses, |
||||
mailmsg, |
||||
) |
||||
} |
||||
|
||||
func (_ *SmtpWriter) Flush() { |
||||
} |
||||
|
||||
func (_ *SmtpWriter) Destroy() { |
||||
} |
||||
|
||||
func init() { |
||||
Register("smtp", NewSmtpWriter) |
||||
} |
Loading…
Reference in new issue