Documentation
¶
Overview ¶
Package logs 读取写在磁盘上的运行日志,供后台「日志」页查询与下载。
只读不写:日志的产生在 internal/logging,本包只解析它写下的 JSON 行。 两边共用 logging 里的文件名约定(FilePrefix / ParseFileName / SafeFileName), 免得「哪些文件算日志」出现第二个答案。
Index ¶
Constants ¶
const Name = "logs"
Name 是模块名。
Variables ¶
var ErrBadFileName = errors.New("不是合法的日志文件名")
ErrBadFileName 表示请求的文件名不是本目录下的日志文件。
Functions ¶
This section is empty.
Types ¶
type Entry ¶
type Entry struct {
Time time.Time `json:"time"`
Level string `json:"level"`
Msg string `json:"msg"`
Attrs map[string]any `json:"attrs,omitempty"`
// File 是这条日志所在的文件名,便于站长按文件下载原文。
File string `json:"file"`
}
Entry 是一条日志。
type FileInfo ¶
type FileInfo struct {
Name string `json:"name"`
// Day 是文件所属日期,形如 2026-09-21。
Day string `json:"day"`
Size int64 `json:"size"`
ModTime time.Time `json:"modTime"`
SizeHuman string `json:"sizeHuman"`
}
FileInfo 描述一个日志文件。
type Handler ¶
type Handler struct {
// contains filtered or unexported fields
}
Handler 提供日志的 Console 接口。
只有 Console 平面,且全部需要 settings:manage:日志里有请求路径、错误详情与 内部状态,不是访客该看的东西。
沿用 settings:manage 而不是新增一条 logs:read:内置角色的权限只在首次创建时 写入,新增权限串意味着已有站点的管理员拿不到它,站长得手动补——为一页日志 引入一次升级摩擦不划算。语义上也说得通:能改 SMTP 口令的人看日志不算越权。
type Module ¶
type Module struct {
// contains filtered or unexported fields
}
Module 是日志模块。
无数据库表,故不实现 Migrator:运行日志落在文件里,不落库。 理由是数据库出问题的时候恰恰最需要日志——写库意味着 DB 一挂就什么也查不到, 而且日志是高频写入,会和业务查询抢连接池。
不声明权限:接口沿用 settings:manage(见 Handler 的说明), 不往权限清单里添一条让站长以为需要额外授权的东西。
func (*Module) Permissions ¶
func (m *Module) Permissions() []app.Permission
Permissions 实现 app.PermissionProvider:本模块不新增权限串。
明写一个返回 nil 的实现而不是不实现这个接口,是为了让「为什么没有 logs:read」 这个问题在代码里有个落点。
type Query ¶
type Query struct {
// Level 是最低级别(debug/info/warn/error),空表示不限。
//
// 用「最低」而不是「精确匹配」:排障时问的是「有没有出错」,
// 选 warn 却看不到 error 会让人以为一切正常。
Level string
// Q 是关键词,在消息与全部属性值里做大小写不敏感的子串匹配。
Q string
// From、To 限定时间范围,零值表示不限。
From time.Time
To time.Time
// File 限定只查某个日志文件,空表示全部。
File string
// Page 从 1 起,Size 是每页条数。
Page int
Size int
}
Query 是一次查询的条件。