add default writer for glog to be integrated with other package; comments update for glog

This commit is contained in:
John
2019-04-17 23:50:37 +08:00
parent d55e77fb90
commit 2d3d2e783e
9 changed files with 145 additions and 196 deletions

View File

@ -15,60 +15,60 @@ import (
) )
// Console values. // Console values.
type gCmdValue struct { type gCmdValue struct {
values []string values []string
} }
// Console options. // Console options.
type gCmdOption struct { type gCmdOption struct {
options map[string]string options map[string]string
} }
var Value = &gCmdValue{} // Console values. var Value = &gCmdValue{} // Console values.
var Option = &gCmdOption{} // Console options. var Option = &gCmdOption{} // Console options.
var cmdFuncMap = make(map[string]func()) // Registered callback functions. var cmdFuncMap = make(map[string]func()) // Registered callback functions.
func init() { func init() {
reg := regexp.MustCompile(`\-\-{0,1}(.+?)=(.+)`) reg := regexp.MustCompile(`\-\-{0,1}(.+?)=(.+)`)
Option.options = make(map[string]string) Option.options = make(map[string]string)
for i := 0; i < len(os.Args); i++ { for i := 0; i < len(os.Args); i++ {
result := reg.FindStringSubmatch(os.Args[i]) result := reg.FindStringSubmatch(os.Args[i])
if len(result) > 1 { if len(result) > 1 {
Option.options[result[1]] = result[2] Option.options[result[1]] = result[2]
} else { } else {
Value.values = append(Value.values, os.Args[i]) Value.values = append(Value.values, os.Args[i])
} }
} }
} }
// BindHandle registers callback function <f> with <cmd>. // BindHandle registers callback function <f> with <cmd>.
func BindHandle (cmd string, f func()) { func BindHandle(cmd string, f func()) {
if _, ok := cmdFuncMap[cmd]; ok { if _, ok := cmdFuncMap[cmd]; ok {
glog.Fatal("duplicated handle for command:" + cmd) glog.Fatal("duplicated handle for command:" + cmd)
} else { } else {
cmdFuncMap[cmd] = f cmdFuncMap[cmd] = f
} }
} }
// RunHandle executes the callback function registered by <cmd>. // RunHandle executes the callback function registered by <cmd>.
func RunHandle (cmd string) { func RunHandle(cmd string) {
if handle, ok := cmdFuncMap[cmd]; ok { if handle, ok := cmdFuncMap[cmd]; ok {
handle() handle()
} else { } else {
glog.Fatal("no handle found for command:" + cmd) glog.Fatal("no handle found for command:" + cmd)
} }
} }
// AutoRun automatically recognizes and executes the callback function // AutoRun automatically recognizes and executes the callback function
// by value of index 0 (the first console parameter). // by value of index 0 (the first console parameter).
func AutoRun () { func AutoRun() {
if cmd := Value.Get(1); cmd != "" { if cmd := Value.Get(1); cmd != "" {
if handle, ok := cmdFuncMap[cmd]; ok { if handle, ok := cmdFuncMap[cmd]; ok {
handle() handle()
} else { } else {
glog.Fatal("no handle found for command:" + cmd) glog.Fatal("no handle found for command:" + cmd)
} }
} else { } else {
glog.Fatal("no command found") glog.Fatal("no command found")
} }
} }

View File

