mirror of
https://gitee.com/johng/gf
synced 2026-07-04 13:02:36 +08:00
add logging for gcron
This commit is contained in:
@ -242,7 +242,7 @@ func (s *Server) Start() error {
|
||||
s.config.Handler = http.HandlerFunc(s.defaultHttpHandle)
|
||||
}
|
||||
// 不允许访问的路由注册(使用HOOK实现)
|
||||
// @TODO 去掉HOOK的实现方式
|
||||
// TODO 去掉HOOK的实现方式
|
||||
if s.config.DenyRoutes != nil {
|
||||
for _, v := range s.config.DenyRoutes {
|
||||
s.BindHookHandler(v, HOOK_BEFORE_SERVE, func(r *Request) {
|
||||
|
||||
77
g/os/gcfg/gcfg_z_unit_test.go
Normal file
77
g/os/gcfg/gcfg_z_unit_test.go
Normal file
@ -0,0 +1,77 @@
|
||||
// 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.
|
||||
|
||||
// go test *.go -bench=".*" -benchmem
|
||||
|
||||
package gcfg_test
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/g/os/gcfg"
|
||||
"github.com/gogf/gf/g/os/gfile"
|
||||
"github.com/gogf/gf/g/test/gtest"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func Test_Basic(t *testing.T) {
|
||||
config := `
|
||||
v1 = 1
|
||||
v2 = "true"
|
||||
v3 = "off"
|
||||
v4 = "1.23"
|
||||
array = [1,2,3]
|
||||
[redis]
|
||||
disk = "127.0.0.1:6379,0"
|
||||
cache = "127.0.0.1:6379,1"
|
||||
`
|
||||
gtest.Case(t, func() {
|
||||
path := "config.toml"
|
||||
err := gfile.PutContents(path, config)
|
||||
gtest.Assert(err, nil)
|
||||
defer gfile.Remove(path)
|
||||
|
||||
c := gcfg.New(".")
|
||||
gtest.Assert(c.Get("v1"), 1)
|
||||
gtest.AssertEQ(c.GetInt("v1"), 1)
|
||||
gtest.AssertEQ(c.GetInt8("v1"), int8(1))
|
||||
gtest.AssertEQ(c.GetInt16("v1"), int16(1))
|
||||
gtest.AssertEQ(c.GetInt32("v1"), int32(1))
|
||||
gtest.AssertEQ(c.GetInt64("v1"), int64(1))
|
||||
gtest.AssertEQ(c.GetUint("v1"), uint(1))
|
||||
gtest.AssertEQ(c.GetUint8("v1"), uint8(1))
|
||||
gtest.AssertEQ(c.GetUint16("v1"), uint16(1))
|
||||
gtest.AssertEQ(c.GetUint32("v1"), uint32(1))
|
||||
gtest.AssertEQ(c.GetUint64("v1"), uint64(1))
|
||||
|
||||
gtest.AssertEQ(c.GetVar("v1").String(), "1")
|
||||
gtest.AssertEQ(c.GetVar("v1").Bool(), true)
|
||||
gtest.AssertEQ(c.GetVar("v2").String(), "true")
|
||||
gtest.AssertEQ(c.GetVar("v2").Bool(), true)
|
||||
|
||||
gtest.AssertEQ(c.GetString("v1"), "1")
|
||||
gtest.AssertEQ(c.GetFloat32("v4"), float32(1.23))
|
||||
gtest.AssertEQ(c.GetFloat64("v4"), float64(1.23))
|
||||
gtest.AssertEQ(c.GetString("v2"), "true")
|
||||
gtest.AssertEQ(c.GetBool("v2"), true)
|
||||
gtest.AssertEQ(c.GetBool("v3"), false)
|
||||
|
||||
gtest.AssertEQ(c.Contains("v1"), true)
|
||||
gtest.AssertEQ(c.Contains("v2"), true)
|
||||
gtest.AssertEQ(c.Contains("v3"), true)
|
||||
gtest.AssertEQ(c.Contains("v4"), true)
|
||||
gtest.AssertEQ(c.Contains("v5"), false)
|
||||
|
||||
gtest.AssertEQ(c.GetInts("array"), []int{1,2,3})
|
||||
gtest.AssertEQ(c.GetStrings("array"), []string{"1","2","3"})
|
||||
gtest.AssertEQ(c.GetArray("array"), []interface{}{"1","2","3"})
|
||||
gtest.AssertEQ(c.GetInterfaces("array"), []interface{}{"1","2","3"})
|
||||
gtest.AssertEQ(c.GetMap("redis"), map[string]interface{}{
|
||||
"disk" : "127.0.0.1:6379,0",
|
||||
"cache" : "127.0.0.1:6379,1",
|
||||
})
|
||||
gtest.AssertEQ(c.GetFilePath(), gfile.Pwd() + gfile.Separator + "config.toml")
|
||||
|
||||
})
|
||||
}
|
||||
@ -29,7 +29,27 @@ var (
|
||||
defaultCron = New()
|
||||
)
|
||||
|
||||
// 添加执行方法,可以给定名字,以便于后续执行删除
|
||||
// 设置日志输出路径
|
||||
func SetLogPath(path string) {
|
||||
defaultCron.SetLogPath(path)
|
||||
}
|
||||
|
||||
// 获取设置的日志输出路径
|
||||
func GetLogPath() string {
|
||||
return defaultCron.GetLogPath()
|
||||
}
|
||||
|
||||
// 设置日志输出等级。
|
||||
func SetLogLevel(level int) {
|
||||
defaultCron.SetLogLevel(level)
|
||||
}
|
||||
|
||||
// 获取日志输出等级。
|
||||
func GetLogLevel() int {
|
||||
return defaultCron.GetLogLevel()
|
||||
}
|
||||
|
||||
// 添加定时任务,可以给定名字,以便于后续执行删除
|
||||
func Add(pattern string, job func(), name ... string) (*Entry, error) {
|
||||
return defaultCron.Add(pattern, job, name...)
|
||||
}
|
||||
|
||||
@ -12,26 +12,51 @@ import (
|
||||
"github.com/gogf/gf/g/container/garray"
|
||||
"github.com/gogf/gf/g/container/gmap"
|
||||
"github.com/gogf/gf/g/container/gtype"
|
||||
"github.com/gogf/gf/g/os/glog"
|
||||
"github.com/gogf/gf/g/os/gtimer"
|
||||
"time"
|
||||
)
|
||||
|
||||
// 定时任务管理对象
|
||||
type Cron struct {
|
||||
idgen *gtype.Int // 用于唯一名称生成
|
||||
status *gtype.Int // 定时任务状态(0: 未执行; 1: 运行中; 2: 已停止; -1:删除关闭)
|
||||
entries *gmap.StringInterfaceMap // 所有的定时任务项
|
||||
idGen *gtype.Int64 // 用于唯一名称生成
|
||||
status *gtype.Int // 定时任务状态(0: 未执行; 1: 运行中; 2: 已停止; -1:删除关闭)
|
||||
entries *gmap.StringInterfaceMap // 所有的定时任务项
|
||||
logPath *gtype.String // 日志文件输出目录
|
||||
logLevel *gtype.Int // 日志输出等级
|
||||
}
|
||||
|
||||
// 创建自定义的定时任务管理对象
|
||||
func New() *Cron {
|
||||
return &Cron {
|
||||
idgen : gtype.NewInt(1000000),
|
||||
status : gtype.NewInt(STATUS_RUNNING),
|
||||
entries : gmap.NewStringInterfaceMap(),
|
||||
idGen : gtype.NewInt64(),
|
||||
status : gtype.NewInt(STATUS_RUNNING),
|
||||
entries : gmap.NewStringInterfaceMap(),
|
||||
logPath : gtype.NewString(),
|
||||
logLevel : gtype.NewInt(glog.LEVEL_PROD),
|
||||
}
|
||||
}
|
||||
|
||||
// 设置日志输出路径
|
||||
func (c *Cron) SetLogPath(path string) {
|
||||
c.logPath.Set(path)
|
||||
}
|
||||
|
||||
// 获取设置的日志输出路径
|
||||
func (c *Cron) GetLogPath() string {
|
||||
return c.logPath.Val()
|
||||
}
|
||||
|
||||
// 设置日志输出等级。
|
||||
func (c *Cron) SetLogLevel(level int) {
|
||||
c.logLevel.Set(level)
|
||||
}
|
||||
|
||||
// 获取日志输出等级。
|
||||
func (c *Cron) GetLogLevel() int {
|
||||
return c.logLevel.Val()
|
||||
}
|
||||
|
||||
// 添加定时任务
|
||||
func (c *Cron) Add(pattern string, job func(), name ... string) (*Entry, error) {
|
||||
if len(name) > 0 {
|
||||
|
||||
@ -7,8 +7,11 @@
|
||||
package gcron
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/g/os/glog"
|
||||
"github.com/gogf/gf/g/os/gtimer"
|
||||
"strconv"
|
||||
"github.com/gogf/gf/g/util/gconv"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"time"
|
||||
)
|
||||
|
||||
@ -17,6 +20,7 @@ type Entry struct {
|
||||
cron *Cron // 所属定时任务
|
||||
entry *gtimer.Entry // 定时器任务对象
|
||||
schedule *cronSchedule // 定时任务配置对象
|
||||
jobName string // 任务注册方法名称
|
||||
Name string // 定时任务名称
|
||||
Job func() // 注册定时任务方法
|
||||
Time time.Time // 注册时间
|
||||
@ -31,13 +35,14 @@ func (c *Cron) addEntry(pattern string, job func(), singleton bool, times int, n
|
||||
entry := &Entry {
|
||||
cron : c,
|
||||
schedule : schedule,
|
||||
jobName : runtime.FuncForPC(reflect.ValueOf(job).Pointer()).Name(),
|
||||
Job : job,
|
||||
Time : time.Now(),
|
||||
}
|
||||
if len(name) > 0 {
|
||||
entry.Name = name[0]
|
||||
} else {
|
||||
entry.Name = strconv.Itoa(c.idgen.Add(1))
|
||||
entry.Name = "gcron-" + gconv.String(c.idGen.Add(1))
|
||||
}
|
||||
entry.entry = gtimer.AddEntry(time.Second, entry.check, singleton, times, gtimer.STATUS_STOPPED)
|
||||
entry.entry.Start()
|
||||
@ -89,20 +94,29 @@ func (entry *Entry) Close() {
|
||||
// 定时任务检查执行
|
||||
func (entry *Entry) check() {
|
||||
if entry.schedule.meet(time.Now()) {
|
||||
path := entry.cron.GetLogPath()
|
||||
level := entry.cron.GetLogLevel()
|
||||
switch entry.cron.status.Val() {
|
||||
case STATUS_STOPPED:
|
||||
return
|
||||
|
||||
case STATUS_CLOSED:
|
||||
entry.cron.Remove(entry.Name)
|
||||
glog.Path(path).Level(level).Debugfln("[gcron] %s(%s) %s remove", entry.Name, entry.schedule.pattern, entry.jobName)
|
||||
gtimer.Exit()
|
||||
|
||||
case STATUS_READY: fallthrough
|
||||
case STATUS_RUNNING:
|
||||
glog.Path(path).Level(level).Debugfln("[gcron] %s(%s) %s start", entry.Name, entry.schedule.pattern, entry.jobName)
|
||||
defer func() {
|
||||
if entry.entry.Status() == STATUS_CLOSED {
|
||||
entry.cron.Remove(entry.Name)
|
||||
}
|
||||
if err := recover(); err != nil {
|
||||
glog.Path(path).Level(level).Errorfln("[gcron] %s(%s) %s end with error: %v", entry.Name, entry.schedule.pattern, entry.jobName, err)
|
||||
} else {
|
||||
glog.Path(path).Level(level).Debugfln("[gcron] %s(%s) %s end", entry.Name, entry.schedule.pattern, entry.jobName)
|
||||
}
|
||||
}()
|
||||
entry.Job()
|
||||
}
|
||||
|
||||
@ -18,6 +18,8 @@ import (
|
||||
|
||||
const (
|
||||
LEVEL_ALL = LEVEL_DEBU | LEVEL_INFO | LEVEL_NOTI | LEVEL_WARN | LEVEL_ERRO | LEVEL_CRIT
|
||||
LEVEL_DEV = LEVEL_ALL
|
||||
LEVEL_PROD = LEVEL_WARN | LEVEL_ERRO | LEVEL_CRIT
|
||||
LEVEL_DEBU = 1 << iota
|
||||
LEVEL_INFO
|
||||
LEVEL_NOTI
|
||||
@ -141,6 +143,14 @@ func To(writer io.Writer) *Logger {
|
||||
return logger.To(writer)
|
||||
}
|
||||
|
||||
// Path is a chaining function,
|
||||
// which sets the directory path to <path> for current logging content output.
|
||||
//
|
||||
// 链式操作,设置下一次输出的日志路径。
|
||||
func Path(path string) *Logger {
|
||||
return logger.Path(path)
|
||||
}
|
||||
|
||||
// Cat is a chaining function,
|
||||
// which sets the category to <category> for current logging content output.
|
||||
//
|
||||
|
||||
@ -26,6 +26,23 @@ func (l *Logger) To(writer io.Writer) *Logger {
|
||||
return logger
|
||||
}
|
||||
|
||||
// Path is a chaining function,
|
||||
// which sets the directory path to <path> for current logging content output.
|
||||
//
|
||||
// 链式操作,设置下一次输出的日志路径。
|
||||
func (l *Logger) Path(path string) *Logger {
|
||||
logger := (*Logger)(nil)
|
||||
if l.pr == nil {
|
||||
logger = l.Clone()
|
||||
} else {
|
||||
logger = l
|
||||
}
|
||||
if path != "" {
|
||||
logger.SetPath(path)
|
||||
}
|
||||
return logger
|
||||
}
|
||||
|
||||
// Cat is a chaining function,
|
||||
// which sets the category to <category> for current logging content output.
|
||||
//
|
||||
|
||||
@ -47,7 +47,7 @@ func init() {
|
||||
// 自定义的 rand.Intn ,绝对随机, 返回: [0, max)
|
||||
func Intn (max int) int {
|
||||
n := int(<- bufferChan)%max
|
||||
if n < 0 {
|
||||
if (max > 0 && n < 0) || (max < 0 && n > 0) {
|
||||
return -n
|
||||
}
|
||||
return n
|
||||
|
||||
@ -17,9 +17,15 @@ import (
|
||||
|
||||
func Test_Intn(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
for i := 0; i < 100; i++ {
|
||||
for i := 0; i < 1000000; i++ {
|
||||
n := grand.Intn(100)
|
||||
gtest.AssertLT(n, 100)
|
||||
gtest.AssertGTE(n, 0)
|
||||
}
|
||||
for i := 0; i < 1000000; i++ {
|
||||
n := grand.Intn(-100)
|
||||
gtest.AssertLTE(n, 0)
|
||||
gtest.AssertGT(n, -100)
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -77,6 +83,9 @@ func Test_Rand(t *testing.T) {
|
||||
for i := 0; i < 100; i++ {
|
||||
gtest.AssertIN(grand.Rand(1, 2), []int{1, 2})
|
||||
}
|
||||
for i := 0; i < 100; i++ {
|
||||
gtest.AssertIN(grand.Rand(-1, 2), []int{-1, 0, 1, 2})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user