cloudwu / skynet

A lightweight online game framework

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

希望在 debug 的 STAT 指令返回值中添加服务名以及服务启动参数以方便调试和监控

tqing1128 opened this issue · comments

无论是 debug_console 还是自定义的监控服务中,都必须 LIST 和 STAT 一起配合使用才可以定位,而 STAT 返回值中增加服务名几乎不产生消耗,加服务启动参数需要额外处理。

我觉得可以提 pr ,mem 指令也带上名字了

STAT 和 MEM 不同在于 STAT 中每一项都是 table, MEM 是字符串,在 debug_console 可视化中 table 中每一项的显示顺序好像没有规则,STAT 中每一项最后显示的是 task:0,服务启动参数长短不一,放在最后比较合适(MEM 也是这样做的),有两种方案:

1、服务启动参数项以 t 字母开头可以显示在最后,但是这种实现比较奇怪
2、将每一项 table 都 format 成字符串,和 MEM 一样

我个人偏向第二种,但是不明确现有方案为什么没有这样做

建议另外写监控工具,debug console 和程序脚本对接。

调试的时候也经常会在 debug console 用 stat 查看信息

我的意思是,即使调试,也可以用额外的脚本去解析。debug console 支持用 http 协议 GET ,就是为了方便做这样的脚本取数据。

用额外的脚本从 debug console 中获取数据,按自己的需求整合并输出,减少不必要的指令输入,灵活高效。只是需要写一个 debug console 返回值(字符串)解析方法。是这个意思吗?

是的。这样你可以根据需要 cache 住名称等信息,不必重复查询。解析字符串相对容易,另外可以调用现成的 curl 等程序来编写脚本。

明白了,谢谢

我的意思是,即使调试,也可以用额外的脚本去解析。debug console 支持用 http 协议 GET ,就是为了方便做这样的脚本取数据。

这个有示例吗?想做一些工具来支持debug一些相关命令。比如通过http注入inject某个服务

项目中难免会需要新增一些特殊指令,可以参考下这个无侵入式扩展 debug_console 服务的 demo 。

https://github.com/hanxi/skynet-demo#无侵入式扩展官方的-debug_console-服务

@sue602 http 接口的使用示例我加到 wiki 里了 https://github.com/cloudwu/skynet/wiki/DebugConsole

如果你想通过 http 接口使用 inject 指令可以这样写(下面示例是对 debug_console 服务 inject):

> curl --http0.9 'http://127.0.0.1:8000/list'
Welcome to skynet console
:01000004       snlua cmaster
:01000005       snlua cslave
:01000007       snlua datacenterd
:01000008       snlua service_mgr
:0100000a       snlua protoloader
:0100000b       snlua console
:0100000c       snlua debug_console 8000
:0100000d       snlua simpledb
:0100000e       snlua watchdog
:0100000f       snlua gate
<CMD OK>
> curl --http0.9 'http://127.0.0.1:8000/stat'
Welcome to skynet console
:01000004       cpu:0.001628    message:10      mqlen:0 task:1
:01000005       cpu:0.001488    message:12      mqlen:0 task:1
:01000007       cpu:0.000519    message:3       mqlen:0 task:0
:01000008       cpu:0.001077    message:5       mqlen:0 task:0
:0100000a       cpu:0.000971    message:3       mqlen:0 task:0
:0100000b       cpu:0.000307    message:4       mqlen:0 task:1
:0100000c       cpu:0.001407    message:8       mqlen:0 task:1
:0100000d       cpu:0.00033     message:3       mqlen:0 task:0
:0100000e       cpu:0.000305    message:6       mqlen:0 task:0
:0100000f       cpu:0.000572    message:5       mqlen:0 task:0
<CMD OK>
> curl --http0.9 'http://127.0.0.1:8000/inject/:0100000c/debug_console_inject_source.lua'
Welcome to skynet console

<CMD OK>
> curl --http0.9 'http://127.0.0.1:8000/stat'
Welcome to skynet console
:01000004       cpu:0.000989    message:16      mqlen:0 task:1  xmem:59.74 Kb (snlua cmaster)
:01000005       cpu:0.000966    message:18      mqlen:0 task:1  xmem:64.34 Kb (snlua cslave)
:01000007       cpu:0.000362    message:9       mqlen:0 task:0  xmem:44.60 Kb (snlua datacenterd)
:01000008       cpu:0.000686    message:11      mqlen:0 task:0  xmem:53.16 Kb (snlua service_mgr)
:0100000a       cpu:0.001229    message:9       mqlen:0 task:0  xmem:251.01 Kb (snlua protoloader)
:0100000b       cpu:0.000534    message:10      mqlen:0 task:1  xmem:58.34 Kb (snlua console)
:0100000c       cpu:0.008822    message:95      mqlen:0 task:1  xmem:87.67 Kb (snlua debug_console 8000)
:0100000d       cpu:0.000425    message:9       mqlen:0 task:0  xmem:48.51 Kb (snlua simpledb)
:0100000e       cpu:0.000353    message:12      mqlen:0 task:0  xmem:47.07 Kb (snlua watchdog)
:0100000f       cpu:0.000516    message:11      mqlen:0 task:0  xmem:53.19 Kb (snlua gate)
<CMD OK>
-- debug_console_inject_source.lua
local function getupvaluetable(u, func, unique)
    unique = unique or {}
    local i = 1
    while true do
        local name, value = debug.getupvalue(func, i)
        if name == nil then
            return
        end
        local t = type(value)
        if t == "table" then
            u[name] = value
        elseif t == "function" then
            if not unique[value] then
                unique[value] = true
                getupvaluetable(u, value, unique)
            end
        end
        i=i+1
    end
end

local skynet = require "skynet"
local TIMEOUT = 300 -- 3 sec
local function timeout(ti)
    if ti then
        ti = tonumber(ti)
        if ti <= 0 then
            ti = nil
        end
    else
        ti = TIMEOUT
    end
    return ti
end
local function stat(ti)
    local statlist = skynet.call(".launcher", "lua", "STAT", timeout(ti))
    local memlist = skynet.call(".launcher", "lua", "MEM", timeout(ti))
    local memkv = {}
    for k,v in pairs(memlist) do
        memkv[k] = v
    end
    for k,v in pairs(statlist) do
        v.xmem=memkv[k]
    end
    return statlist
end

local socket = require "skynet.socket"
local u1 = {}
getupvaluetable(u1, _P.socket.socket_message[1])
for k,v in pairs(u1.socket_pool) do
    if v.callback then
        local u2 = {}
        getupvaluetable(u2, v.callback)
        for kk,vv in pairs(u2) do
            if u2.COMMAND then
                u2.COMMAND.stat = stat
            end
        end
    end
end