正在载入

等待时间过长时请刷新页面

编写于

最近更新

审计服务

LinAudit 是 Linlang 的统一诊断入口。插件从 Facade 取得一个入口,再按记录的含义选择对应成员:

LinAudit audit = lin.linAudit();
内容入口用途
运行日志logger()服务状态、调试信息和普通警告
操作审计record()谁在何时对什么资源执行了什么操作
问题报告problem()稳定问题代码、故障上下文和异常原因

三者共用 Runtime 的输出设施,但语义和文件彼此独立。普通状态不应记录为 Problem,玩家输入错误等正常结果也不属于系统故障。

运行日志与操作审计的基本用法见下文;错误边界与代码目录分别见:Problem 与异常 ⇱和Problem 代码 ⇱。

运行日志

普通状态、调试信息和不需要问题代码的警告通过 LinLogger 记录:

LinLogger logger = audit.logger();

logger.info("奖励缓存已重载:{count}", "count", rewards.size());
logger.file("数据库已落盘:{table}", "table", tableName);
logger.warn("可选资源加载失败:{file}", exception, "file", fileName);

info、warn 和 error 按租户策略写入普通日志,并可投递到控制台;file 只写普通日志文件,不向控制台输出。需要保留原因链时应使用带 Throwable 的 warn 或 error 重载,不要把堆栈转换成普通字符串。

操作审计

操作审计适合保存具有业务意义、以后可能需要追溯的事件。例如管理员修改配置、玩家领取奖励或后台任务迁移数据。

简单事件可以直接记录稳定事件名和字段:

audit.record(
        "config.reload",
        "actor", sender.getName(),
        "file", "config.yml"
);

需要完整描述事件时,使用 AuditEvent:

AuditEvent event = AuditEvent.builder("item.rename")
        .actor(player.getUniqueId().toString())
        .action("rename")
        .resource(itemId)
        .outcome(AuditOutcome.SUCCESS)
        .correlationId(requestId)
        .field("name", nextName)
        .build();

audit.record(event);

事件名、操作名和字段名应使用稳定的机器标识,不要写入随语言变化的展示文本。correlationId 用于串联同一次请求产生的多条记录。

插件隔离

Runtime 只维护一个审计 Provider,但会按插件 owner 选择名称、输出目录和控制台策略。插件不需要创建日志实现,也不会与其他插件共用输出文件。

flowchart LR
    Facade["LinAudit"] --> Logger["运行日志"]
    Facade --> Event["操作审计"]
    Facade --> Problem["问题报告"]
    Logger --> Provider["Audit Provider"]
    Event --> Provider
    Problem --> Provider
    Provider --> Tenant["按 owner 输出"]

Runtime 在插件关闭时刷新异步文件队列。确实需要等待此前记录落盘时,可以调用:

audit.flush();

讨论

请登录账号