mirror of
https://github.com/astaxie/beego.git
synced 2024-12-22 22:30:49 +00:00
Merge branch 'develop' into log_enhancement
This commit is contained in:
commit
9da4d1d847
@ -53,6 +53,7 @@ Please see [Documentation](http://beego.me/docs) for more.
|
||||
## Community
|
||||
|
||||
* [http://beego.me/community](http://beego.me/community)
|
||||
* Welcome to join us in Slack: [https://beego.slack.com](https://beego.slack.com), you can get invited from [here](https://github.com/beego/beedoc/issues/232)
|
||||
|
||||
## LICENSE
|
||||
|
||||
|
@ -294,7 +294,7 @@ func parseConfig(appConfigPath string) (err error) {
|
||||
}
|
||||
|
||||
//init log
|
||||
BeeLogger.Close()
|
||||
BeeLogger.Reset()
|
||||
for adaptor, config := range BConfig.Log.Outputs {
|
||||
err = BeeLogger.SetLogger(adaptor, config)
|
||||
if err != nil {
|
||||
|
53
logs/log.go
53
logs/log.go
@ -98,6 +98,8 @@ type BeeLogger struct {
|
||||
loggerFuncCallDepth int
|
||||
asynchronous bool
|
||||
msgChan chan *logMsg
|
||||
signalChan chan string
|
||||
wg sync.WaitGroup
|
||||
outputs []*nameLogger
|
||||
}
|
||||
|
||||
@ -122,6 +124,7 @@ func NewLogger(channelLen int64) *BeeLogger {
|
||||
bl.level = LevelDebug
|
||||
bl.loggerFuncCallDepth = 2
|
||||
bl.msgChan = make(chan *logMsg, channelLen)
|
||||
bl.signalChan = make(chan string, 1)
|
||||
return bl
|
||||
}
|
||||
|
||||
@ -133,6 +136,7 @@ func (bl *BeeLogger) Async() *BeeLogger {
|
||||
return &logMsg{}
|
||||
},
|
||||
}
|
||||
bl.wg.Add(1)
|
||||
go bl.startLogger()
|
||||
return bl
|
||||
}
|
||||
@ -232,11 +236,26 @@ func (bl *BeeLogger) EnableFuncCallDepth(b bool) {
|
||||
// start logger chan reading.
|
||||
// when chan is not empty, write logs.
|
||||
func (bl *BeeLogger) startLogger() {
|
||||
gameOver := false
|
||||
for {
|
||||
select {
|
||||
case bm := <-bl.msgChan:
|
||||
bl.writeToLoggers(bm.when, bm.msg, bm.level)
|
||||
logMsgPool.Put(bm)
|
||||
case sg := <-bl.signalChan:
|
||||
// Now should only send "flush" or "close" to bl.signalChan
|
||||
bl.flush()
|
||||
if sg == "close" {
|
||||
for _, l := range bl.outputs {
|
||||
l.Destroy()
|
||||
}
|
||||
bl.outputs = nil
|
||||
gameOver = true
|
||||
}
|
||||
bl.wg.Done()
|
||||
}
|
||||
if gameOver {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -345,13 +364,41 @@ func (bl *BeeLogger) Trace(format string, v ...interface{}) {
|
||||
|
||||
// Flush flush all chan data.
|
||||
func (bl *BeeLogger) Flush() {
|
||||
for _, l := range bl.outputs {
|
||||
l.Flush()
|
||||
if bl.asynchronous {
|
||||
bl.signalChan <- "flush"
|
||||
bl.wg.Wait()
|
||||
bl.wg.Add(1)
|
||||
return
|
||||
}
|
||||
bl.flush()
|
||||
}
|
||||
|
||||
// Close close logger, flush all chan data and destroy all adapters in BeeLogger.
|
||||
func (bl *BeeLogger) Close() {
|
||||
if bl.asynchronous {
|
||||
bl.signalChan <- "close"
|
||||
bl.wg.Wait()
|
||||
} else {
|
||||
bl.flush()
|
||||
for _, l := range bl.outputs {
|
||||
l.Destroy()
|
||||
}
|
||||
bl.outputs = nil
|
||||
}
|
||||
close(bl.msgChan)
|
||||
close(bl.signalChan)
|
||||
}
|
||||
|
||||
// Reset close all outputs, and set bl.outputs to nil
|
||||
func (bl *BeeLogger) Reset() {
|
||||
bl.Flush()
|
||||
for _, l := range bl.outputs {
|
||||
l.Destroy()
|
||||
}
|
||||
bl.outputs = nil
|
||||
}
|
||||
|
||||
func (bl *BeeLogger) flush() {
|
||||
for {
|
||||
if len(bl.msgChan) > 0 {
|
||||
bm := <-bl.msgChan
|
||||
@ -363,7 +410,5 @@ func (bl *BeeLogger) Close() {
|
||||
}
|
||||
for _, l := range bl.outputs {
|
||||
l.Flush()
|
||||
l.Destroy()
|
||||
}
|
||||
bl.outputs = nil
|
||||
}
|
||||
|
98
template.go
98
template.go
@ -23,6 +23,7 @@ import (
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/astaxie/beego/utils"
|
||||
)
|
||||
@ -30,7 +31,8 @@ import (
|
||||
var (
|
||||
beegoTplFuncMap = make(template.FuncMap)
|
||||
// BeeTemplates caching map and supported template file extensions.
|
||||
BeeTemplates = make(map[string]*template.Template)
|
||||
BeeTemplates = make(map[string]*template.Template)
|
||||
templatesLock sync.Mutex
|
||||
// BeeTemplateExt stores the template extension which will build
|
||||
BeeTemplateExt = []string{"tpl", "html"}
|
||||
)
|
||||
@ -66,17 +68,21 @@ func init() {
|
||||
}
|
||||
|
||||
// AddFuncMap let user to register a func in the template.
|
||||
func AddFuncMap(key string, funname interface{}) error {
|
||||
beegoTplFuncMap[key] = funname
|
||||
func AddFuncMap(key string, fn interface{}) error {
|
||||
beegoTplFuncMap[key] = fn
|
||||
return nil
|
||||
}
|
||||
|
||||
type templatefile struct {
|
||||
type templateFile struct {
|
||||
root string
|
||||
files map[string][]string
|
||||
}
|
||||
|
||||
func (tf *templatefile) visit(paths string, f os.FileInfo, err error) error {
|
||||
// visit will make the paths into two part,the first is subDir (without tf.root),the second is full path(without tf.root).
|
||||
// if tf.root="views" and
|
||||
// paths is "views/errors/404.html",the subDir will be "errors",the file will be "errors/404.html"
|
||||
// paths is "views/admin/errors/404.html",the subDir will be "admin/errors",the file will be "admin/errors/404.html"
|
||||
func (tf *templateFile) visit(paths string, f os.FileInfo, err error) error {
|
||||
if f == nil {
|
||||
return err
|
||||
}
|
||||
@ -88,18 +94,10 @@ func (tf *templatefile) visit(paths string, f os.FileInfo, err error) error {
|
||||
}
|
||||
|
||||
replace := strings.NewReplacer("\\", "/")
|
||||
a := []byte(paths)
|
||||
a = a[len([]byte(tf.root)):]
|
||||
file := strings.TrimLeft(replace.Replace(string(a)), "/")
|
||||
subdir := filepath.Dir(file)
|
||||
if _, ok := tf.files[subdir]; ok {
|
||||
tf.files[subdir] = append(tf.files[subdir], file)
|
||||
} else {
|
||||
m := make([]string, 1)
|
||||
m[0] = file
|
||||
tf.files[subdir] = m
|
||||
}
|
||||
file := strings.TrimLeft(replace.Replace(paths[len(tf.root):]), "/")
|
||||
subDir := filepath.Dir(file)
|
||||
|
||||
tf.files[subDir] = append(tf.files[subDir], file)
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -132,7 +130,7 @@ func BuildTemplate(dir string, files ...string) error {
|
||||
}
|
||||
return errors.New("dir open err")
|
||||
}
|
||||
self := &templatefile{
|
||||
self := &templateFile{
|
||||
root: dir,
|
||||
files: make(map[string][]string),
|
||||
}
|
||||
@ -146,12 +144,14 @@ func BuildTemplate(dir string, files ...string) error {
|
||||
for _, v := range self.files {
|
||||
for _, file := range v {
|
||||
if len(files) == 0 || utils.InSlice(file, files) {
|
||||
templatesLock.Lock()
|
||||
t, err := getTemplate(self.root, file, v...)
|
||||
if err != nil {
|
||||
Trace("parse template err:", file, err)
|
||||
} else {
|
||||
BeeTemplates[file] = t
|
||||
}
|
||||
templatesLock.Unlock()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -159,16 +159,16 @@ func BuildTemplate(dir string, files ...string) error {
|
||||
}
|
||||
|
||||
func getTplDeep(root, file, parent string, t *template.Template) (*template.Template, [][]string, error) {
|
||||
var fileabspath string
|
||||
var fileAbsPath string
|
||||
if filepath.HasPrefix(file, "../") {
|
||||
fileabspath = filepath.Join(root, filepath.Dir(parent), file)
|
||||
fileAbsPath = filepath.Join(root, filepath.Dir(parent), file)
|
||||
} else {
|
||||
fileabspath = filepath.Join(root, file)
|
||||
fileAbsPath = filepath.Join(root, file)
|
||||
}
|
||||
if e := utils.FileExists(fileabspath); !e {
|
||||
if e := utils.FileExists(fileAbsPath); !e {
|
||||
panic("can't find template file:" + file)
|
||||
}
|
||||
data, err := ioutil.ReadFile(fileabspath)
|
||||
data, err := ioutil.ReadFile(fileAbsPath)
|
||||
if err != nil {
|
||||
return nil, [][]string{}, err
|
||||
}
|
||||
@ -177,11 +177,11 @@ func getTplDeep(root, file, parent string, t *template.Template) (*template.Temp
|
||||
return nil, [][]string{}, err
|
||||
}
|
||||
reg := regexp.MustCompile(BConfig.WebConfig.TemplateLeft + "[ ]*template[ ]+\"([^\"]+)\"")
|
||||
allsub := reg.FindAllStringSubmatch(string(data), -1)
|
||||
for _, m := range allsub {
|
||||
allSub := reg.FindAllStringSubmatch(string(data), -1)
|
||||
for _, m := range allSub {
|
||||
if len(m) == 2 {
|
||||
tlook := t.Lookup(m[1])
|
||||
if tlook != nil {
|
||||
tl := t.Lookup(m[1])
|
||||
if tl != nil {
|
||||
continue
|
||||
}
|
||||
if !HasTemplateExt(m[1]) {
|
||||
@ -193,17 +193,17 @@ func getTplDeep(root, file, parent string, t *template.Template) (*template.Temp
|
||||
}
|
||||
}
|
||||
}
|
||||
return t, allsub, nil
|
||||
return t, allSub, nil
|
||||
}
|
||||
|
||||
func getTemplate(root, file string, others ...string) (t *template.Template, err error) {
|
||||
t = template.New(file).Delims(BConfig.WebConfig.TemplateLeft, BConfig.WebConfig.TemplateRight).Funcs(beegoTplFuncMap)
|
||||
var submods [][]string
|
||||
t, submods, err = getTplDeep(root, file, "", t)
|
||||
var subMods [][]string
|
||||
t, subMods, err = getTplDeep(root, file, "", t)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
t, err = _getTemplate(t, root, submods, others...)
|
||||
t, err = _getTemplate(t, root, subMods, others...)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -211,44 +211,44 @@ func getTemplate(root, file string, others ...string) (t *template.Template, err
|
||||
return
|
||||
}
|
||||
|
||||
func _getTemplate(t0 *template.Template, root string, submods [][]string, others ...string) (t *template.Template, err error) {
|
||||
func _getTemplate(t0 *template.Template, root string, subMods [][]string, others ...string) (t *template.Template, err error) {
|
||||
t = t0
|
||||
for _, m := range submods {
|
||||
for _, m := range subMods {
|
||||
if len(m) == 2 {
|
||||
templ := t.Lookup(m[1])
|
||||
if templ != nil {
|
||||
tpl := t.Lookup(m[1])
|
||||
if tpl != nil {
|
||||
continue
|
||||
}
|
||||
//first check filename
|
||||
for _, otherfile := range others {
|
||||
if otherfile == m[1] {
|
||||
var submods1 [][]string
|
||||
t, submods1, err = getTplDeep(root, otherfile, "", t)
|
||||
for _, otherFile := range others {
|
||||
if otherFile == m[1] {
|
||||
var subMods1 [][]string
|
||||
t, subMods1, err = getTplDeep(root, otherFile, "", t)
|
||||
if err != nil {
|
||||
Trace("template parse file err:", err)
|
||||
} else if submods1 != nil && len(submods1) > 0 {
|
||||
t, err = _getTemplate(t, root, submods1, others...)
|
||||
} else if subMods1 != nil && len(subMods1) > 0 {
|
||||
t, err = _getTemplate(t, root, subMods1, others...)
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
//second check define
|
||||
for _, otherfile := range others {
|
||||
fileabspath := filepath.Join(root, otherfile)
|
||||
data, err := ioutil.ReadFile(fileabspath)
|
||||
for _, otherFile := range others {
|
||||
fileAbsPath := filepath.Join(root, otherFile)
|
||||
data, err := ioutil.ReadFile(fileAbsPath)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
reg := regexp.MustCompile(BConfig.WebConfig.TemplateLeft + "[ ]*define[ ]+\"([^\"]+)\"")
|
||||
allsub := reg.FindAllStringSubmatch(string(data), -1)
|
||||
for _, sub := range allsub {
|
||||
allSub := reg.FindAllStringSubmatch(string(data), -1)
|
||||
for _, sub := range allSub {
|
||||
if len(sub) == 2 && sub[1] == m[1] {
|
||||
var submods1 [][]string
|
||||
t, submods1, err = getTplDeep(root, otherfile, "", t)
|
||||
var subMods1 [][]string
|
||||
t, subMods1, err = getTplDeep(root, otherFile, "", t)
|
||||
if err != nil {
|
||||
Trace("template parse file err:", err)
|
||||
} else if submods1 != nil && len(submods1) > 0 {
|
||||
t, err = _getTemplate(t, root, submods1, others...)
|
||||
} else if subMods1 != nil && len(subMods1) > 0 {
|
||||
t, err = _getTemplate(t, root, subMods1, others...)
|
||||
}
|
||||
break
|
||||
}
|
||||
|
9
tree.go
9
tree.go
@ -265,15 +265,14 @@ func (t *Tree) addseg(segments []string, route interface{}, wildcards []string,
|
||||
}
|
||||
t.wildcard.addseg(segments[1:], route, append(wildcards, params...), reg+regexpStr)
|
||||
} else {
|
||||
var ok bool
|
||||
var subTree *Tree
|
||||
for _, subTree = range t.fixrouters {
|
||||
if t.prefix == seg {
|
||||
ok = true
|
||||
for _, sub := range t.fixrouters {
|
||||
if sub.prefix == seg {
|
||||
subTree = sub
|
||||
break
|
||||
}
|
||||
}
|
||||
if !ok {
|
||||
if subTree == nil {
|
||||
subTree = NewTree()
|
||||
subTree.prefix = seg
|
||||
t.fixrouters = append(t.fixrouters, subTree)
|
||||
|
12
tree_test.go
12
tree_test.go
@ -221,6 +221,18 @@ func TestAddTree4(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// Test for issue #1595
|
||||
func TestAddTree5(t *testing.T) {
|
||||
tr := NewTree()
|
||||
tr.AddRouter("/v1/shop/:id", "shopdetail")
|
||||
tr.AddRouter("/v1/shop/", "shophome")
|
||||
ctx := context.NewContext()
|
||||
obj := tr.Match("/v1/shop/", ctx)
|
||||
if obj == nil || obj.(string) != "shophome" {
|
||||
t.Fatal("url /v1/shop/ need match router /v1/shop/ ")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSplitPath(t *testing.T) {
|
||||
a := splitPath("")
|
||||
if len(a) != 0 {
|
||||
|
Loading…
Reference in New Issue
Block a user