add logging for gcron

This commit is contained in:
John
2019-03-19 13:58:18 +08:00
parent 60e5a7da28
commit 4e3d735b90
9 changed files with 184 additions and 12 deletions

View File

@ -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) {

View 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")
})
}

View File

@ -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...)
}

View File

@ -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 {

View File

@ -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()
}

View File

@ -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.
//

View File

@ -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.
//

View File

@ -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

View File

@ -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})
}
})
}