forked from x/icebergs
add traceid
This commit is contained in:
parent
b3024262ca
commit
5759eb31db
@ -3,7 +3,9 @@ package log
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
ice "shylinux.com/x/icebergs"
|
||||
"shylinux.com/x/icebergs/base/lex"
|
||||
@ -103,3 +105,22 @@ var Index = &ice.Context{Name: LOG, Help: "日志模块", Configs: ice.Configs{
|
||||
}}
|
||||
|
||||
func init() { ice.Index.Register(Index, &Frame{}, TAIL) }
|
||||
|
||||
const (
|
||||
LOG_TRACE = "log_trace"
|
||||
)
|
||||
|
||||
func Traceid() (traceid string) {
|
||||
ls := []string{}
|
||||
kit.For(kit.Split(os.Getenv(LOG_TRACE)), func(key string) {
|
||||
switch key {
|
||||
case "short":
|
||||
ls = append(ls, kit.Hashs(mdb.UNIQ)[:6])
|
||||
case "long":
|
||||
ls = append(ls, kit.Hashs(mdb.UNIQ))
|
||||
case "node":
|
||||
ls = append(ls, ice.Info.NodeName)
|
||||
}
|
||||
})
|
||||
return strings.Join(ls, "-")
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ func _hash_inputs(m *ice.Message, prefix, chain string, field, value string) {
|
||||
kit.For(list, func(k string, i int) { m.Push(field, k).Push(COUNT, i) })
|
||||
m.SortIntR(COUNT)
|
||||
}()
|
||||
defer RLock(m, prefix, chain)()
|
||||
defer RLock(m, prefix)()
|
||||
Richs(m, prefix, chain, FOREACH, func(key string, value Map) {
|
||||
value = kit.GetMeta(value)
|
||||
list[kit.Format(value[field])] += kit.Int(kit.Select("1", value[COUNT]))
|
||||
@ -31,7 +31,7 @@ func _hash_inputs(m *ice.Message, prefix, chain string, field, value string) {
|
||||
}
|
||||
func _hash_insert(m *ice.Message, prefix, chain string, arg ...string) string {
|
||||
m.Logs(INSERT, KEY, path.Join(prefix, chain), arg)
|
||||
defer Lock(m, prefix, chain)()
|
||||
defer Lock(m, prefix)()
|
||||
if expire := m.Conf(prefix, kit.Keys(chain, kit.Keym(EXPIRE))); expire != "" && arg[0] != HASH {
|
||||
arg = kit.Simple(TIME, m.Time(expire), arg)
|
||||
}
|
||||
@ -44,7 +44,7 @@ func _hash_insert(m *ice.Message, prefix, chain string, arg ...string) string {
|
||||
return m.Result()
|
||||
}
|
||||
func _hash_delete(m *ice.Message, prefix, chain, field, value string) {
|
||||
defer Lock(m, prefix, chain)()
|
||||
defer Lock(m, prefix)()
|
||||
Richs(m, prefix, chain, value, func(key string, val Map) {
|
||||
if target, ok := kit.GetMeta(val)[TARGET].(io.Closer); ok {
|
||||
target.Close()
|
||||
@ -56,7 +56,7 @@ func _hash_delete(m *ice.Message, prefix, chain, field, value string) {
|
||||
}
|
||||
func _hash_modify(m *ice.Message, prefix, chain string, field, value string, arg ...string) {
|
||||
m.Logs(MODIFY, KEY, path.Join(prefix, chain), field, value, arg)
|
||||
defer Lock(m, prefix, chain)()
|
||||
defer Lock(m, prefix)()
|
||||
Richs(m, prefix, chain, value, func(key string, val Map) {
|
||||
saveImportant(m, prefix, chain, kit.Simple(MODIFY, prefix, chain, HASH, HASH, key, arg)...)
|
||||
_mdb_modify(m, val, field, arg...)
|
||||
@ -66,18 +66,18 @@ func _hash_select(m *ice.Message, prefix, chain, field, value string) {
|
||||
kit.If(field == HASH && value == RANDOM, func() { value = RANDOMS })
|
||||
defer m.SortStrR(TIME)
|
||||
fields := _hash_fields(m)
|
||||
defer RLock(m, prefix, chain)()
|
||||
defer RLock(m, prefix)()
|
||||
Richs(m, prefix, chain, value, func(key string, value Map) { _mdb_select(m, m.OptionCB(""), key, value, fields, nil) })
|
||||
}
|
||||
func _hash_select_field(m *ice.Message, prefix, chain string, key string, field string) (value string) {
|
||||
defer RLock(m, prefix, chain)()
|
||||
defer RLock(m, prefix)()
|
||||
Richs(m, prefix, chain, key, func(key string, val Map) { value = kit.Select(kit.Format(val[field]), key, field == HASH) })
|
||||
return
|
||||
}
|
||||
func _hash_prunes(m *ice.Message, prefix, chain string, arg ...string) {
|
||||
fields := _hash_fields(m)
|
||||
kit.If(kit.IndexOf(fields, HASH) == -1, func() { fields = append(fields, HASH) })
|
||||
defer RLock(m, prefix, chain)()
|
||||
defer RLock(m, prefix)()
|
||||
Richs(m, prefix, chain, FOREACH, func(key string, value Map) {
|
||||
switch value = kit.GetMeta(value); cb := m.OptionCB("").(type) {
|
||||
case func(string, Map) bool:
|
||||
@ -90,7 +90,7 @@ func _hash_prunes(m *ice.Message, prefix, chain string, arg ...string) {
|
||||
})
|
||||
}
|
||||
func _hash_export(m *ice.Message, prefix, chain, file string) {
|
||||
defer Lock(m, prefix, chain)()
|
||||
defer Lock(m, prefix)()
|
||||
count := len(Confm(m, prefix, kit.Keys(chain, HASH)))
|
||||
p := kit.Keys(file, JSON)
|
||||
if count == 0 {
|
||||
@ -110,7 +110,7 @@ func _hash_export(m *ice.Message, prefix, chain, file string) {
|
||||
}
|
||||
}
|
||||
func _hash_import(m *ice.Message, prefix, chain, file string) {
|
||||
defer Lock(m, prefix, chain)()
|
||||
defer Lock(m, prefix)()
|
||||
f, e := ice.Info.Open(m, kit.Keys(file, JSON))
|
||||
if os.IsNotExist(e) {
|
||||
return
|
||||
|
@ -20,7 +20,7 @@ func _list_inputs(m *ice.Message, prefix, chain string, field, value string) {
|
||||
kit.For(list, func(k string, i int) { m.Push(field, k).Push(COUNT, i) })
|
||||
m.SortIntR(COUNT)
|
||||
}()
|
||||
defer RLock(m, prefix, chain)()
|
||||
defer RLock(m, prefix)()
|
||||
Grows(m, prefix, chain, "", "", func(value ice.Map) {
|
||||
value = kit.GetMeta(value)
|
||||
list[kit.Format(value[field])] += kit.Int(kit.Select("1", value[COUNT]))
|
||||
@ -28,26 +28,26 @@ func _list_inputs(m *ice.Message, prefix, chain string, field, value string) {
|
||||
}
|
||||
func _list_insert(m *ice.Message, prefix, chain string, arg ...string) {
|
||||
m.Logs(INSERT, KEY, path.Join(prefix, chain), arg)
|
||||
defer Lock(m, prefix, chain)()
|
||||
defer Lock(m, prefix)()
|
||||
saveImportant(m, prefix, chain, kit.Simple(INSERT, prefix, chain, LIST, TIME, m.Time(), arg)...)
|
||||
m.Echo("%d", Grow(m, prefix, chain, kit.Dict(arg, TARGET, m.Optionv(TARGET))))
|
||||
}
|
||||
func _list_modify(m *ice.Message, prefix, chain string, field, value string, arg ...string) {
|
||||
m.Logs(MODIFY, KEY, path.Join(prefix, chain), field, value, arg)
|
||||
defer Lock(m, prefix, chain)()
|
||||
defer Lock(m, prefix)()
|
||||
saveImportant(m, prefix, chain, kit.Simple(MODIFY, prefix, chain, LIST, field, value, arg)...)
|
||||
Grows(m, prefix, chain, field, value, func(index int, val ice.Map) { _mdb_modify(m, val, field, arg...) })
|
||||
}
|
||||
func _list_select(m *ice.Message, prefix, chain, field, value string) {
|
||||
defer m.SortIntR(ID)
|
||||
fields := _list_fields(m)
|
||||
defer RLock(m, prefix, chain)()
|
||||
defer RLock(m, prefix)()
|
||||
Grows(m, prefix, chain, kit.Select(m.Option(CACHE_FIELD), field), kit.Select(m.Option(CACHE_VALUE), value), func(value ice.Map) {
|
||||
_mdb_select(m, m.OptionCB(""), "", value, fields, nil)
|
||||
})
|
||||
}
|
||||
func _list_export(m *ice.Message, prefix, chain, file string) {
|
||||
defer Lock(m, prefix, chain)()
|
||||
defer Lock(m, prefix)()
|
||||
f, p, e := miss.CreateFile(kit.Keys(file, CSV))
|
||||
m.Assert(e)
|
||||
defer f.Close()
|
||||
@ -68,7 +68,7 @@ func _list_export(m *ice.Message, prefix, chain, file string) {
|
||||
m.Conf(prefix, kit.Keys(chain, LIST), "")
|
||||
}
|
||||
func _list_import(m *ice.Message, prefix, chain, file string) {
|
||||
defer Lock(m, prefix, chain)()
|
||||
defer Lock(m, prefix)()
|
||||
f, e := miss.OpenFile(kit.Keys(file, CSV))
|
||||
m.Assert(e)
|
||||
defer f.Close()
|
||||
|
@ -13,7 +13,7 @@ import (
|
||||
)
|
||||
|
||||
func _zone_meta(m *ice.Message, prefix, chain, key string) string {
|
||||
defer RLock(m, prefix, chain)()
|
||||
defer RLock(m, prefix)()
|
||||
return m.Conf(prefix, kit.Keys(chain, kit.Keym(key)))
|
||||
}
|
||||
func _zone_fields(m *ice.Message) []string {
|
||||
@ -25,7 +25,6 @@ func _zone_inputs(m *ice.Message, prefix, chain, zone string, field, value strin
|
||||
return
|
||||
}
|
||||
h := _hash_select_field(m, prefix, chain, zone, HASH)
|
||||
defer RLock(m, prefix, chain)()
|
||||
_list_inputs(m, prefix, kit.Keys(chain, HASH, h), field, value)
|
||||
}
|
||||
func _zone_insert(m *ice.Message, prefix, chain, zone string, arg ...string) {
|
||||
@ -34,13 +33,11 @@ func _zone_insert(m *ice.Message, prefix, chain, zone string, arg ...string) {
|
||||
h = _hash_insert(m, prefix, chain, kit.Select(ZONE, _zone_meta(m, prefix, chain, SHORT)), zone)
|
||||
}
|
||||
m.Assert(h != "")
|
||||
defer Lock(m, prefix, chain)()
|
||||
_list_insert(m, prefix, kit.Keys(chain, HASH, h), arg...)
|
||||
}
|
||||
func _zone_modify(m *ice.Message, prefix, chain, zone, id string, arg ...string) {
|
||||
h := _hash_select_field(m, prefix, chain, zone, HASH)
|
||||
m.Assert(h != "")
|
||||
defer Lock(m, prefix, chain)()
|
||||
_list_modify(m, prefix, kit.Keys(chain, HASH, h), ID, id, arg...)
|
||||
}
|
||||
func _zone_select(m *ice.Message, prefix, chain, zone string, id string) {
|
||||
@ -52,17 +49,16 @@ func _zone_select(m *ice.Message, prefix, chain, zone string, id string) {
|
||||
}
|
||||
defer m.SortIntR(ID)
|
||||
fields := _zone_fields(m)
|
||||
defer RLock(m, prefix, chain)()
|
||||
defer RLock(m, prefix)()
|
||||
Richs(m, prefix, chain, kit.Select(FOREACH, zone), func(key string, val Map) {
|
||||
chain := kit.Keys(chain, HASH, key)
|
||||
defer RLock(m, prefix, chain)()
|
||||
Grows(m, prefix, chain, ID, id, func(value ice.Map) {
|
||||
_mdb_select(m, m.OptionCB(""), key, value, fields, val)
|
||||
})
|
||||
})
|
||||
}
|
||||
func _zone_export(m *ice.Message, prefix, chain, file string) {
|
||||
defer Lock(m, prefix, chain)()
|
||||
defer Lock(m, prefix)()
|
||||
f, p, e := miss.CreateFile(kit.Keys(file, CSV))
|
||||
m.Assert(e)
|
||||
defer f.Close()
|
||||
@ -76,7 +72,6 @@ func _zone_export(m *ice.Message, prefix, chain, file string) {
|
||||
Richs(m, prefix, chain, key, func(key string, val ice.Map) {
|
||||
val = kit.GetMeta(val)
|
||||
chain := kit.Keys(chain, HASH, key)
|
||||
defer Lock(m, prefix, chain)()
|
||||
Grows(m, prefix, chain, "", "", func(value ice.Map) {
|
||||
value = kit.GetMeta(value)
|
||||
w.Write(kit.Simple(head, func(k string) string {
|
||||
@ -94,7 +89,7 @@ func _zone_export(m *ice.Message, prefix, chain, file string) {
|
||||
m.Conf(prefix, kit.Keys(chain, HASH), "")
|
||||
}
|
||||
func _zone_import(m *ice.Message, prefix, chain, file string) {
|
||||
defer Lock(m, prefix, chain)()
|
||||
defer Lock(m, prefix)()
|
||||
f, e := ice.Info.Open(m, kit.Keys(file, CSV))
|
||||
if os.IsNotExist(e) {
|
||||
return
|
||||
@ -133,7 +128,6 @@ func _zone_import(m *ice.Message, prefix, chain, file string) {
|
||||
}
|
||||
func() {
|
||||
chain := kit.Keys(chain, HASH, list[zone])
|
||||
defer Lock(m, prefix, chain)()
|
||||
Grow(m, prefix, chain, data)
|
||||
}()
|
||||
count++
|
||||
|
@ -120,7 +120,10 @@ func init() {
|
||||
)),
|
||||
}, DIR), Hand: func(m *ice.Message, arg ...string) {
|
||||
if !DirList(m, arg...) {
|
||||
_cat_list(m.Logs(FIND, m.OptionSimple(DIR_ROOT), FILE, arg[0]), arg[0])
|
||||
if arg[0] != "" {
|
||||
m.Logs(FIND, m.OptionSimple(DIR_ROOT), FILE, arg[0])
|
||||
}
|
||||
_cat_list(m, arg[0])
|
||||
}
|
||||
}},
|
||||
})
|
||||
|
@ -200,8 +200,9 @@ func init() {
|
||||
}
|
||||
m.Logs(FIND, DIR_ROOT, root, PATH, dir, m.OptionSimple(DIR_TYPE, DIR_REG))
|
||||
fields := kit.Split(kit.Select(kit.Select(DIR_DEF_FIELDS, m.OptionFields()), kit.Join(kit.Slice(arg, 1))))
|
||||
size, last := _dir_list(m, root, dir, 0, m.Option(DIR_DEEP) == ice.TRUE, kit.Select(TYPE_BOTH, m.Option(DIR_TYPE)), regexp.MustCompile(m.Option(DIR_REG)), fields)
|
||||
m.Status(mdb.TIME, last, mdb.COUNT, kit.Split(m.FormatSize())[0], SIZE, kit.FmtSize(size), m.OptionSimple(DIR_ROOT), kit.MDB_COST, m.FormatCost())
|
||||
size, _ := _dir_list(m, root, dir, 0, m.Option(DIR_DEEP) == ice.TRUE, kit.Select(TYPE_BOTH, m.Option(DIR_TYPE)), regexp.MustCompile(m.Option(DIR_REG)), fields)
|
||||
// m.Status(mdb.TIME, last, mdb.COUNT, kit.Split(m.FormatSize())[0], SIZE, kit.FmtSize(size), m.OptionSimple(DIR_ROOT), kit.MDB_COST, m.FormatCost())
|
||||
m.StatusTimeCount(SIZE, kit.FmtSize(size), m.OptionSimple(DIR_ROOT))
|
||||
}},
|
||||
})
|
||||
}
|
||||
|
@ -32,10 +32,12 @@ func Render(m *ice.Message, cmd string, args ...ice.Any) bool {
|
||||
arg := kit.Simple(args...)
|
||||
kit.If(len(arg) == 0, func() { args = nil })
|
||||
if cmd != "" {
|
||||
if cmd != ice.RENDER_DOWNLOAD || !kit.HasPrefix(arg[0], ice.USR_VOLCANOS, ice.USR_INTSHELL, ice.SRC_TEMPLATE, ice.USR_ICONS, "usr/node_modules/") {
|
||||
if cmd != ice.RENDER_DOWNLOAD || !kit.HasPrefix(arg[0], ice.SRC_TEMPLATE, ice.USR_INTSHELL, ice.USR_VOLCANOS, ice.USR_ICONS, ice.USR_MODULES) {
|
||||
if !(cmd == ice.RENDER_RESULT && len(args) == 0) {
|
||||
defer func() { m.Logs("Render", cmd, args) }()
|
||||
}
|
||||
}
|
||||
}
|
||||
switch cmd {
|
||||
case COOKIE: // value [name [path [expire]]]
|
||||
RenderCookie(m, arg[0], arg[1:]...)
|
||||
|
@ -12,11 +12,13 @@ import (
|
||||
"shylinux.com/x/icebergs/base/cli"
|
||||
"shylinux.com/x/icebergs/base/ctx"
|
||||
"shylinux.com/x/icebergs/base/lex"
|
||||
"shylinux.com/x/icebergs/base/log"
|
||||
"shylinux.com/x/icebergs/base/mdb"
|
||||
"shylinux.com/x/icebergs/base/nfs"
|
||||
"shylinux.com/x/icebergs/base/ssh"
|
||||
"shylinux.com/x/icebergs/base/tcp"
|
||||
kit "shylinux.com/x/toolkits"
|
||||
"shylinux.com/x/toolkits/logs"
|
||||
)
|
||||
|
||||
func _serve_address(m *ice.Message) string { return Domain(tcp.LOCALHOST, m.Option(tcp.PORT)) }
|
||||
@ -53,7 +55,9 @@ func _serve_main(m *ice.Message, w http.ResponseWriter, r *http.Request) bool {
|
||||
} else {
|
||||
r.Header.Set(ice.MSG_USERIP, strings.Split(r.RemoteAddr, nfs.DF)[0])
|
||||
}
|
||||
if m.Logs(r.Header.Get(ice.MSG_USERIP), r.Method, r.URL.String()); r.Method == http.MethodGet {
|
||||
traceid := log.Traceid()
|
||||
r.Header.Set(ice.LOG_TRACEID, traceid)
|
||||
if m.Logs(r.Header.Get(ice.MSG_USERIP), r.Method, r.URL.String(), logs.TraceidMeta(traceid)); r.Method == http.MethodGet {
|
||||
ispod := kit.Contains(r.URL.String(), CHAT_POD, "pod=") || kit.Contains(r.Header.Get(Referer), CHAT_POD, "pod=")
|
||||
if msg := m.Spawn(w, r).Options(ice.MSG_USERUA, r.UserAgent()); path.Join(r.URL.Path) == nfs.PS {
|
||||
if !msg.IsCliUA() {
|
||||
@ -80,6 +84,7 @@ func _serve_main(m *ice.Message, w http.ResponseWriter, r *http.Request) bool {
|
||||
}
|
||||
func _serve_handle(key string, cmd *ice.Command, m *ice.Message, w http.ResponseWriter, r *http.Request) {
|
||||
debug := strings.Contains(r.URL.String(), "debug=true") || strings.Contains(r.Header.Get(Referer), "debug=true")
|
||||
m.Option(ice.LOG_TRACEID, r.Header.Get(ice.LOG_TRACEID))
|
||||
_log := func(level string, arg ...ice.Any) *ice.Message {
|
||||
if debug || arg[0] == ice.MSG_CMDS {
|
||||
return m.Logs(strings.Title(level), arg...)
|
||||
@ -115,10 +120,11 @@ func _serve_handle(key string, cmd *ice.Command, m *ice.Message, w http.Response
|
||||
kit.If(m.Optionv(ice.MSG_CMDS) == nil, func() {
|
||||
kit.If(strings.TrimPrefix(r.URL.Path, key), func(p string) { m.Optionv(ice.MSG_CMDS, strings.Split(p, nfs.PS)) })
|
||||
})
|
||||
m.W.Header().Add(strings.ReplaceAll(ice.LOG_TRACEID, ".", "-"), m.Option(ice.LOG_TRACEID))
|
||||
defer func() { Render(m, m.Option(ice.MSG_OUTPUT), kit.List(m.Optionv(ice.MSG_ARGS))...) }()
|
||||
if cmds, ok := _serve_auth(m, key, kit.Simple(m.Optionv(ice.MSG_CMDS)), w, r); ok {
|
||||
defer func() {
|
||||
m.Cost(kit.Format("%s: /chat/cmd/%s/%s %v %s", r.Method, m.Option(ice.MSG_INDEX), path.Join(cmds...), m.FormatSize(), kit.FmtSize(len(m.Result()))))
|
||||
m.Cost(kit.Format("%s: /chat/cmd/%s/%s %v", r.Method, m.Option(ice.MSG_INDEX), path.Join(cmds...), m.FormatSize()))
|
||||
}()
|
||||
m.Option(ice.MSG_OPTS, kit.Simple(m.Optionv(ice.MSG_OPTION), func(k string) bool { return !strings.HasPrefix(k, ice.MSG_SESSID) }))
|
||||
if m.Detailv(m.PrefixKey(), cmds); len(cmds) > 1 && cmds[0] == ctx.ACTION {
|
||||
|
@ -89,6 +89,7 @@ func _space_handle(m *ice.Message, safe bool, name string, c *websocket.Conn) {
|
||||
break
|
||||
}
|
||||
msg := m.Spawn(b)
|
||||
// msg.Option(ice.LOG_TRACEID, kit.Split(msg.Option(ice.LOG_TRACEID), "-")[0]+"-"+ice.Info.NodeName)
|
||||
if safe { // 下行权限
|
||||
msg.OptionDefault(ice.MSG_USERROLE, aaa.UserRole(msg, msg.Option(ice.MSG_USERNAME)))
|
||||
} else { // 上行权限
|
||||
|
2
conf.go
2
conf.go
@ -177,6 +177,7 @@ const ( // DIR
|
||||
)
|
||||
const ( // MSG
|
||||
MSG_CMDS = "cmds"
|
||||
MSG_DEBUG = "debug"
|
||||
MSG_FIELDS = "fields"
|
||||
MSG_SESSID = "sessid"
|
||||
MSG_METHOD = "method"
|
||||
@ -224,6 +225,7 @@ const ( // MSG
|
||||
MSG_DAEMON = "sess.daemon"
|
||||
MSG_FILES = "file.system"
|
||||
LOG_DISABLE = "log.disable"
|
||||
LOG_TRACEID = "log.id"
|
||||
YAC_MESSAGE = "yac.message"
|
||||
YAC_STACK = "yac.stack"
|
||||
SSH_ALIAS = "ssh.alias"
|
||||
|
@ -41,7 +41,7 @@ func _bench_http(m *ice.Message, target string, arg ...string) {
|
||||
}
|
||||
})
|
||||
var ndata int64
|
||||
if s, e := bench.HTTP(nconn, nreqs, list, func(req *http.Request, res *http.Response) {
|
||||
if s, e := bench.HTTP(m.FormatTaskMeta(), nconn, nreqs, list, func(req *http.Request, res *http.Response) {
|
||||
n, _ := io.Copy(ioutil.Discard, res.Body)
|
||||
atomic.AddInt64(&ndata, n)
|
||||
}); m.Assert(e) {
|
||||
|
@ -41,7 +41,6 @@ func _xterm_get(m *ice.Message, h string) xterm.XTerm {
|
||||
for {
|
||||
if n, e := term.Read(buf); !m.Warn(e) && e == nil {
|
||||
if _xterm_echo(m, h, string(buf[:n])); len(text) > 0 {
|
||||
m.Debug("what %v", text[0])
|
||||
kit.If(text[0], func(cmd string) { m.Go(func() { m.Sleep30ms(); term.Writeln(cmd) }) })
|
||||
text = text[1:]
|
||||
}
|
||||
|
8
exec.go
8
exec.go
@ -62,7 +62,7 @@ func (m *Message) GoSleep(t string, arg ...Any) {
|
||||
}
|
||||
func (m *Message) Go(cb func(), arg ...Any) *Message {
|
||||
kit.If(len(arg) == 0, func() { arg = append(arg, logs.FileLine(cb)) })
|
||||
task.Put(arg[0], func(task *task.Task) { m.TryCatch(true, func(m *Message) { cb() }) })
|
||||
task.Put(m.FormatTaskMeta(), arg[0], func(task *task.Task) { m.TryCatch(true, func(m *Message) { cb() }) })
|
||||
return m
|
||||
}
|
||||
func (m *Message) Wait(d string, cb ...Handler) (wait func() bool, done Handler) {
|
||||
@ -82,7 +82,7 @@ func (m *Message) Cmdv(arg ...Any) string {
|
||||
return m._command(kit.Slice(args, 0, -1), OptionFields(field)).Append(field)
|
||||
}
|
||||
func (m *Message) Cmdx(arg ...Any) string {
|
||||
res := strings.TrimSpace(kit.Select("", m._command(arg...).meta[MSG_RESULT], 0))
|
||||
res := strings.TrimSpace(m._command(arg...).index(MSG_RESULT, 0))
|
||||
return kit.Select("", res, res != strings.TrimSpace(ErrWarn))
|
||||
}
|
||||
func (m *Message) Cmdy(arg ...Any) *Message { return m.Copy(m._command(arg...)) }
|
||||
@ -147,7 +147,7 @@ func (m *Message) _command(arg ...Any) *Message {
|
||||
panic(count)
|
||||
}
|
||||
list := kit.Simple(args...)
|
||||
kit.If(len(list) == 0, func() { list = m.meta[MSG_DETAIL] })
|
||||
kit.If(len(list) == 0, func() { list = m.value(MSG_DETAIL) })
|
||||
if len(list) == 0 {
|
||||
return m
|
||||
}
|
||||
@ -175,7 +175,7 @@ func (c *Context) _command(m *Message, cmd *Command, key string, arg ...string)
|
||||
if m._cmd, m._key = cmd, key; cmd == nil {
|
||||
return m
|
||||
}
|
||||
if m.meta[MSG_DETAIL] = kit.Simple(m.PrefixKey(), arg); cmd.Actions != nil {
|
||||
if m.value(MSG_DETAIL, kit.Simple(m.PrefixKey(), arg)...); cmd.Actions != nil {
|
||||
if len(arg) > 1 && arg[0] == ACTION {
|
||||
if h, ok := cmd.Actions[arg[1]]; ok {
|
||||
return c._action(m, cmd, key, arg[1], h, arg[2:]...)
|
||||
|
4
init.go
4
init.go
@ -77,7 +77,7 @@ var Index = &Context{Name: ICE, Help: "冰山模块", Commands: Commands{
|
||||
})
|
||||
}},
|
||||
}, server: &Frame{}}
|
||||
var Pulse = &Message{meta: map[string][]string{}, data: Map{}, source: Index, target: Index}
|
||||
var Pulse = &Message{_meta: map[string][]string{}, _data: Map{}, source: Index, target: Index}
|
||||
|
||||
func init() {
|
||||
switch tz := os.Getenv("TZ"); tz {
|
||||
@ -98,7 +98,7 @@ func Run(arg ...string) string {
|
||||
} else if arg[0] == FOREVER && arg[1] == START && runtime.GOOS == WINDOWS {
|
||||
arg[0] = SERVE
|
||||
}
|
||||
Pulse.meta[MSG_DETAIL] = arg
|
||||
Pulse.value(MSG_DETAIL, arg...)
|
||||
kit.For(kit.Sort(os.Environ()), func(env string) {
|
||||
if ls := strings.SplitN(env, EQ, 2); strings.ToLower(ls[0]) == ls[0] && ls[0] != "_" {
|
||||
Pulse.Option(ls[0], ls[1])
|
||||
|
107
lock.go
Normal file
107
lock.go
Normal file
@ -0,0 +1,107 @@
|
||||
package ice
|
||||
|
||||
import (
|
||||
kit "shylinux.com/x/toolkits"
|
||||
)
|
||||
|
||||
func (m *Message) index(key string, index int, value ...string) string {
|
||||
if len(value) > 0 {
|
||||
defer m.lock.Lock()()
|
||||
m._meta[key][index] = value[0]
|
||||
} else {
|
||||
defer m.lock.RLock()()
|
||||
}
|
||||
return kit.Select("", m._meta[key], index)
|
||||
}
|
||||
func (m *Message) value(key string, list ...string) []string {
|
||||
if len(list) > 0 {
|
||||
defer m.lock.Lock()()
|
||||
m._meta[key] = list
|
||||
} else {
|
||||
defer m.lock.RLock()()
|
||||
}
|
||||
return m._meta[key]
|
||||
}
|
||||
func (m *Message) delete(key ...string) {
|
||||
defer m.lock.Lock()()
|
||||
for _, key := range key {
|
||||
delete(m._meta, key)
|
||||
}
|
||||
}
|
||||
|
||||
func (m *Message) Add(key string, arg ...string) *Message {
|
||||
if len(arg) == 0 {
|
||||
return m
|
||||
}
|
||||
defer m.lock.Lock()()
|
||||
switch key {
|
||||
case MSG_DETAIL, MSG_RESULT:
|
||||
m._meta[key] = append(m._meta[key], arg...)
|
||||
case MSG_OPTION, MSG_APPEND:
|
||||
if index := 0; key == MSG_APPEND {
|
||||
if m._meta[MSG_OPTION], index = kit.SliceRemove(m._meta[MSG_OPTION], arg[0]); index > -1 {
|
||||
delete(m._meta, arg[0])
|
||||
}
|
||||
}
|
||||
if m._meta[arg[0]] = append(m._meta[arg[0]], arg[1:]...); kit.IndexOf(m._meta[key], arg[0]) == -1 {
|
||||
m._meta[key] = append(m._meta[key], arg[0])
|
||||
}
|
||||
}
|
||||
return m
|
||||
}
|
||||
func (m *Message) setDetail(key string, arg ...string) *Message {
|
||||
defer m.lock.Lock()()
|
||||
for i := 0; i < len(m._meta[KEY]); i++ {
|
||||
if m._meta[KEY][i] == key {
|
||||
if len(arg) > 0 {
|
||||
m._meta[VALUE][i] = arg[0]
|
||||
return m
|
||||
}
|
||||
for ; i < len(m._meta[KEY])-1; i++ {
|
||||
m._meta[KEY][i] = m._meta[KEY][i+1]
|
||||
m._meta[VALUE][i] = m._meta[VALUE][i+1]
|
||||
}
|
||||
m._meta[KEY] = kit.Slice(m._meta[KEY], 0, -1)
|
||||
m._meta[VALUE] = kit.Slice(m._meta[VALUE], 0, -1)
|
||||
return m
|
||||
}
|
||||
}
|
||||
if len(arg) > 0 {
|
||||
m._meta[KEY] = append(m._meta[KEY], key)
|
||||
m._meta[VALUE] = append(m._meta[VALUE], arg[0])
|
||||
}
|
||||
return m
|
||||
}
|
||||
func (m *Message) Optionv(key string, arg ...Any) Any {
|
||||
var unlock func()
|
||||
if len(arg) > 0 {
|
||||
unlock = m.lock.Lock()
|
||||
kit.If(kit.IndexOf(m._meta[MSG_OPTION], key) == -1, func() { m._meta[MSG_OPTION] = append(m._meta[MSG_OPTION], key) })
|
||||
switch delete(m._data, key); v := arg[0].(type) {
|
||||
case nil:
|
||||
delete(m._meta, key)
|
||||
case string:
|
||||
m._meta[key] = kit.Simple(arg...)
|
||||
case []string:
|
||||
m._meta[key] = v
|
||||
default:
|
||||
m._data[key] = v
|
||||
}
|
||||
} else {
|
||||
unlock = m.lock.RLock()
|
||||
}
|
||||
if v, ok := m._data[key]; ok {
|
||||
unlock()
|
||||
return v
|
||||
} else if v, ok := m._meta[key]; ok {
|
||||
unlock()
|
||||
return v
|
||||
} else {
|
||||
unlock()
|
||||
}
|
||||
if m.message != nil {
|
||||
return m.message.Optionv(key)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
65
logs.go
65
logs.go
@ -14,6 +14,7 @@ import (
|
||||
|
||||
kit "shylinux.com/x/toolkits"
|
||||
"shylinux.com/x/toolkits/logs"
|
||||
"shylinux.com/x/toolkits/task"
|
||||
)
|
||||
|
||||
func (m *Message) join(arg ...Any) (string, []Any) {
|
||||
@ -52,8 +53,20 @@ func (m *Message) log(level string, str string, arg ...Any) *Message {
|
||||
if m.Option(LOG_DISABLE) == TRUE {
|
||||
return m
|
||||
}
|
||||
arg = append(arg, logs.TraceidMeta(m.Option(LOG_TRACEID)))
|
||||
args, traceid := []Any{}, ""
|
||||
for _, v := range arg {
|
||||
switch v := v.(type) {
|
||||
case logs.Meta:
|
||||
if v.Key == logs.TRACEID {
|
||||
traceid = kit.Select(strings.TrimSpace(v.Value), traceid)
|
||||
continue
|
||||
}
|
||||
}
|
||||
args = append(args, v)
|
||||
}
|
||||
_source := logs.FileLineMeta(3)
|
||||
kit.If(Info.Log != nil, func() { Info.Log(m, m.FormatPrefix(), level, logs.Format(str, append(arg, _source)...)) })
|
||||
kit.If(Info.Log != nil, func() { Info.Log(m, m.FormatPrefix(traceid), level, logs.Format(str, append(args, _source)...)) })
|
||||
prefix, suffix := "", ""
|
||||
if Info.Colors {
|
||||
switch level {
|
||||
@ -65,7 +78,8 @@ func (m *Message) log(level string, str string, arg ...Any) *Message {
|
||||
prefix, suffix = "\033[31m", "\033[0m"
|
||||
}
|
||||
}
|
||||
logs.Infof(str, append(arg, logs.PrefixMeta(kit.Format("%02d %4s->%-4s %s%s ", m.code, m.source.Name, m.target.Name, prefix, level)), logs.SuffixMeta(suffix), _source)...)
|
||||
kit.If(traceid, func() { traceid = kit.Format("%s: %s ", logs.TRACEID, traceid) })
|
||||
logs.Infof(str, append(args, logs.PrefixMeta(kit.Format("%s%02d %4s->%-4s %s%s ", traceid, m.code, m.source.Name, m.target.Name, prefix, level)), logs.SuffixMeta(suffix), _source)...)
|
||||
return m
|
||||
}
|
||||
func (m *Message) Log(level string, str string, arg ...Any) *Message {
|
||||
@ -83,7 +97,7 @@ func (m *Message) Auth(arg ...Any) *Message {
|
||||
}
|
||||
func (m *Message) Cost(arg ...Any) *Message {
|
||||
str, meta := m.join(arg...)
|
||||
kit.If(str == "" || len(arg) == 0, func() { str, meta = kit.Join(m.meta[MSG_DETAIL], SP), []Any{logs.FileLineMeta(m._fileline())} })
|
||||
kit.If(str == "" || len(arg) == 0, func() { str, meta = kit.Join(m.value(MSG_DETAIL), SP), []Any{logs.FileLineMeta(m._fileline())} })
|
||||
return m.log(LOG_COST, kit.Join([]string{m.FormatCost(), str}, SP), meta...)
|
||||
}
|
||||
func (m *Message) Info(str string, arg ...Any) *Message {
|
||||
@ -145,7 +159,7 @@ func (m *Message) error(arg ...Any) {
|
||||
}
|
||||
func (m *Message) IsOk() bool { return m.Result() == OK }
|
||||
func (m *Message) IsErr(arg ...string) bool {
|
||||
return len(arg) == 0 && kit.Select("", m.meta[MSG_RESULT], 0) == ErrWarn || len(arg) > 0 && kit.Select("", m.meta[MSG_RESULT], 1) == arg[0]
|
||||
return len(arg) == 0 && m.index(MSG_RESULT, 0) == ErrWarn || len(arg) > 0 && m.index(MSG_RESULT, 1) == arg[0]
|
||||
}
|
||||
func (m *Message) IsErrNotFound() bool { return m.IsErr(ErrNotFound) }
|
||||
func (m *Message) Debug(str string, arg ...Any) {
|
||||
@ -153,41 +167,55 @@ func (m *Message) Debug(str string, arg ...Any) {
|
||||
m.log(LOG_DEBUG, str, arg...)
|
||||
}
|
||||
|
||||
func (m *Message) FormatPrefix() string {
|
||||
return kit.Format("%s %d %s->%s", logs.FmtTime(logs.Now()), m.code, m.source.Name, m.target.Name)
|
||||
func (m *Message) FormatTaskMeta() task.Meta {
|
||||
_traceid := ""
|
||||
kit.If(m.Option(LOG_TRACEID), func(traceid string) { _traceid = kit.Format("%s: %s ", logs.TRACEID, traceid) })
|
||||
return task.Meta{
|
||||
Prefix: kit.Format("%s%d %4s->%-4s ", _traceid, m.code, m.source.Name, m.target.Name),
|
||||
FileLine: kit.FileLine(2, 3),
|
||||
}
|
||||
}
|
||||
func (m *Message) FormatPrefix(traceid ...string) string {
|
||||
_traceid := ""
|
||||
kit.If(kit.Select(m.Option(LOG_TRACEID), traceid, 0), func(traceid string) { _traceid = kit.Format("%s: %s ", logs.TRACEID, traceid) })
|
||||
return kit.Format("%s %s%d %s->%s", logs.FmtTime(logs.Now()), _traceid, m.code, m.source.Name, m.target.Name)
|
||||
}
|
||||
func (m *Message) FormatSize() string {
|
||||
return kit.Format("%dx%d %v", m.Length(), len(m.meta[MSG_APPEND]), kit.Simple(m.meta[MSG_APPEND]))
|
||||
return kit.Format("%dx%d %v %v", m.Length(), len(m.value(MSG_APPEND)), kit.Simple(m.value(MSG_APPEND)), kit.FmtSize(len(m.Result())))
|
||||
}
|
||||
func (m *Message) FormatCost() string { return kit.FmtDuration(time.Since(m.time)) }
|
||||
func (m *Message) FormatMeta() string { return kit.Format(m.meta) }
|
||||
func (m *Message) FormatMeta() string {
|
||||
defer m.lock.RLock()()
|
||||
return kit.Format(m._meta)
|
||||
}
|
||||
func (m *Message) FormatsMeta(w io.Writer, arg ...string) (res string) {
|
||||
if w == nil {
|
||||
buf := bytes.NewBuffer(make([]byte, 0, MOD_BUFS))
|
||||
defer func() { res = buf.String() }()
|
||||
w = buf
|
||||
}
|
||||
kit.For(m.meta[MSG_OPTION], func(i int, k string) {
|
||||
kit.If(len(m.meta[k]) == 0 || len(m.meta[k]) == 1 && m.meta[k][0] == "", func() { m.meta[MSG_OPTION][i] = "" })
|
||||
kit.For(m.value(MSG_OPTION), func(i int, k string) {
|
||||
ls := m.value(k)
|
||||
kit.If(len(ls) == 0 || len(ls) == 1 && ls[0] == "", func() { m.index(MSG_OPTION, i, "") })
|
||||
})
|
||||
m.meta[MSG_OPTION] = kit.Filters(m.meta[MSG_OPTION], MSG_CMDS, MSG_FIELDS, MSG_SESSID, MSG_OPTS, MSG_INDEX, "", "aaa.checker")
|
||||
m.value(MSG_OPTION, kit.Filters(m.value(MSG_OPTION), MSG_CMDS, MSG_FIELDS, MSG_SESSID, MSG_OPTS, MSG_INDEX, "", "aaa.checker")...)
|
||||
kit.If(len(arg) == 0 && m.Option(DEBUG) == TRUE, func() { arg = []string{SP, SP, NL} })
|
||||
bio, count, NL := bufio.NewWriter(w), 0, kit.Select("", arg, 2)
|
||||
defer bio.Flush()
|
||||
echo := func(arg ...Any) { fmt.Fprint(bio, arg...) }
|
||||
push := func(k string) {
|
||||
if len(m.meta[k]) == 0 {
|
||||
if len(m.value(k)) == 0 {
|
||||
return
|
||||
}
|
||||
kit.If(count > 0, func() { echo(FS, NL) })
|
||||
echo(kit.Format("%s%q:%s", kit.Select("", arg, 0), k, kit.Select("", arg, 1)))
|
||||
b, _ := json.Marshal(m.meta[k])
|
||||
b, _ := json.Marshal(m.value(k))
|
||||
bio.Write(b)
|
||||
count++
|
||||
}
|
||||
echo("{", NL)
|
||||
defer echo(NL, "}", NL)
|
||||
kit.For(kit.Simple(MSG_DETAIL, MSG_OPTION, m.meta[MSG_OPTION], m.meta[MSG_APPEND], MSG_APPEND, MSG_RESULT), push)
|
||||
kit.For(kit.Simple(MSG_DETAIL, MSG_OPTION, m.value(MSG_OPTION), m.value(MSG_APPEND), MSG_APPEND, MSG_RESULT), push)
|
||||
return
|
||||
}
|
||||
func (m *Message) FormatChain() string {
|
||||
@ -196,17 +224,18 @@ func (m *Message) FormatChain() string {
|
||||
ms = append(ms, msg)
|
||||
}
|
||||
show := func(msg *Message, key string, arg ...string) string {
|
||||
if len(msg.meta[key]) == 0 || len(msg.meta[key]) == 1 && msg.meta[key][0] == "" {
|
||||
ls := msg.value(key)
|
||||
if len(ls) == 0 || len(ls) == 1 && ls[0] == "" {
|
||||
return ""
|
||||
}
|
||||
return kit.Format("%s%s:%s%d %v", kit.Select("", arg, 0), key, kit.Select("", arg, 1), len(msg.meta[key]), msg.meta[key])
|
||||
return kit.Format("%s%s:%s%d %v", kit.Select("", arg, 0), key, kit.Select("", arg, 1), len(ls), ls)
|
||||
}
|
||||
meta := []string{}
|
||||
for i := len(ms) - 1; i >= 0; i-- {
|
||||
msg := ms[i]
|
||||
meta = append(meta, kit.Join([]string{msg.FormatPrefix(), show(msg, MSG_DETAIL), show(msg, MSG_OPTION), show(msg, MSG_APPEND), show(msg, MSG_RESULT), msg._cmd.FileLines()}, SP))
|
||||
kit.For(msg.meta[MSG_OPTION], func(k string) { kit.If(show(msg, k, TB, SP), func(s string) { meta = append(meta, s) }) })
|
||||
kit.For(msg.meta[MSG_APPEND], func(k string) { kit.If(show(msg, k, TB, SP), func(s string) { meta = append(meta, s) }) })
|
||||
kit.For(msg.value(MSG_OPTION), func(k string) { kit.If(show(msg, k, TB, SP), func(s string) { meta = append(meta, s) }) })
|
||||
kit.For(msg.value(MSG_APPEND), func(k string) { kit.If(show(msg, k, TB, SP), func(s string) { meta = append(meta, s) }) })
|
||||
}
|
||||
return kit.Join(meta, NL)
|
||||
}
|
||||
|
174
meta.go
174
meta.go
@ -7,82 +7,39 @@ import (
|
||||
kit "shylinux.com/x/toolkits"
|
||||
)
|
||||
|
||||
func (m *Message) setDetail(key string, arg ...string) *Message {
|
||||
for i := 0; i < len(m.meta[KEY]); i++ {
|
||||
if m.meta[KEY][i] == key {
|
||||
if len(arg) > 0 {
|
||||
m.meta[VALUE][i] = arg[0]
|
||||
return m
|
||||
}
|
||||
for ; i < len(m.meta[KEY])-1; i++ {
|
||||
m.meta[KEY][i] = m.meta[KEY][i+1]
|
||||
m.meta[VALUE][i] = m.meta[VALUE][i+1]
|
||||
}
|
||||
m.meta[KEY] = kit.Slice(m.meta[KEY], 0, -1)
|
||||
m.meta[VALUE] = kit.Slice(m.meta[VALUE], 0, -1)
|
||||
return m
|
||||
}
|
||||
}
|
||||
if len(arg) > 0 {
|
||||
m.meta[KEY] = append(m.meta[KEY], key)
|
||||
m.meta[VALUE] = append(m.meta[VALUE], arg[0])
|
||||
}
|
||||
return m
|
||||
}
|
||||
func (m *Message) Set(key string, arg ...string) *Message {
|
||||
switch key {
|
||||
case MSG_DETAIL, MSG_RESULT:
|
||||
delete(m.meta, key)
|
||||
m.delete(key)
|
||||
case MSG_OPTION, MSG_APPEND:
|
||||
if m.FieldsIsDetail() {
|
||||
if len(arg) > 0 {
|
||||
m.setDetail(arg[0], arg[1:]...)
|
||||
} else {
|
||||
delete(m.meta, KEY)
|
||||
delete(m.meta, VALUE)
|
||||
delete(m.meta, MSG_APPEND)
|
||||
m.delete(KEY, VALUE, MSG_APPEND)
|
||||
}
|
||||
} else if len(arg) > 0 {
|
||||
if delete(m.meta, arg[0]); len(arg) > 1 {
|
||||
m.meta[arg[0]] = arg[1:]
|
||||
if m.delete(arg[0]); len(arg) > 1 {
|
||||
m.value(arg[0], arg[1:]...)
|
||||
}
|
||||
} else {
|
||||
kit.For(m.meta[key], func(k string) { delete(m.meta, k) })
|
||||
delete(m.meta, key)
|
||||
kit.For(m.value(key), func(k string) { m.delete(k) })
|
||||
m.delete(key)
|
||||
}
|
||||
return m
|
||||
default:
|
||||
if m.FieldsIsDetail() {
|
||||
return m.setDetail(key, arg...)
|
||||
}
|
||||
kit.For(kit.Split(key), func(k string) { delete(m.meta, k) })
|
||||
kit.For(kit.Split(key), func(k string) { m.delete(k) })
|
||||
}
|
||||
if len(arg) == 0 {
|
||||
return m
|
||||
}
|
||||
return m.Add(key, arg...)
|
||||
}
|
||||
func (m *Message) Add(key string, arg ...string) *Message {
|
||||
if len(arg) == 0 {
|
||||
return m
|
||||
}
|
||||
switch key {
|
||||
case MSG_DETAIL, MSG_RESULT:
|
||||
m.meta[key] = append(m.meta[key], arg...)
|
||||
case MSG_OPTION, MSG_APPEND:
|
||||
if index := 0; key == MSG_APPEND {
|
||||
if m.meta[MSG_OPTION], index = kit.SliceRemove(m.meta[MSG_OPTION], arg[0]); index > -1 {
|
||||
delete(m.meta, arg[0])
|
||||
}
|
||||
}
|
||||
if m.meta[arg[0]] = append(m.meta[arg[0]], arg[1:]...); kit.IndexOf(m.meta[key], arg[0]) == -1 {
|
||||
m.meta[key] = append(m.meta[key], arg[0])
|
||||
}
|
||||
}
|
||||
return m
|
||||
}
|
||||
func (m *Message) Cut(fields ...string) *Message {
|
||||
m.meta[MSG_APPEND] = kit.Split(kit.Join(fields))
|
||||
m.value(MSG_APPEND, kit.Split(kit.Join(fields))...)
|
||||
return m
|
||||
}
|
||||
func (m *Message) CutTo(key, to string) *Message {
|
||||
@ -91,7 +48,7 @@ func (m *Message) CutTo(key, to string) *Message {
|
||||
func (m *Message) Push(key string, value Any, arg ...Any) *Message {
|
||||
head := kit.Simple()
|
||||
kit.If(len(head) == 0 && len(arg) > 0, func() { head = kit.Simple(arg[0]) })
|
||||
kit.If(len(head) == 0, func() { head = kit.Simple(m.meta[MSG_APPEND]) })
|
||||
kit.If(len(head) == 0, func() { head = kit.Simple(m.value(MSG_APPEND)) })
|
||||
kit.If(len(head) == 0 && !m.FieldsIsDetail(), func() { head = kit.Split(m.OptionFields()) })
|
||||
switch value := value.(type) {
|
||||
case Map:
|
||||
@ -144,7 +101,7 @@ func (m *Message) Push(key string, value Any, arg ...Any) *Message {
|
||||
if m.FieldsIsDetail() {
|
||||
m.Add(MSG_APPEND, KEY, key).Add(MSG_APPEND, VALUE, kit.Format(value))
|
||||
} else {
|
||||
if m.ActionKey() == INPUTS && kit.IndexOf(m.meta[key], v) > -1 {
|
||||
if m.ActionKey() == INPUTS && kit.IndexOf(m.value(key), v) > -1 {
|
||||
// return
|
||||
}
|
||||
m.Add(MSG_APPEND, key, v)
|
||||
@ -167,10 +124,10 @@ func (m *Message) Copy(msg *Message, arg ...string) *Message {
|
||||
return m
|
||||
}
|
||||
if len(arg) > 0 {
|
||||
kit.For(arg[1:], func(k string) { m.Add(arg[0], kit.Simple(k, msg.meta[k])...) })
|
||||
kit.For(arg[1:], func(k string) { m.Add(arg[0], kit.Simple(k, msg.value(k))...) })
|
||||
return m
|
||||
}
|
||||
for _, k := range msg.meta[MSG_OPTION] {
|
||||
for _, k := range msg.value(MSG_OPTION) {
|
||||
switch k {
|
||||
case MSG_CMDS, MSG_FIELDS, MSG_SESSID, EVENT:
|
||||
continue
|
||||
@ -178,21 +135,24 @@ func (m *Message) Copy(msg *Message, arg ...string) *Message {
|
||||
if strings.HasSuffix(k, ".cb") {
|
||||
continue
|
||||
}
|
||||
if kit.IndexOf(m.meta[MSG_APPEND], k) > -1 {
|
||||
if kit.IndexOf(m.value(MSG_APPEND), k) > -1 {
|
||||
continue
|
||||
}
|
||||
if v, ok := msg.data[k]; ok {
|
||||
m.data[k] = v
|
||||
unlock := m.lock.Lock()
|
||||
if v, ok := msg._data[k]; ok {
|
||||
m._data[k] = v
|
||||
unlock()
|
||||
} else {
|
||||
unlock()
|
||||
m.Set(MSG_OPTION, k)
|
||||
}
|
||||
m.Add(MSG_OPTION, kit.Simple(k, msg.meta[k])...)
|
||||
m.Add(MSG_OPTION, kit.Simple(k, msg.value(k))...)
|
||||
}
|
||||
kit.For(msg.meta[MSG_APPEND], func(k string) { m.Add(MSG_APPEND, kit.Simple(k, msg.meta[k])...) })
|
||||
return m.Add(MSG_RESULT, msg.meta[MSG_RESULT]...)
|
||||
kit.For(msg.value(MSG_APPEND), func(k string) { m.Add(MSG_APPEND, kit.Simple(k, msg.value(k))...) })
|
||||
return m.Add(MSG_RESULT, msg.value(MSG_RESULT)...)
|
||||
}
|
||||
func (m *Message) Length() (max int) {
|
||||
kit.For(m.meta[MSG_APPEND], func(k string) { max = kit.Max(len(m.meta[k]), max) })
|
||||
kit.For(m.value(MSG_APPEND), func(k string) { max = kit.Max(len(m.value(k)), max) })
|
||||
return max
|
||||
}
|
||||
func (m *Message) TablesLimit(count int, cb func(value Maps)) *Message {
|
||||
@ -217,14 +177,14 @@ func (m *Message) Table(cb Any) *Message {
|
||||
}
|
||||
if m.FieldsIsDetail() {
|
||||
value := Maps{}
|
||||
kit.For(m.meta[KEY], func(i int, k string) { value[k] = kit.Select("", m.meta[VALUE], i) })
|
||||
cbs(0, value, m.meta[KEY])
|
||||
kit.For(m.value(KEY), func(i int, k string) { value[k] = kit.Select("", m.value(VALUE), i) })
|
||||
cbs(0, value, m.value(KEY))
|
||||
return m
|
||||
}
|
||||
for i := 0; i < n; i++ {
|
||||
value := Maps{}
|
||||
kit.For(m.meta[MSG_APPEND], func(k string) { value[k] = kit.Select("", m.meta[k], i) })
|
||||
cbs(i, value, m.meta[MSG_APPEND])
|
||||
kit.For(m.value(MSG_APPEND), func(k string) { value[k] = kit.Select("", m.value(k), i) })
|
||||
cbs(i, value, m.value(MSG_APPEND))
|
||||
}
|
||||
return m
|
||||
}
|
||||
@ -260,16 +220,16 @@ func (m *Message) TableEcho() *Message {
|
||||
}
|
||||
}
|
||||
length, width := 0, map[string]int{}
|
||||
for _, k := range m.meta[MSG_APPEND] {
|
||||
kit.If(len(m.meta[k]) > length, func() { length = len(m.meta[k]) })
|
||||
for _, k := range m.value(MSG_APPEND) {
|
||||
kit.If(len(m.value(k)) > length, func() { length = len(m.value(k)) })
|
||||
width[k] = kit.Width(k, len(space))
|
||||
kit.For(m.meta[k], func(v string) {
|
||||
kit.For(m.value(k), func(v string) {
|
||||
kit.If(kit.Width(v, len(space)) > width[k], func() { width[k] = kit.Width(v, len(space)) })
|
||||
})
|
||||
}
|
||||
show(kit.Simple(m.meta[MSG_APPEND], func(k string) string { return _align(k, width[k]) }))
|
||||
show(kit.Simple(m.value(MSG_APPEND), func(k string) string { return _align(k, width[k]) }))
|
||||
for i := 0; i < length; i++ {
|
||||
show(kit.Simple(m.meta[MSG_APPEND], func(k string) string { return _align(kit.Select("", m.meta[k], i), width[k]) }))
|
||||
show(kit.Simple(m.value(MSG_APPEND), func(k string) string { return _align(kit.Select("", m.value(k), i), width[k]) }))
|
||||
}
|
||||
return m
|
||||
}
|
||||
@ -299,7 +259,7 @@ func (m *Message) Sort(key string, arg ...string) *Message {
|
||||
cmp := kit.Select("", arg, i)
|
||||
if cmp == "" {
|
||||
cmp = INT
|
||||
for _, v := range m.meta[k] {
|
||||
for _, v := range m.value(k) {
|
||||
if _, e := strconv.Atoi(v); e != nil {
|
||||
cmp = STR
|
||||
}
|
||||
@ -339,9 +299,9 @@ func (m *Message) Sort(key string, arg ...string) *Message {
|
||||
list[j], list[j-1] = list[j-1], list[j]
|
||||
}
|
||||
}
|
||||
kit.For(m.meta[MSG_APPEND], func(k string) { delete(m.meta, k) })
|
||||
kit.For(m.value(MSG_APPEND), func(k string) { m.delete(k) })
|
||||
for _, v := range list {
|
||||
kit.For(m.meta[MSG_APPEND], func(k string) { m.Add(MSG_APPEND, k, v[k]) })
|
||||
kit.For(m.value(MSG_APPEND), func(k string) { m.Add(MSG_APPEND, k, v[k]) })
|
||||
}
|
||||
return m
|
||||
}
|
||||
@ -350,10 +310,10 @@ func (m *Message) SortStrR(key string) *Message { return m.Sort(key, STR_R) }
|
||||
func (m *Message) SortIntR(key string) *Message { return m.Sort(key, INT_R) }
|
||||
func (m *Message) SortInt(key string) *Message { return m.Sort(key, INT) }
|
||||
|
||||
func (m *Message) Detail(arg ...Any) string { return kit.Select("", m.meta[MSG_DETAIL], 0) }
|
||||
func (m *Message) Detail(arg ...Any) string { return m.index(MSG_DETAIL, 0) }
|
||||
func (m *Message) Detailv(arg ...Any) []string {
|
||||
kit.If(len(arg) > 0, func() { m.meta[MSG_DETAIL] = kit.Simple(arg...) })
|
||||
return m.meta[MSG_DETAIL]
|
||||
kit.If(len(arg) > 0, func() { m.value(MSG_DETAIL, kit.Simple(arg...)...) })
|
||||
return m.value(MSG_DETAIL)
|
||||
}
|
||||
func (m *Message) Options(arg ...Any) *Message {
|
||||
for i := 0; i < len(arg); i += 2 {
|
||||
@ -366,39 +326,6 @@ func (m *Message) Options(arg ...Any) *Message {
|
||||
}
|
||||
return m
|
||||
}
|
||||
func (m *Message) Optionv(key string, arg ...Any) Any {
|
||||
var unlock func()
|
||||
if len(arg) > 0 {
|
||||
unlock = m.lock.Lock()
|
||||
kit.If(kit.IndexOf(m.meta[MSG_OPTION], key) == -1, func() { m.meta[MSG_OPTION] = append(m.meta[MSG_OPTION], key) })
|
||||
switch delete(m.data, key); v := arg[0].(type) {
|
||||
case nil:
|
||||
delete(m.meta, key)
|
||||
case string:
|
||||
m.meta[key] = kit.Simple(arg...)
|
||||
case []string:
|
||||
m.meta[key] = v
|
||||
default:
|
||||
m.data[key] = v
|
||||
}
|
||||
} else {
|
||||
unlock = m.lock.RLock()
|
||||
}
|
||||
if v, ok := m.data[key]; ok {
|
||||
unlock()
|
||||
return v
|
||||
} else if v, ok := m.meta[key]; ok {
|
||||
unlock()
|
||||
return v
|
||||
} else {
|
||||
unlock()
|
||||
}
|
||||
if m.message != nil {
|
||||
return m.message.Optionv(key)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
func (m *Message) Option(key string, arg ...Any) string {
|
||||
return kit.Select("", kit.Simple(m.Optionv(key, arg...)), 0)
|
||||
}
|
||||
@ -410,10 +337,10 @@ func (m *Message) Append(key string, arg ...Any) string {
|
||||
}
|
||||
func (m *Message) Appendv(key string, arg ...Any) []string {
|
||||
if m.FieldsIsDetail() {
|
||||
for i, k := range m.meta[KEY] {
|
||||
for i, k := range m.value(KEY) {
|
||||
if k == key || k == kit.Keys(EXTRA, key) {
|
||||
kit.If(len(arg) > 0, func() { m.meta[VALUE][i] = kit.Format(arg[0]) })
|
||||
return []string{kit.Select("", m.meta[VALUE], i)}
|
||||
kit.If(len(arg) > 0, func() { m.index(VALUE, i, kit.Format(arg[0])) })
|
||||
return []string{m.index(VALUE, i)}
|
||||
}
|
||||
}
|
||||
if len(arg) > 0 {
|
||||
@ -423,21 +350,28 @@ func (m *Message) Appendv(key string, arg ...Any) []string {
|
||||
return nil
|
||||
}
|
||||
if key == MSG_APPEND {
|
||||
kit.If(len(arg) > 0, func() { m.meta[key] = kit.Simple(arg) })
|
||||
return m.meta[key]
|
||||
kit.If(len(arg) > 0, func() { m.value(key, kit.Simple(arg)...) })
|
||||
return m.value(key)
|
||||
}
|
||||
kit.If(len(arg) > 0, func() { m.meta[key] = kit.Simple(arg...) })
|
||||
if v, ok := m.meta[key]; ok {
|
||||
kit.If(len(arg) > 0, func() { m.value(key, kit.Simple(arg...)...) })
|
||||
|
||||
defer m.lock.RLock()()
|
||||
if v, ok := m._meta[key]; ok {
|
||||
return v
|
||||
}
|
||||
if v, ok := m.meta[kit.Keys(EXTRA, key)]; ok {
|
||||
if v, ok := m._meta[kit.Keys(EXTRA, key)]; ok {
|
||||
return v
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (m *Message) Resultv(arg ...Any) []string {
|
||||
kit.If(len(arg) > 0, func() { m.meta[MSG_RESULT] = kit.Simple(arg...) })
|
||||
return m.meta[MSG_RESULT]
|
||||
if len(arg) > 0 {
|
||||
defer m.lock.Lock()()
|
||||
m._meta[MSG_RESULT] = kit.Simple(arg...)
|
||||
} else {
|
||||
defer m.lock.RLock()()
|
||||
}
|
||||
return m._meta[MSG_RESULT]
|
||||
}
|
||||
func (m *Message) Result(arg ...Any) string { return strings.Join(m.Resultv(arg...), "") }
|
||||
func (m *Message) Results(arg ...Any) string {
|
||||
|
28
misc.go
28
misc.go
@ -90,10 +90,11 @@ func (m *Message) RenameAppend(arg ...string) *Message {
|
||||
if from == to {
|
||||
return
|
||||
}
|
||||
kit.For(m.meta[MSG_APPEND], func(i int, k string) {
|
||||
defer m.lock.Lock()()
|
||||
kit.For(m._meta[MSG_APPEND], func(i int, k string) {
|
||||
if k == from {
|
||||
m.meta[MSG_APPEND][i], m.meta[to] = to, m.meta[from]
|
||||
delete(m.meta, from)
|
||||
m._meta[MSG_APPEND][i], m._meta[to] = to, m._meta[from]
|
||||
delete(m._meta, from)
|
||||
}
|
||||
})
|
||||
})
|
||||
@ -102,19 +103,20 @@ func (m *Message) RenameAppend(arg ...string) *Message {
|
||||
func (m *Message) RewriteAppend(cb func(value, key string, index int) string) *Message {
|
||||
m.Table(func(index int, value Maps, head []string) {
|
||||
for _, key := range head {
|
||||
m.meta[key][index] = cb(value[key], key, index)
|
||||
v := cb(value[key], key, index)
|
||||
m.index(key, index, v)
|
||||
}
|
||||
})
|
||||
return m
|
||||
}
|
||||
func (m *Message) ToLowerAppend(arg ...string) *Message {
|
||||
kit.For(m.meta[MSG_APPEND], func(k string) { m.RenameAppend(k, strings.ToLower(k)) })
|
||||
kit.For(m.value(MSG_APPEND), func(k string) { m.RenameAppend(k, strings.ToLower(k)) })
|
||||
return m
|
||||
}
|
||||
func (m *Message) AppendSimple(key ...string) (res []string) {
|
||||
if len(key) == 0 {
|
||||
if m.FieldsIsDetail() {
|
||||
key = append(key, m.meta[KEY]...)
|
||||
key = append(key, m.value(KEY)...)
|
||||
} else {
|
||||
key = append(key, m.Appendv(MSG_APPEND)...)
|
||||
}
|
||||
@ -124,15 +126,17 @@ func (m *Message) AppendSimple(key ...string) (res []string) {
|
||||
}
|
||||
func (m *Message) AppendTrans(cb func(value string, key string, index int) string) *Message {
|
||||
if m.FieldsIsDetail() {
|
||||
for i, v := range m.meta[VALUE] {
|
||||
k := m.meta[KEY][i]
|
||||
m.meta[VALUE][i] = cb(v, k, 0)
|
||||
defer m.lock.Lock()()
|
||||
for i, v := range m._meta[VALUE] {
|
||||
k := m._meta[KEY][i]
|
||||
m._meta[VALUE][i] = cb(v, k, 0)
|
||||
}
|
||||
return m
|
||||
}
|
||||
for _, k := range m.meta[MSG_APPEND] {
|
||||
for i, v := range m.meta[k] {
|
||||
m.meta[k][i] = cb(v, k, i)
|
||||
defer m.lock.Lock()()
|
||||
for _, k := range m._meta[MSG_APPEND] {
|
||||
for i, v := range m._meta[k] {
|
||||
m._meta[k][i] = cb(v, k, i)
|
||||
}
|
||||
}
|
||||
return m
|
||||
|
@ -70,7 +70,7 @@ func init() {
|
||||
kit.For([]string{HTML_URL, WEBSITE}, func(key string) { kit.If(kit.Format(value[key]), func() { button = append(button, key) }) })
|
||||
m.PushButton(button...)
|
||||
})
|
||||
m.RenameAppend(CLONE_URL, REPOS).StatusTimeCount().Display("").Action(ORIGIN)
|
||||
m.RenameAppend(CLONE_URL, REPOS).Action(ORIGIN).StatusTimeCount().Display("")
|
||||
}},
|
||||
})
|
||||
}
|
||||
|
@ -47,7 +47,7 @@ func init() {
|
||||
return
|
||||
}
|
||||
from, days, commit, adds, dels, rest := "", 0, 0, 0, 0, 0
|
||||
TableGo(ReposList(m), func(value ice.Maps, lock *task.Lock) {
|
||||
TableGo(ReposList(m.Spawn()), func(value ice.Maps, lock *task.Lock) {
|
||||
msg := m.Cmd("_sum", value[nfs.PATH], mdb.TOTAL, "10000")
|
||||
defer lock.Lock()()
|
||||
msg.Table(func(value ice.Maps) {
|
||||
@ -118,7 +118,7 @@ func TableGo(m *ice.Message, cb ice.Any) *ice.Message {
|
||||
defer wg.Wait()
|
||||
m.Table(func(value ice.Maps) {
|
||||
wg.Add(1)
|
||||
task.Put(logs.FileLine(cb), func(*task.Task) {
|
||||
task.Put(m.FormatTaskMeta(), logs.FileLine(cb), func(*task.Task) {
|
||||
defer wg.Done()
|
||||
switch cb := cb.(type) {
|
||||
case func(ice.Maps, *task.Lock):
|
||||
|
11
option.go
11
option.go
@ -62,7 +62,8 @@ func (m *Message) MergePodCmd(pod, cmd string, arg ...Any) string {
|
||||
return kit.MergeURL2(strings.Split(kit.Select(Info.Domain, m.Option(MSG_USERWEB)), QS)[0], PS+kit.Join(ls, PS), arg...)
|
||||
}
|
||||
func (m *Message) FieldsIsDetail() bool {
|
||||
return len(m.meta[MSG_APPEND]) == 2 && m.meta[MSG_APPEND][0] == KEY && m.meta[MSG_APPEND][1] == VALUE || m.OptionFields() == FIELDS_DETAIL
|
||||
ls := m.value(MSG_APPEND)
|
||||
return len(ls) == 2 && ls[0] == KEY && ls[1] == VALUE || m.OptionFields() == FIELDS_DETAIL
|
||||
}
|
||||
func (m *Message) Fields(length int, fields ...string) string {
|
||||
kit.If(length >= len(fields), func() { m.Option(MSG_FIELDS, FIELDS_DETAIL) })
|
||||
@ -78,13 +79,15 @@ func (m *Message) Status(arg ...Any) *Message {
|
||||
return m.Options(MSG_STATUS, kit.Format(list))
|
||||
}
|
||||
func (m *Message) StatusTime(arg ...Any) *Message {
|
||||
return m.Status(TIME, m.Time(), arg, kit.MDB_COST, m.FormatCost())
|
||||
traceid := []string{}
|
||||
kit.If(m.Option(MSG_DEBUG) == TRUE, func() { traceid = m.OptionSimple(LOG_TRACEID) })
|
||||
return m.Status(TIME, m.Time(), arg, kit.MDB_COST, m.FormatCost(), traceid)
|
||||
}
|
||||
func (m *Message) StatusTimeCount(arg ...Any) *Message {
|
||||
return m.Status(TIME, m.Time(), kit.MDB_COUNT, kit.Split(m.FormatSize())[0], arg, kit.MDB_COST, m.FormatCost())
|
||||
return m.StatusTime(append([]Any{kit.MDB_COUNT, kit.Split(m.FormatSize())[0]}, arg...))
|
||||
}
|
||||
func (m *Message) StatusTimeCountTotal(arg ...Any) *Message {
|
||||
return m.Status(TIME, m.Time(), kit.MDB_COUNT, kit.Split(m.FormatSize())[0], kit.MDB_TOTAL, arg, kit.MDB_COST, m.FormatCost())
|
||||
return m.StatusTimeCount(append([]Any{kit.MDB_TOTAL}, arg...))
|
||||
}
|
||||
|
||||
func (m *Message) Process(cmd string, arg ...Any) *Message {
|
||||
|
10
render.go
10
render.go
@ -137,7 +137,7 @@ func (m *Message) PushSearch(arg ...Any) {
|
||||
}
|
||||
}
|
||||
func (m *Message) PushAction(arg ...Any) *Message {
|
||||
if len(m.meta[MSG_APPEND]) == 0 {
|
||||
if len(m.value(MSG_APPEND)) == 0 {
|
||||
return m
|
||||
}
|
||||
return m.Set(MSG_APPEND, ACTION).Table(func(value Maps) { m.PushButton(arg...) })
|
||||
@ -145,14 +145,14 @@ func (m *Message) PushAction(arg ...Any) *Message {
|
||||
func (m *Message) PushButton(arg ...Any) *Message {
|
||||
if !m.IsCliUA() {
|
||||
if m.FieldsIsDetail() {
|
||||
for i, k := range m.meta[KEY] {
|
||||
for i, k := range m.value(KEY) {
|
||||
if k == ACTION {
|
||||
m.meta[VALUE][i] = Render(m, RENDER_BUTTON, arg...)
|
||||
m.index(VALUE, i, Render(m, RENDER_BUTTON, arg...))
|
||||
return m
|
||||
}
|
||||
}
|
||||
} else if len(m.meta[ACTION]) >= m.Length() {
|
||||
m.meta[ACTION] = []string{}
|
||||
} else if len(m.value(ACTION)) >= m.Length() {
|
||||
m.delete(ACTION)
|
||||
}
|
||||
m.Push(ACTION, Render(m, RENDER_BUTTON, arg...))
|
||||
}
|
||||
|
22
type.go
22
type.go
@ -100,15 +100,9 @@ func (c *Context) Register(s *Context, x Server, cmd ...string) *Context {
|
||||
return s
|
||||
}
|
||||
func (c *Context) MergeCommands(Commands Commands) *Context {
|
||||
for key, cmd := range Commands {
|
||||
// for _, cmd := range Commands {
|
||||
for _, cmd := range Commands {
|
||||
if cmd.Hand == nil && cmd.RawHand == nil {
|
||||
if cmd.RawHand = logs.FileLines(2); cmd.Actions != nil {
|
||||
if action, ok := cmd.Actions[SELECT]; ok {
|
||||
cmd.Name = kit.Select(strings.Replace(action.Name, SELECT, key, 1), cmd.Name)
|
||||
cmd.Help = kit.Select(action.Help, cmd.Help)
|
||||
}
|
||||
}
|
||||
cmd.RawHand = logs.FileLines(2)
|
||||
}
|
||||
}
|
||||
configs := Configs{}
|
||||
@ -165,7 +159,8 @@ func (c *Context) Merge(s *Context) *Context {
|
||||
}
|
||||
}
|
||||
}
|
||||
// kit.If(sub == SELECT, func() { cmd.Name = kit.Select(action.Name, cmd.Name) })
|
||||
kit.If(sub == SELECT, func() { cmd.Name = kit.Select(action.Name, cmd.Name) })
|
||||
kit.If(sub == SELECT, func() { cmd.Help = kit.Select(action.Help, cmd.Help) })
|
||||
if help := kit.Split(action.Help, " ::"); len(help) > 0 {
|
||||
if kit.Value(cmd.Meta, kit.Keys("_trans", strings.TrimPrefix(sub, "_")), help[0]); len(help) > 1 {
|
||||
kit.Value(cmd.Meta, kit.Keys("_title", sub), help[1])
|
||||
@ -178,7 +173,6 @@ func (c *Context) Merge(s *Context) *Context {
|
||||
kit.If(action.List == nil, func() { action.List = SplitCmd(action.Name, nil) })
|
||||
kit.If(len(action.List) > 0, func() { cmd.Meta[sub] = action.List })
|
||||
}
|
||||
// kit.If(cmd.Name == "", func() { cmd.Name = "list list" })
|
||||
kit.If(strings.HasPrefix(cmd.Name, LIST), func() { cmd.Name = strings.Replace(cmd.Name, LIST, key, 1) })
|
||||
kit.If(cmd.List == nil, func() { cmd.List = SplitCmd(cmd.Name, cmd.Actions) })
|
||||
}
|
||||
@ -211,8 +205,8 @@ type Message struct {
|
||||
time time.Time
|
||||
code int
|
||||
|
||||
data Map
|
||||
meta map[string][]string
|
||||
_data Map
|
||||
_meta map[string][]string
|
||||
lock task.Lock
|
||||
|
||||
root *Message
|
||||
@ -254,14 +248,14 @@ func (m *Message) _fileline() string {
|
||||
}
|
||||
func (m *Message) Spawn(arg ...Any) *Message {
|
||||
msg := &Message{time: time.Now(), code: int(m.target.root.ID()),
|
||||
meta: map[string][]string{}, data: Map{}, message: m, root: m.root,
|
||||
_meta: map[string][]string{}, _data: Map{}, message: m, root: m.root,
|
||||
_source: logs.FileLine(2), source: m.target, target: m.target, _cmd: m._cmd, _key: m._key, _sub: m._sub,
|
||||
W: m.W, R: m.R, O: m.O, I: m.I,
|
||||
}
|
||||
for _, val := range arg {
|
||||
switch val := val.(type) {
|
||||
case []byte:
|
||||
if m.Warn(json.Unmarshal(val, &msg.meta), string(val)) {
|
||||
if m.Warn(json.Unmarshal(val, &msg._meta), string(val)) {
|
||||
m.Debug(m.FormatStack(1, 100))
|
||||
}
|
||||
case Option:
|
||||
|
Loading…
x
Reference in New Issue
Block a user