1
0
mirror of https://shylinux.com/x/ContextOS synced 2025-04-25 16:58:06 +08:00
2019-07-27 13:42:47 +08:00

193 lines
6.1 KiB
Go

package log
import (
"contexts/ctx"
"path"
"toolkit"
"fmt"
"os"
)
type LOG struct {
queue chan map[string]interface{}
file map[string]*os.File
*ctx.Context
}
func (log *LOG) Log(msg *ctx.Message, action string, str string, arg ...interface{}) {
if log.queue != nil {
log.queue <- map[string]interface{}{"action": action, "str": str, "arg": arg, "msg": msg}
}
}
func (log *LOG) Value(msg *ctx.Message, arg ...interface{}) []string {
args := append(kit.Trans(arg...))
if value, ok := kit.Chain(log.Configs["output"].Value, args).(map[string]interface{}); ok {
if kit.Right(value["source"]) && kit.Format(value["source"]) != msg.Source().Name {
return nil
}
if kit.Right(value["target"]) && kit.Format(value["target"]) != msg.Target().Name {
return nil
}
return kit.Trans(value["value"])
}
return nil
}
func (log *LOG) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server {
return &LOG{Context: c}
}
func (log *LOG) Begin(m *ctx.Message, arg ...string) ctx.Server {
return log
}
func (log *LOG) Start(m *ctx.Message, arg ...string) bool {
// 创建文件
log.file = map[string]*os.File{}
m.Assert(os.MkdirAll(m.Conf("logdir"), 0770))
m.Confm("output", "file", func(key string, value string) {
switch value {
case "":
case "stderr":
log.file[key] = os.Stderr
case "stdout":
log.file[key] = os.Stdout
default:
if f, e := os.Create(path.Join(m.Conf("logdir"), value)); m.Assert(e) {
log.file[key] = f
}
}
})
// 创建队列
log.queue = make(chan map[string]interface{}, m.Confi("logbuf"))
m.Cap("stream", m.Conf("output", []string{"bench", "value", "file"}))
for {
select {
case l := <-log.queue:
m.Capi("nlog", 1)
msg := l["msg"].(*ctx.Message)
args := kit.Trans(l["arg"].([]interface{})...)
loop:
for _, v := range []string{kit.Format(l["action"]), "bench"} {
for i := len(args); i >= 0; i-- {
value := log.Value(msg, append([]string{v}, args[:i]...))
if !kit.Right(value) {
continue
}
if value[0] == "debug" && !m.Options("log.debug") {
break loop
}
// 日志文件
file := os.Stderr
if f, ok := log.file[value[0]]; ok {
file = f
} else {
break loop
}
// 日志格式
font := m.Conf("output", []string{"font", kit.Select("", value, 1)})
meta := msg.Format(m.Confv("output", []string{"meta", kit.Select("short", value, 2)}).([]interface{})...)
// 输出日志
fmt.Fprintln(file, fmt.Sprintf("%d %s %s%s %s%s", m.Capi("nout", 1), meta, font,
kit.Format(l["action"]), fmt.Sprintf(kit.Format(l["str"]), l["arg"].([]interface{})...),
kit.Select("", "\033[0m", font != "")))
break loop
}
}
}
}
return true
}
func (log *LOG) Close(m *ctx.Message, arg ...string) bool {
return false
}
var Index = &ctx.Context{Name: "log", Help: "日志中心",
Caches: map[string]*ctx.Cache{
"nlog": &ctx.Cache{Name: "nlog", Value: "0", Help: "日志调用数量"},
"nout": &ctx.Cache{Name: "nout", Value: "0", Help: "日志输出数量"},
},
Configs: map[string]*ctx.Config{
"logbuf": &ctx.Config{Name: "logbuf", Value: "1024", Help: "日志队列长度"},
"logdir": &ctx.Config{Name: "logdir", Value: "var/log", Help: "日志目录"},
"output": &ctx.Config{Name: "output", Value: map[string]interface{}{
"file": map[string]interface{}{
"debug": "debug.log",
"bench": "bench.log",
"right": "right.log",
"error": "error.log",
},
"font": map[string]interface{}{
"red": "\033[31m",
"green": "\033[32m",
"yellow": "\033[33m",
},
"meta": map[string]interface{}{
"short": []interface{}{"time", "ship"},
"long": []interface{}{"time", "ship"},
},
"debug": map[string]interface{}{"value": []interface{}{"debug"}},
"search": map[string]interface{}{"value": []interface{}{"debug"}},
"call": map[string]interface{}{"value": []interface{}{"debug"}},
"back": map[string]interface{}{"value": []interface{}{"debug"}},
"send": map[string]interface{}{"value": []interface{}{"debug"}},
"recv": map[string]interface{}{"value": []interface{}{"debug"}},
"bench": map[string]interface{}{"value": []interface{}{"bench"}},
"begin": map[string]interface{}{"value": []interface{}{"bench", "red"}},
"start": map[string]interface{}{"value": []interface{}{"bench", "red"}},
"close": map[string]interface{}{"value": []interface{}{"bench", "red"}},
"stack": map[string]interface{}{"value": []interface{}{"bench", "yellow"}},
"warn": map[string]interface{}{"value": []interface{}{"bench", "yellow"}},
"right": map[string]interface{}{"value": []interface{}{"right"}},
"error": map[string]interface{}{"value": []interface{}{"error", "red"}},
"trace": map[string]interface{}{"value": []interface{}{"error", "red"}},
"cmd": map[string]interface{}{"value": []interface{}{"bench", "green"},
"lex": map[string]interface{}{"value": []interface{}{"debug", "green"}},
"yac": map[string]interface{}{"value": []interface{}{"debug", "green"}},
"cli": map[string]interface{}{
"cmd": map[string]interface{}{"value": []interface{}{"debug", "red"}},
},
"mdb": map[string]interface{}{
"note": map[string]interface{}{"value": []interface{}{"debug", "red"}},
},
"aaa": map[string]interface{}{
"auth": map[string]interface{}{"value": []interface{}{"debug", "red"}},
"hash": map[string]interface{}{"value": []interface{}{"debug", "red"}},
"rsa": map[string]interface{}{"value": []interface{}{"debug", "red"}},
},
},
}, Help: "日志输出配置"},
},
Commands: map[string]*ctx.Command{
"_init": &ctx.Command{Name: "_init", Help: "初始化", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
m.Target().Start(m)
return
}},
"log": &ctx.Command{Name: "log level string...", Help: "输出日志, level: 日志类型, string: 日志内容", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
if log, ok := m.Target().Server.(*LOG); m.Assert(ok) {
log.Log(m, arg[0], arg[1], arg[2:])
}
return
}},
},
}
func init() {
ctx.Index.Register(Index, &LOG{Context: Index})
}