summaryrefslogtreecommitdiff
path: root/AGENTS.md
diff options
context:
space:
mode:
Diffstat (limited to 'AGENTS.md')
-rw-r--r--AGENTS.md45
1 files changed, 38 insertions, 7 deletions
diff --git a/AGENTS.md b/AGENTS.md
index b7a7ee5..0084f21 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -218,18 +218,49 @@ If you add another sequence field, you must do the same.
## Log tail setup (important for operators)
-Most game servers create new timestamped log files per session. The
-inotify watch is set up once (at start or SIGHUP) against the resolved
-real path. The recommended pattern:
+Two modes are supported. They are mutually exclusive per unit.
+
+### Fixed-path mode (`logs:`)
+
+Point `logs:` at a stable symlink; `log_tail_init` calls `realpath()` to
+resolve it to the real inode before opening and watching it.
1. Point unit YAML `logs:` at a stable symlink, e.g. `current.log`
2. Startup script does: `ln -sf /path/to/actual.log /path/to/current.log`
-3. SIGHUP umbrella — `log_tail_init` calls `realpath()` to resolve the
- symlink to the real file before opening and watching it
-4. inotify then watches the actual inode, so `IN_MODIFY` fires correctly
+3. SIGHUP umbrella so it re-resolves the symlink
Source engine: use `sv_log_onefile 1` so the file is stable within a
-session; only update the symlink on server restart.
+session; only update the symlink on restarts.
+
+### Directory-watch mode (`log_dir` + `log_pattern`)
+
+Valve games (TF2, GMod) create a new timestamped log file on every map
+change (`L0222000.log`, `L0222001.log`, ...). Use `log_dir` to watch the
+directory and `log_pattern` (fnmatch glob) to filter filenames. Umbrella
+auto-switches to the newest matching file whenever one is created.
+
+```yaml
+log_dir: /home/gmod/nnn/gmodds/garrysmod/logs
+log_pattern: "L???????.log"
+```
+
+- `log_pattern` is optional; omitting it defaults to `"*"` (all files)
+- `log_dir` and `logs:` are mutually exclusive; if both are set, `logs:`
+ is ignored with a warning
+- Pattern matching uses `fnmatch(3)` — shell-style globs, zero allocation
+
+#### How it works
+
+- One inotify instance watches the directory for `IN_CREATE`/`IN_MOVED_TO`
+- On each new matching file, `log_tail_scan_dir` finds the newest one
+ (re-scan handles races where multiple files appear in one event batch)
+- `log_tail_switch_file` drains the old file, then opens the new one
+ from the beginning so no output is missed
+- `IN_MOVE_SELF`/`IN_DELETE_SELF` on the current file closes it and
+ scans for a replacement immediately
+
+SIGHUP rebuilds everything from scratch via `log_tail_cleanup` +
+`log_tail_init`.
## Filter contract