logs

package
v0.2.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 26, 2026 License: AGPL-3.0 Imports: 19 Imported by: 0

Documentation

Overview

Package logs 读取写在磁盘上的运行日志,供后台「日志」页查询与下载。

只读不写:日志的产生在 internal/logging,本包只解析它写下的 JSON 行。 两边共用 logging 里的文件名约定(FilePrefix / ParseFileName / SafeFileName), 免得「哪些文件算日志」出现第二个答案。

Index

Constants

View Source
const Name = "logs"

Name 是模块名。

Variables

View Source
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 口令的人看日志不算越权。

func NewHandler

func NewHandler(reader *Reader, fileEnabled bool) *Handler

NewHandler 构造 Handler。

func (*Handler) Register

func (h *Handler) Register(console huma.API)

Register 挂载接口。

type Module

type Module struct {
	// contains filtered or unexported fields
}

Module 是日志模块。

无数据库表,故不实现 Migrator:运行日志落在文件里,不落库。 理由是数据库出问题的时候恰恰最需要日志——写库意味着 DB 一挂就什么也查不到, 而且日志是高频写入,会和业务查询抢连接池。

不声明权限:接口沿用 settings:manage(见 Handler 的说明), 不往权限清单里添一条让站长以为需要额外授权的东西。

func New

func New() *Module

New 构造模块。

func (*Module) Name

func (m *Module) Name() string

Name 实现 app.Module。

func (*Module) Permissions

func (m *Module) Permissions() []app.Permission

Permissions 实现 app.PermissionProvider:本模块不新增权限串。

明写一个返回 nil 的实现而不是不实现这个接口,是为了让「为什么没有 logs:read」 这个问题在代码里有个落点。

func (*Module) Reader

func (m *Module) Reader() *Reader

Reader 返回日志读取器,供将来可能的复用(如诊断信息导出)。

func (*Module) Register

func (m *Module) Register(a *app.App) error

Register 实现 app.Module:只做装配,不访问数据库。

日志目录的算法必须与 cmd/lumo 里构造写入器时一致,否则页面会去一个空目录里找日志。

func (*Module) Routes

func (m *Module) Routes(r app.Router)

Routes 实现 app.RouteProvider。

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 是一次查询的条件。

type Reader

type Reader struct {
	// contains filtered or unexported fields
}

Reader 从日志目录读取日志。

func NewReader

func NewReader(dir string) *Reader

NewReader 构造读取器。

func (*Reader) Dir

func (r *Reader) Dir() string

Dir 返回日志目录。

func (*Reader) Files

func (r *Reader) Files() ([]FileInfo, error)

Files 列出日志文件,最新的在前。

func (*Reader) Open

func (r *Reader) Open(name string) (*os.File, os.FileInfo, error)

Open 打开一个日志文件供下载;文件名非法或不存在时返回错误。

func (*Reader) Query

func (r *Reader) Query(q Query) (*Result, error)

Query 按条件查询日志,最新的在前。

type Result

type Result struct {
	Items []Entry `json:"items"`
	Total int     `json:"total"`
	Page  int     `json:"page"`
	Size  int     `json:"size"`
	// Truncated 为真表示触到扫描上限,更早的日志没有纳入统计。
	Truncated bool `json:"truncated"`
}

Result 是一次查询的结果。

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL