跳转至

API

给开发者的留言

作为一名饥荒mod开发者,在收到bug反馈时,我常常要花费大量精力教玩家寻找 server_log,所以我做出了这个小工具。

错误追踪mod内置了日志发送功能,玩家只需要点击按钮,就能把报错日志直接发到你的手里。 支持两种发送方法: 邮箱URL

配置过程非常简单。只需在 modinfo.luamodmain.lua 中以全局变量的形式声明 bugtracker_config表,然后把所有配置写在这个表内。类似这样:

bugtracker_config = {
    email = "myemail@dst.com",
    upload_client_log = true,
    upload_server_log = false,
    -- 其它配置项目...
}

所有配置项目一览

项目 描述 类型 示例值
email 接收日志的邮箱。 字符串 myemail@dst.com
lang 邮件使用的语言,设定为CHI代表接收中文邮件,否则为英文。 字符串 CHI
url 接收post请求的地址,优先级高于email,注意必须带http或https协议 字符串 http://23.233.2.3:80/upload/
http://my-log-db.cn/upload/
upload_client_log 是否接受客户端报错日志,默认true。
大部分mod都包含会在客户端运行的代码,所以建议都设置为true。
布尔 true
upload_server_log 是否接受服务器报错日志,客户端mod默认false,服务器mod默认true。
建议默认(不填)。
布尔 true
upload_other_mods_crash_log 是否接受其它mod引起的报错日志,默认true。 布尔 true
auto_upload 只要发生崩溃就自动上传日志,默认false。
该设定仅对url有效。
布尔 true

详细介绍

1.设定接收条件

你可以指定哪些日志允许上传,避免收到一些无意义的报错信息。

跳过此设置,使用默认值。

bugtracker_config = {
    upload_client_log = true,  -- 接受客户端报错日志
    upload_server_log = true,  -- 接受服务器报错日志
    upload_other_mods_crash_log = true, -- 接受其他mod引起的报错日志

    -- 其它配置项目...
}

2.设定邮箱

如果你希望玩家将日志发送到你指定的邮箱,你需要添加email键,如下所示:

bugtracker_config = {
    email = "myemail@dst.com", --注意: 不要设置成工作的邮箱!建议注册一个新邮箱专门用于接收日志。
    lang = "CHI", -- 设置邮件语言为中文

    -- 其它配置项目...
}

这样一来,当玩家点击【发送日志】按钮时,日志会即刻送达你的邮箱。

具体来说,日志会先上传至我的服务器,然后自动转发到你的邮箱,每日发送上限为100封,日志信息不会储存在服务器上。

如果想收到更多报错邮件,你可以选择配置URL。(见下)

3.设定URL

如果你有一个网络服务器,强烈建议你配置一个专用的上传URL,日志信息将直接以POST的方法发送至你的服务器。

该配置的优先级高于 email 。如果同时设置 emailurl ,只有 url 会生效。

bugtracker_config = {
    url = "http://127.0.0.1:8000/demo/",  -- 请求的url,请务必带上协议,如 http:// 
    auto_upload = true, -- 设置为自动发送日志,该配置项目仅对url有效

    -- 其它配置项目...
}

上传的数据结构为: <摘要区字节数> 摘要区(json格式)日志内容(纯字符串)

这是使用python-django的后端解析示例,可供参考。(我没学过php和java,所以没有例子)

import json
import re
from django.http import HttpResponse

def parsebody(body: bytes) -> dict:
    '''饥荒只能POST字符串,服务器需要对上传的内容进行解析。
    数据结构为 <摘要区字节数> 摘要区(json格式) 日志内容(纯字符串)
    摘要区包含一些基础信息,日志则包含详细的报错内容。

    摘要结构:
    gameversion     <str>   饥荒版本号
    platform        <str>   运行平台
    playername      <str>   向您发送日志的玩家昵称
    playerid        <str>   玩家的游戏id
    modname         <str>   模组名
    modversion      <str>   模组版本号
    diagnose        <str>   诊断信息,如安全/崩溃回溯路径/崩溃点
    diagnoselevel   <int>   诊断等级,大于50代表崩溃可能和mod有关,小于50代表其他警告,0代表安全
    timestamp       <int>   崩溃发生的时间戳
    ingame          <bool>  崩溃发生在世界启动后
    isserver        <bool>  崩溃点位于服务器
    isdedicated     <bool>  崩溃点位于专用服务器
    apiversion      <str>   错误追踪器版本号
    '''
    match = re.match(b"^<(\\d+)>.", body)
    if match is not None:
        # parse abstract length
        abslenstr = match.group(1)
        abslen = int(abslenstr)
        # don't forget `<` and `>`!
        absstart = len(abslenstr) + 2
        # parse abstract, note abstract may contain utf-8 character.
        jsonstr = body[absstart: absstart + abslen].decode("utf-8")

        # Here we get abstract!
        abstract = json.loads(jsonstr)
        # Here we get log content!
        log = body[absstart + abslen: ].decode("utf-8")

        return {
            "abstract"  : abstract,
            "log"       : log,
        }

def demo(request):
    ''' Your url function '''
    if request.method == "POST":
        result = parsebody(request.body)
        if result:
            abstract = result["abstract"]
            log = request["log"]
            # Now do anything you want to do.
            # (For example, save log file in the database or send an email.)

    # Actually, BugTracker doesn't handle response, but you need this to avoid 500.
    return HttpResponse("")

进阶:忽略部分钩子

在mod中修改某些常用的基础函数,可能会导致mod经常出现在回溯路径内。

在下面的例子中,我们对 CreateEntity 函数稍作修改。

-- modmain.lua
local old_fn = GLOBAL.CreateEntity
function GLOBAL.CreateEntity(name)
    print("Hello don't starve!")
    return old_fn(name)
end

由于 CreateEntity 函数会被频繁调用,在报错路径出镜率极高,这会让你的mod也无辜中枪,被错误追踪检测到。

为了解决这一问题,你可以显式地添加忽略标记,以使特定的钩子不被错误追踪识别为报错路径。

标记格式为 local bugtracker_ignore_flag__{函数名} = true,注意flag后是双下划线。

-- modmain.lua
local old_fn = GLOBAL.CreateEntity
function GLOBAL.CreateEntity(name)
    print("Hello don't starve!")

    local bugtracker_ignore_flag__CreateEntity = true -- 标记
    return old_fn(name)
end

添加标记后,如果游戏调用 CreateEntity 发生了某些错误,你的这处修改会被错误追踪忽略,mod不会被判定为位于回溯路径内。

警告:

尽量少用这个功能,特别是在你无法确认钩子是否绝对安全的情况下。

在加入标记前,请务必确保你的修改是符合逻辑的!注意观察下面的代码。

-- modmain.lua
local old_fn = GLOBAL.CreateEntity
function GLOBAL.CreateEntity(name)
    print("Hello don't starve!")

    local bugtracker_ignore_flag__CreateEntity = true -- 标记
    -- return old_fn() -- 错误的写法,缺少原始参数
    -- old_fn(name)    -- 错误的写法,未返回,注意原始的 CreateEntity 函数有返回值

    return old_fn(name) -- 正确
end

源代码

本mod所有代码开源无混淆,如果你对本mod的实现有任何疑问,可直接查看源代码。

回到页面顶部