@ -15,18 +15,22 @@ import (
"time" "time"
) )
// 定时任务项 // Timed task entry.
type Entry struct { type Entry struct {
cron *Cron // 所属定时任务 cron *Cron // Cron object belonged to.
entry *gtimer.Entry // 定时器任务对象 entry *gtimer.Entry // Associated gtimer.Entry.
schedule *cronSchedule // 定时任务配置对象 schedule *cronSchedule // Timed schedule object.
jobName string // 任务注册方法名称 jobName string // Callback function name(address info).
Name string // 定时任务名称 Name string // Entry name.
Job func() // 注册定时任务方法 Job func() `json:"-"` // Callback function.
Time time.Time // 注册时间 Time time.Time // Registered time.
} }
// 创建定时任务 // addEntry creates and returns a new Entry object.
// Param <job> is the callback function for timed task execution.
// Param <singleton> specifies whether timed task executing in singleton mode.
// Param <times> limits the times for timed task executing.
// Param <name> names this entry for manual control.
func (c *Cron) addEntry(pattern string, job func(), singleton bool, times int, name ... string) (*Entry, error) { func (c *Cron) addEntry(pattern string, job func(), singleton bool, times int, name ... string) (*Entry, error) {
schedule, err := newSchedule(pattern) schedule, err := newSchedule(pattern)
if err != nil { if err != nil {

View File

@ -3,11 +3,10 @@
// This Source Code Form is subject to the terms of the MIT License. // This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file, // If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf. // You can obtain one at https://github.com/gogf/gf.
//
// @author john, zseeker // @author john, zseeker
// Package glog implements powerful and easy-to-use levelled logging functionality. // Package glog implements powerful and easy-to-use levelled logging functionality.
//
// 日志模块, 直接文件/输出操作,没有异步逻辑,没有使用缓存或者通道
package glog package glog
import ( import (
@ -29,10 +28,10 @@ const (
) )
var ( var (
// default level for log // Default level for log
defaultLevel = gtype.NewInt(LEVEL_ALL) defaultLevel = gtype.NewInt(LEVEL_ALL)
// default logger object, for package method usage // Default logger object, for package method usage
logger = New() logger = New()
) )
@ -41,8 +40,6 @@ func init() {
} }
// SetPath sets the directory path for file logging. // SetPath sets the directory path for file logging.
//
// 日志日志目录绝对路径.
func SetPath(path string) { func SetPath(path string) {
logger.SetPath(path) logger.SetPath(path)
} }
@ -50,151 +47,113 @@ func SetPath(path string) {
// SetFile sets the file name <pattern> for file logging. // SetFile sets the file name <pattern> for file logging.
// Datetime pattern can be used in <pattern>, eg: access-{Ymd}.log. // Datetime pattern can be used in <pattern>, eg: access-{Ymd}.log.
// The default file name pattern is: Y-m-d.log, eg: 2018-01-01.log // The default file name pattern is: Y-m-d.log, eg: 2018-01-01.log
//
// 日志文件名称.
func SetFile(pattern string) { func SetFile(pattern string) {
logger.SetFile(pattern) logger.SetFile(pattern)
} }
// SetLevel sets the default logging level. // SetLevel sets the default logging level.
//
// 设置全局的日志记录等级.
func SetLevel(level int) { func SetLevel(level int) {
logger.SetLevel(level) logger.SetLevel(level)
defaultLevel.Set(level) defaultLevel.Set(level)
} }
// SetWriter sets the customed logging <writer> for logging. // SetWriter sets the customized logging <writer> for logging.
// The <writer> object should implements the io.Writer interface. // The <writer> object should implements the io.Writer interface.
// Developer can use customed logging <writer> to redirect logging output to another service, // Developer can use customized logging <writer> to redirect logging output to another service,
// eg: kafka, mysql, mongodb, etc. // eg: kafka, mysql, mongodb, etc.
//
// 可自定义IO接口IO可以是文件输出、标准输出、网络输出.
func SetWriter(writer io.Writer) { func SetWriter(writer io.Writer) {
logger.SetWriter(writer) logger.SetWriter(writer)
} }
// GetWriter returns the customed writer object, which implements the io.Writer interface. // GetWriter returns the customized writer object, which implements the io.Writer interface.
// It returns nil if no customed writer set. // It returns nil if no customized writer set.
//
// 返回自定义的IO默认为nil.
func GetWriter() io.Writer { func GetWriter() io.Writer {
return logger.GetWriter() return logger.GetWriter()
} }
// GetLevel returns the default logging level value. // GetLevel returns the default logging level value.
//
// 获取全局的日志记录等级.
func GetLevel() int { func GetLevel() int {
return defaultLevel.Val() return defaultLevel.Val()
} }
// SetDebug enables/disables the debug level for default logger. // SetDebug enables/disables the debug level for default logger.
// The debug level is enbaled in default. // The debug level is enbaled in default.
//
// 设置是否允许输出DEBUG信息.
func SetDebug(debug bool) { func SetDebug(debug bool) {
logger.SetDebug(debug) logger.SetDebug(debug)
} }
// SetStdPrint sets whether ouptput the logging contents to stdout, which is false indefault. // SetStdPrint sets whether ouptput the logging contents to stdout, which is false in default.
//
// 设置写日志的同时开启or关闭控制台打印默认是关闭的
func SetStdPrint(open bool) { func SetStdPrint(open bool) {
logger.SetStdPrint(open) logger.SetStdPrint(open)
} }
// GetPath returns the logging directory path for file logging. // GetPath returns the logging directory path for file logging.
// It returns empty string if no directory path set. // It returns empty string if no directory path set.
//
// 获取日志目录绝对路径
func GetPath() string { func GetPath() string {
return logger.GetPath() return logger.GetPath()
} }
// PrintBacktrace prints the caller backtrace, // PrintBacktrace prints the caller backtrace,
// the optional parameter <skip> specify the skipped backtraces offset from the end point. // the optional parameter <skip> specify the skipped backtrace offset from the end point.
//
// 打印文件调用回溯信息
func PrintBacktrace(skip...int) { func PrintBacktrace(skip...int) {
logger.PrintBacktrace(skip...) logger.PrintBacktrace(skip...)
} }
// GetBacktrace returns the caller backtrace content, // GetBacktrace returns the caller backtrace content,
// the optional parameter <skip> specify the skipped backtraces offset from the end point. // the optional parameter <skip> specify the skipped backtrace offset from the end point.
//
// 获取文件调用回溯信息.
func GetBacktrace(skip...int) string { func GetBacktrace(skip...int) string {
return logger.GetBacktrace(skip...) return logger.GetBacktrace(skip...)
} }
// SetBacktrace enables/disables the backtrace feature in failure logging outputs. // SetBacktrace enables/disables the backtrace feature in failure logging outputs.
//
// 是否关闭全局的backtrace信息
func SetBacktrace(enabled bool) { func SetBacktrace(enabled bool) {
logger.SetBacktrace(enabled) logger.SetBacktrace(enabled)
} }
// To is a chaining function, // To is a chaining function,
// which redirects current logging content output to the sepecified <writer>. // which redirects current logging content output to the sepecified <writer>.
//
// 链式操作设置下一次写入日志内容的Writer
func To(writer io.Writer) *Logger { func To(writer io.Writer) *Logger {
return logger.To(writer) return logger.To(writer)
} }
// Path is a chaining function, // Path is a chaining function,
// which sets the directory path to <path> for current logging content output. // which sets the directory path to <path> for current logging content output.
//
// 链式操作,设置下一次输出的日志路径。
func Path(path string) *Logger { func Path(path string) *Logger {
return logger.Path(path) return logger.Path(path)
} }
// Cat is a chaining function, // Cat is a chaining function,
// which sets the category to <category> for current logging content output. // which sets the category to <category> for current logging content output.
//
// 设置下一次输出的分类,支持多级分类设置.
func Cat(category string) *Logger { func Cat(category string) *Logger {
return logger.Cat(category) return logger.Cat(category)
} }
// File is a chaining function, // File is a chaining function,
// which sets file name <pattern> for the current logging content output. // which sets file name <pattern> for the current logging content output.
//
// 设置日志输出文件名称格式
func File(pattern string) *Logger { func File(pattern string) *Logger {
return logger.File(pattern) return logger.File(pattern)
} }
// Level is a chaining function, // Level is a chaining function,
// which sets logging level for the current logging content output. // which sets logging level for the current logging content output.
//
// 设置日志打印等级.
func Level(level int) *Logger { func Level(level int) *Logger {
return logger.Level(level) return logger.Level(level)
} }
// Backtrace is a chaining function, // Backtrace is a chaining function,
// which sets backtrace options for the current logging content output . // which sets backtrace options for the current logging content output .
//
// 设置文件调用回溯信息.
func Backtrace(enabled bool, skip...int) *Logger { func Backtrace(enabled bool, skip...int) *Logger {
return logger.Backtrace(enabled, skip...) return logger.Backtrace(enabled, skip...)
} }
// StdPrint is a chaining function, // StdPrint is a chaining function,
// which enables/disables stdout for the current logging content output. // which enables/disables stdout for the current logging content output.
//
// 是否允许在设置输出文件时同时也输出到终端
func StdPrint(enabled bool) *Logger { func StdPrint(enabled bool) *Logger {
return logger.StdPrint(enabled) return logger.StdPrint(enabled)
} }
// Header is a chaining function, // Header is a chaining function,
// which enables/disables log header for the current logging content output. // which enables/disables log header for the current logging content output.
//
// 是否打印每行日志头信息(默认开启)
func Header(enabled bool) *Logger { func Header(enabled bool) *Logger {
return logger.Header(enabled) return logger.Header(enabled)
} }

View File

@ -3,6 +3,7 @@
// This Source Code Form is subject to the terms of the MIT License. // This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file, // If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf. // You can obtain one at https://github.com/gogf/gf.
//
// @author john, zseeker // @author john, zseeker
package glog package glog
@ -26,15 +27,15 @@ import (
type Logger struct { type Logger struct {
mu sync.RWMutex mu sync.RWMutex
pr *Logger // 父级Logger pr *Logger // Parent logger.
io io.Writer // 日志内容写入的IO接口 io io.Writer // Customized io.Writer.
path *gtype.String // 日志写入的目录路径 path *gtype.String // Logging directory path.
file *gtype.String // 日志文件名称格式 file *gtype.String // Format for logging file.
level *gtype.Int // 日志输出等级 level *gtype.Int // Output level.
btSkip *gtype.Int // 错误产生时的backtrace回调信息skip条数 btSkip *gtype.Int // Skip count for backtrace.
btStatus *gtype.Int // 是否当打印错误时同时开启backtrace打印(默认-1表示默认打印逻辑 - 错误才打印) btStatus *gtype.Int // Backtrace status(1: enabled - default; 0: disabled)
printHeader *gtype.Bool // 是否不打印前缀信息(时间,级别等) printHeader *gtype.Bool // Print header or not(true in default).
alsoStdPrint *gtype.Bool // 控制台打印开关,当输出到文件/自定义输出时也同时打印到终端 alsoStdPrint *gtype.Bool // Output to stdout or not(true in default).
} }
const ( const (
@ -45,70 +46,66 @@ const (
) )
var ( var (
// 默认的日志换行符 // Default line break.
ln = "\n" ln = "\n"
// 标准输出互斥锁,防止标准输出串日志 // Mutex to ensure log output sequence.
stdMu = sync.RWMutex{} stdMu = sync.RWMutex{}
) )
// 初始化日志换行符
func init() { func init() {
// Initialize log line breaks depending on underlying os.
if runtime.GOOS == "windows" { if runtime.GOOS == "windows" {
ln = "\r\n" ln = "\r\n"
} }
} }
// New creates a custom logger. // New creates and returns a custom logger.
//
// 新建自定义的日志操作对象
func New() *Logger { func New() *Logger {
return &Logger { logger := &Logger {
io : nil,
path : gtype.NewString(), path : gtype.NewString(),
file : gtype.NewString(gDEFAULT_FILE_FORMAT), file : gtype.NewString(gDEFAULT_FILE_FORMAT),
level : gtype.NewInt(defaultLevel.Val()), level : gtype.NewInt(defaultLevel.Val()),
btSkip : gtype.NewInt(), btSkip : gtype.NewInt(),
btStatus : gtype.NewInt(-1), btStatus : gtype.NewInt(1),
printHeader : gtype.NewBool(true), printHeader : gtype.NewBool(true),
alsoStdPrint : gtype.NewBool(true), alsoStdPrint : gtype.NewBool(true),
} }
logger.io = &Writer {
logger : logger,
}
return logger
} }
// Clone returns a new logger, which is the clone the current logger. // Clone returns a new logger, which is the clone the current logger.
//
// Logger拷贝.
func (l *Logger) Clone() *Logger { func (l *Logger) Clone() *Logger {
return &Logger { logger := &Logger {
pr : l, pr : l,
io : l.GetWriter(),
path : l.path.Clone(), path : l.path.Clone(),
file : l.file.Clone(), file : l.file.Clone(),
level : l.level.Clone(), level : l.level.Clone(),
btSkip : l.btSkip.Clone(), btSkip : l.btSkip.Clone(),
btStatus : l.btStatus.Clone(), btStatus : l.btStatus.Clone(),
printHeader : l.printHeader.Clone(), printHeader : l.printHeader.Clone(),
alsoStdPrint : l.alsoStdPrint.Clone(), alsoStdPrint : l.alsoStdPrint.Clone(),
} }
logger.io = &Writer {
logger : logger,
}
return logger
} }
// SetLevel sets the logging level. // SetLevel sets the logging level.
//
// 设置日志记录等级
func (l *Logger) SetLevel(level int) { func (l *Logger) SetLevel(level int) {
l.level.Set(level) l.level.Set(level)
} }
// GetLevel returns the logging level value. // GetLevel returns the logging level value.
//
// 获取日志记录等级
func (l *Logger) GetLevel() int { func (l *Logger) GetLevel() int {
return l.level.Val() return l.level.Val()
} }
// SetDebug enables/disables the debug level for logger. // SetDebug enables/disables the debug level for logger.
// The debug level is enbaled in default. // The debug level is enabled in default.
//
// 快捷方法打开或关闭DEBU日志信息
func (l *Logger) SetDebug(debug bool) { func (l *Logger) SetDebug(debug bool) {
if debug { if debug {
l.level.Set(l.level.Val() | LEVEL_DEBU) l.level.Set(l.level.Val() | LEVEL_DEBU)
@ -124,7 +121,6 @@ func (l *Logger) SetBacktrace(enabled bool) {
} else { } else {
l.btStatus.Set(0) l.btStatus.Set(0)
} }
} }
// SetBacktraceSkip sets the backtrace offset from the end point. // SetBacktraceSkip sets the backtrace offset from the end point.
@ -132,22 +128,18 @@ func (l *Logger) SetBacktraceSkip(skip int) {
l.btSkip.Set(skip) l.btSkip.Set(skip)
} }
// SetWriter sets the customed logging <writer> for logging. // SetWriter sets the customized logging <writer> for logging.
// The <writer> object should implements the io.Writer interface. // The <writer> object should implements the io.Writer interface.
// Developer can use customed logging <writer> to redirect logging output to another service, // Developer can use customized logging <writer> to redirect logging output to another service,
// eg: kafka, mysql, mongodb, etc. // eg: kafka, mysql, mongodb, etc.
//
// 可自定义IO接口IO可以是文件输出、标准输出、网络输出
func (l *Logger) SetWriter(writer io.Writer) { func (l *Logger) SetWriter(writer io.Writer) {
l.mu.Lock() l.mu.Lock()
l.io = writer l.io = writer
l.mu.Unlock() l.mu.Unlock()
} }
// GetWriter returns the customed writer object, which implements the io.Writer interface. // GetWriter returns the customized writer object, which implements the io.Writer interface.
// It returns nil if no customed writer set. // It returns a default writer if no customized writer set.
//
// 返回自定义的IO默认为nil
func (l *Logger) GetWriter() io.Writer { func (l *Logger) GetWriter() io.Writer {
l.mu.RLock() l.mu.RLock()
r := l.io r := l.io
@ -156,23 +148,21 @@ func (l *Logger) GetWriter() io.Writer {
} }
// getFilePointer returns the file pinter for file logging. // getFilePointer returns the file pinter for file logging.
// It returns nil if file logging disabled, or file open fails. // It returns nil if file logging is disabled, or file opening fails.
//
// 获取默认的文件IO.
func (l *Logger) getFilePointer() *gfpool.File { func (l *Logger) getFilePointer() *gfpool.File {
if path := l.path.Val(); path != "" { if path := l.path.Val(); path != "" {
// 文件名称中使用"{}"包含的内容使用gtime格式化 // Content containing "{}" in the file name is formatted using gtime
file, _ := gregex.ReplaceStringFunc(`{.+?}`, l.file.Val(), func(s string) string { file, _ := gregex.ReplaceStringFunc(`{.+?}`, l.file.Val(), func(s string) string {
return gtime.Now().Format(strings.Trim(s, "{}")) return gtime.Now().Format(strings.Trim(s, "{}"))
}) })
// 如果日志目录不存在则创建目录路径 // Create path if it does not exist。
if !gfile.Exists(path) { if !gfile.Exists(path) {
if err := gfile.Mkdir(path); err != nil { if err := gfile.Mkdir(path); err != nil {
fmt.Fprintln(os.Stderr, fmt.Sprintf(`[glog] mkdir "%s" failed: %s`, path, err.Error())) fmt.Fprintln(os.Stderr, fmt.Sprintf(`[glog] mkdir "%s" failed: %s`, path, err.Error()))
return nil return nil
} }
} }
fpath := path + gfile.Separator + file fpath := path + gfile.Separator + file
if fp, err := gfpool.Open(fpath, gDEFAULT_FILE_POOL_FLAGS, gDEFAULT_FPOOL_PERM, gDEFAULT_FPOOL_EXPIRE); err == nil { if fp, err := gfpool.Open(fpath, gDEFAULT_FILE_POOL_FLAGS, gDEFAULT_FPOOL_PERM, gDEFAULT_FPOOL_EXPIRE); err == nil {
return fp return fp
} else { } else {
@ -183,14 +173,10 @@ func (l *Logger) getFilePointer() *gfpool.File {
} }
// SetPath sets the directory path for file logging. // SetPath sets the directory path for file logging.
//
// 设置日志文件的存储目录路径.
func (l *Logger) SetPath(path string) error { func (l *Logger) SetPath(path string) error {
// path必须有值
if path == "" { if path == "" {
return errors.New("path is empty") return errors.New("path is empty")
} }
// 如果目录不存在,则递归创建
if !gfile.Exists(path) { if !gfile.Exists(path) {
if err := gfile.Mkdir(path); err != nil { if err := gfile.Mkdir(path); err != nil {
fmt.Fprintln(os.Stderr, fmt.Sprintf(`[glog] mkdir "%s" failed: %s`, path, err.Error())) fmt.Fprintln(os.Stderr, fmt.Sprintf(`[glog] mkdir "%s" failed: %s`, path, err.Error()))
@ -203,8 +189,6 @@ func (l *Logger) SetPath(path string) error {
// GetPath returns the logging directory path for file logging. // GetPath returns the logging directory path for file logging.
// It returns empty string if no directory path set. // It returns empty string if no directory path set.
//
// 获取设置的日志目录路径
func (l *Logger) GetPath() string { func (l *Logger) GetPath() string {
return l.path.Val() return l.path.Val()
} }
@ -212,29 +196,24 @@ func (l *Logger) GetPath() string {
// SetFile sets the file name <pattern> for file logging. // SetFile sets the file name <pattern> for file logging.
// Datetime pattern can be used in <pattern>, eg: access-{Ymd}.log. // Datetime pattern can be used in <pattern>, eg: access-{Ymd}.log.
// The default file name pattern is: Y-m-d.log, eg: 2018-01-01.log // The default file name pattern is: Y-m-d.log, eg: 2018-01-01.log
//
// 设置日志文件名称格式.
func (l *Logger) SetFile(pattern string) { func (l *Logger) SetFile(pattern string) {
l.file.Set(pattern) l.file.Set(pattern)
} }
// SetStdPrint sets whether ouptput the logging contents to stdout, which is false indefault. // SetStdPrint sets whether output the logging contents to stdout, which is false in default.
//
// 设置写日志时开启or关闭控制台打印默认是关闭的
func (l *Logger) SetStdPrint(enabled bool) { func (l *Logger) SetStdPrint(enabled bool) {
l.alsoStdPrint.Set(enabled) l.alsoStdPrint.Set(enabled)
} }
// 这里的写锁保证统一时刻只会写入一行日志,防止串日志的情况 // print prints <s> to defined writer, logging file or passed <std>.
// It internally uses memory lock for file logging to ensure logging sequence.
func (l *Logger) print(std io.Writer, s string) { func (l *Logger) print(std io.Writer, s string) {
// 优先使用自定义的IO输出 // Customized writer has the most high priority.
if l.printHeader.Val() { if l.printHeader.Val() {
s = l.format(s) s = l.format(s)
} }
writer := l.GetWriter() writer := l.GetWriter()
if writer == nil { if _, ok := writer.(*Writer); ok {
// 如果设置的writer为空那么其次判断是否有文件输出设置
// 内部使用了内存锁保证在glog中对同一个日志文件的并发写入不会串日志(并发安全)
if f := l.getFilePointer(); f != nil { if f := l.getFilePointer(); f != nil {
defer f.Close() defer f.Close()
key := l.path.Val() key := l.path.Val()
@ -245,7 +224,7 @@ func (l *Logger) print(std io.Writer, s string) {
fmt.Fprintln(os.Stderr, err.Error()) fmt.Fprintln(os.Stderr, err.Error())
} }
} }
// 当没有设置writer时需要判断是否允许输出到标准输出 // Also output to stdout?
if l.alsoStdPrint.Val() { if l.alsoStdPrint.Val() {
l.doStdLockPrint(std, s) l.doStdLockPrint(std, s)
} }
@ -254,7 +233,7 @@ func (l *Logger) print(std io.Writer, s string) {
} }
} }
// 并发安全打印到标准输出 // doStdLockPrint prints <s> to <std> concurrent-safely.
func (l *Logger) doStdLockPrint(std io.Writer, s string) { func (l *Logger) doStdLockPrint(std io.Writer, s string) {
stdMu.Lock() stdMu.Lock()
if _, err := std.Write([]byte(s)); err != nil { if _, err := std.Write([]byte(s)); err != nil {
@ -263,23 +242,21 @@ func (l *Logger) doStdLockPrint(std io.Writer, s string) {
stdMu.Unlock() stdMu.Unlock()
} }
// 核心打印数据方法(标准输出) // stdPrint prints content <s> without backtrace.
func (l *Logger) stdPrint(s string) { func (l *Logger) stdPrint(s string) {
l.print(os.Stdout, s) l.print(os.Stdout, s)
} }
// 核心打印数据方法(标准错误) // stdPrint prints content <s> with backtrace check.
func (l *Logger) errPrint(s string) { func (l *Logger) errPrint(s string) {
// 记录调用回溯信息 if l.btStatus.Val() == 1 {
status := l.btStatus.Val()
if status == -1 || status == 1 {
s = l.appendBacktrace(s) s = l.appendBacktrace(s)
} }
// 防止串日志情况这里不使用stderr而是使用stdout // In matter of sequence, do not use stderr here, but use the same stdout.
l.print(os.Stdout, s) l.print(os.Stdout, s)
} }
// 输出内容中添加回溯信息 // appendBacktrace appends backtrace to the <s>.
func (l *Logger) appendBacktrace(s string, skip...int) string { func (l *Logger) appendBacktrace(s string, skip...int) string {
trace := l.GetBacktrace(skip...) trace := l.GetBacktrace(skip...)
if trace != "" { if trace != "" {
@ -298,17 +275,13 @@ func (l *Logger) appendBacktrace(s string, skip...int) string {
} }
// PrintBacktrace prints the caller backtrace, // PrintBacktrace prints the caller backtrace,
// the optional parameter <skip> specify the skipped backtraces offset from the end point. // the optional parameter <skip> specify the skipped backtrace offset from the end point.
//
// 直接打印回溯信息参数skip表示调用端往上多少级开始回溯
func (l *Logger) PrintBacktrace(skip...int) { func (l *Logger) PrintBacktrace(skip...int) {
l.Println(l.appendBacktrace("", skip...)) l.Println(l.appendBacktrace("", skip...))
} }
// GetBacktrace returns the caller backtrace content, // GetBacktrace returns the caller backtrace content,
// the optional parameter <skip> specify the skipped backtraces offset from the end point. // the optional parameter <skip> specify the skipped backtrace offset from the end point.
//
// 获取文件调用回溯字符串参数skip表示调用端往上多少级开始回溯
func (l *Logger) GetBacktrace(skip...int) string { func (l *Logger) GetBacktrace(skip...int) string {
customSkip := 0 customSkip := 0
if len(skip) > 0 { if len(skip) > 0 {
@ -507,8 +480,6 @@ func (l *Logger) Criticalfln(format string, v ...interface{}) {
} }
// checkLevel checks whether the given <level> could be output. // checkLevel checks whether the given <level> could be output.
//
// 判断给定level是否满足
func (l *Logger) checkLevel(level int) bool { func (l *Logger) checkLevel(level int) bool {
return l.level.Val() & level > 0 return l.level.Val() & level > 0
} }

View File

@ -13,8 +13,6 @@ import (
// To is a chaining function, // To is a chaining function,
// which redirects current logging content output to the specified <writer>. // which redirects current logging content output to the specified <writer>.
//
// 链式操作设置下一次写入日志内容的Writer
func (l *Logger) To(writer io.Writer) *Logger { func (l *Logger) To(writer io.Writer) *Logger {
logger := (*Logger)(nil) logger := (*Logger)(nil)
if l.pr == nil { if l.pr == nil {
@ -28,8 +26,6 @@ func (l *Logger) To(writer io.Writer) *Logger {
// Path is a chaining function, // Path is a chaining function,
// which sets the directory path to <path> for current logging content output. // which sets the directory path to <path> for current logging content output.
//
// 链式操作,设置下一次输出的日志路径。
func (l *Logger) Path(path string) *Logger { func (l *Logger) Path(path string) *Logger {
logger := (*Logger)(nil) logger := (*Logger)(nil)
if l.pr == nil { if l.pr == nil {
@ -45,9 +41,7 @@ func (l *Logger) Path(path string) *Logger {
// Cat is a chaining function, // Cat is a chaining function,
// which sets the category to <category> for current logging content output. // which sets the category to <category> for current logging content output.
// // Param <category> can be hierarchical, eg: module/user.
// 链式操作,设置下一次输出的日志分类(可以按照文件目录层级设置)在当前logpath或者当前工作目录下创建category目录
// 这是一个链式操作,可以设置多个分类,将会创建层级的日志分类目录。
func (l *Logger) Cat(category string) *Logger { func (l *Logger) Cat(category string) *Logger {
logger := (*Logger)(nil) logger := (*Logger)(nil)
if l.pr == nil { if l.pr == nil {
@ -64,8 +58,6 @@ func (l *Logger) Cat(category string) *Logger {
// File is a chaining function, // File is a chaining function,
// which sets file name <pattern> for the current logging content output. // which sets file name <pattern> for the current logging content output.
//
// 日志文件格式
func (l *Logger) File(file string) *Logger { func (l *Logger) File(file string) *Logger {
logger := (*Logger)(nil) logger := (*Logger)(nil)
if l.pr == nil { if l.pr == nil {
@ -79,8 +71,6 @@ func (l *Logger) File(file string) *Logger {
// Level is a chaining function, // Level is a chaining function,
// which sets logging level for the current logging content output. // which sets logging level for the current logging content output.
//
// 设置日志打印等级
func (l *Logger) Level(level int) *Logger { func (l *Logger) Level(level int) *Logger {
logger := (*Logger)(nil) logger := (*Logger)(nil)
if l.pr == nil { if l.pr == nil {
@ -94,8 +84,6 @@ func (l *Logger) Level(level int) *Logger {
// Backtrace is a chaining function, // Backtrace is a chaining function,
// which sets backtrace options for the current logging content output . // which sets backtrace options for the current logging content output .
//
// 设置文件调用回溯信息
func (l *Logger) Backtrace(enabled bool, skip...int) *Logger { func (l *Logger) Backtrace(enabled bool, skip...int) *Logger {
logger := (*Logger)(nil) logger := (*Logger)(nil)
if l.pr == nil { if l.pr == nil {
@ -112,8 +100,6 @@ func (l *Logger) Backtrace(enabled bool, skip...int) *Logger {
// StdPrint is a chaining function, // StdPrint is a chaining function,
// which enables/disables stdout for the current logging content output. // which enables/disables stdout for the current logging content output.
//
// 是否允许在设置输出文件时同时也输出到终端
func (l *Logger) StdPrint(enabled bool) *Logger { func (l *Logger) StdPrint(enabled bool) *Logger {
logger := (*Logger)(nil) logger := (*Logger)(nil)
if l.pr == nil { if l.pr == nil {
@ -127,8 +113,6 @@ func (l *Logger) StdPrint(enabled bool) *Logger {
// Header is a chaining function, // Header is a chaining function,
// which enables/disables log header for the current logging content output. // which enables/disables log header for the current logging content output.
//
// 是否打印每行日志头信息(默认开启)
func (l *Logger) Header(enabled bool) *Logger { func (l *Logger) Header(enabled bool) *Logger {
logger := (*Logger)(nil) logger := (*Logger)(nil)
if l.pr == nil { if l.pr == nil {

19
g/os/glog/glog_writer.go Normal file
View File

@ -0,0 +1,19 @@
// Copyright 2017 gf Author(https://github.com/gogf/gf). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf.
package glog
type Writer struct {
logger *Logger
}
// Write implements the io.Writer interface.
// It just prints the content with header or level.
func (w *Writer) Write(p []byte) (n int, err error) {
w.logger.Header(false).Print(string(p))
return len(p), nil
}

View File

@ -39,7 +39,7 @@ func Export(i...interface{}) string {
// 这里强制对所有map进行反射处理转换 // 这里强制对所有map进行反射处理转换
refValue := reflect.ValueOf(v) refValue := reflect.ValueOf(v)
if refValue.Kind() == reflect.Map { if refValue.Kind() == reflect.Map {
m := make(map[string]interface{}) m := make(map[string]interface{})
keys := refValue.MapKeys() keys := refValue.MapKeys()
for _, k := range keys { for _, k := range keys {
m[gconv.String(k.Interface())] = refValue.MapIndex(k).Interface() m[gconv.String(k.Interface())] = refValue.MapIndex(k).Interface()

View File

@ -1,7 +1,7 @@
package main package main
import ( import (
"fmt" "github.com/gogf/gf/g"
"github.com/gogf/gf/g/os/gcron" "github.com/gogf/gf/g/os/gcron"
"time" "time"
) )
@ -12,7 +12,9 @@ func test() {
func main() { func main() {
_, err := gcron.Add("*/10 * * * * ?", test) _, err := gcron.Add("*/10 * * * * ?", test)
fmt.Println(err) if err != nil {
fmt.Println(gcron.Entries()) panic(err)
}
g.Dump(gcron.Entries())
time.Sleep(10 * time.Second) time.Sleep(10 * time.Second)
} }

View File

@ -0,0 +1,10 @@
package main
import (
"github.com/gogf/gf/g/os/glog"
)
func main() {
w := glog.GetWriter()
w.Write([]byte("hello"))
}