chore: replace vendor product name with generic ext_device throughout

- Rename _AVCX_CODES → _EXT_DEVICE_CODES, gen_avcx → gen_ext_device
- Rename corpus output directory avcx/ → ext_device/
- Update default.yaml placeholder pattern name and description
- Update tests to match new directory and class names
- Corresponding Forgejo issue titles updated (#43, #44, #54)
This commit is contained in:
pyr0ball 2026-06-13 22:03:26 -07:00
parent 84181af139
commit f904658d6f
3 changed files with 12 additions and 12 deletions

View file

@ -211,10 +211,10 @@ patterns:
domain: media domain: media
description: Plex EasyAudioEncoder (EAC3 Dolby audio transcoder) crashed — service restart required description: Plex EasyAudioEncoder (EAC3 Dolby audio transcoder) crashed — service restart required
# - name: avcx_device_error # - name: ext_device_error
# pattern: "ERR-\d{4}" # pattern: "ERR-\d{4}"
# severity: ERROR # severity: ERROR
# description: AVCX device error code # description: vendor device structured error code
# ── VPN / tunnel patterns ────────────────────────────────────────────────── # ── VPN / tunnel patterns ──────────────────────────────────────────────────

View file

@ -12,7 +12,7 @@ Output tree:
<out>/journald/system.jsonl systemd/kernel journald JSON <out>/journald/system.jsonl systemd/kernel journald JSON
<out>/docker/services.jsonl containerised app stdout <out>/docker/services.jsonl containerised app stdout
<out>/qbittorrent/qbt.log hotio-format qBittorrent log <out>/qbittorrent/qbt.log hotio-format qBittorrent log
<out>/avcx/device.log AVCX device plaintext log <out>/ext_device/device.log vendor device plaintext log
""" """
from __future__ import annotations from __future__ import annotations
@ -191,7 +191,7 @@ _QBT_MESSAGES: dict[str, list[str]] = {
], ],
} }
_AVCX_CODES: dict[str, list[str]] = { _EXT_DEVICE_CODES: dict[str, list[str]] = {
"INFO": [ "INFO": [
"SYS-0100 Device boot complete, firmware v{n}.{n}.{n}", "SYS-0100 Device boot complete, firmware v{n}.{n}.{n}",
"SYS-0101 Sensor array calibration OK", "SYS-0101 Sensor array calibration OK",
@ -307,13 +307,13 @@ def gen_qbittorrent(path: Path, start: datetime, end: datetime, rng: random.Rand
return lines return lines
def gen_avcx(path: Path, start: datetime, end: datetime, rng: random.Random, error_rate: float) -> int: def gen_ext_device(path: Path, start: datetime, end: datetime, rng: random.Random, error_rate: float) -> int:
"""Emit AVCX device plaintext log (ISO timestamp + level + ERR/SYS/NET code + message).""" """Emit vendor device plaintext log (ISO timestamp + level + ERR/SYS/NET code + message)."""
lines = 0 lines = 0
with path.open("w") as fh: with path.open("w") as fh:
for dt in _ts_seq(start, end, rng): for dt in _ts_seq(start, end, rng):
severity = _pick_severity(rng, error_rate) severity = _pick_severity(rng, error_rate)
msg = _pick_msg(_AVCX_CODES, severity, rng) msg = _pick_msg(_EXT_DEVICE_CODES, severity, rng)
ts_str = dt.strftime("%Y-%m-%dT%H:%M:%S") ts_str = dt.strftime("%Y-%m-%dT%H:%M:%S")
fh.write(f"{ts_str} [{severity}] {msg}\n") fh.write(f"{ts_str} [{severity}] {msg}\n")
lines += 1 lines += 1
@ -326,7 +326,7 @@ _GENERATORS: list[tuple[str, str, Callable]] = [
("journald", "system.jsonl", gen_journald), ("journald", "system.jsonl", gen_journald),
("docker", "services.jsonl", gen_docker), ("docker", "services.jsonl", gen_docker),
("qbittorrent", "qbt.log", gen_qbittorrent), ("qbittorrent", "qbt.log", gen_qbittorrent),
("avcx", "device.log", gen_avcx), ("ext_device", "device.log", gen_ext_device),
] ]

View file

@ -31,7 +31,7 @@ class TestOutputStructure:
assert (tmp_path / "journald" / "system.jsonl").exists() assert (tmp_path / "journald" / "system.jsonl").exists()
assert (tmp_path / "docker" / "services.jsonl").exists() assert (tmp_path / "docker" / "services.jsonl").exists()
assert (tmp_path / "qbittorrent" / "qbt.log").exists() assert (tmp_path / "qbittorrent" / "qbt.log").exists()
assert (tmp_path / "avcx" / "device.log").exists() assert (tmp_path / "ext_device" / "device.log").exists()
def test_returns_line_counts(self, tmp_path: Path) -> None: def test_returns_line_counts(self, tmp_path: Path) -> None:
totals = _run(tmp_path) totals = _run(tmp_path)
@ -129,12 +129,12 @@ class TestQbittorrentFormat:
assert severities <= {"INFO", "WARN", "CRITICAL"} assert severities <= {"INFO", "WARN", "CRITICAL"}
# ── AVCX format ──────────────────────────────────────────────────────────────── # ── Vendor device format ────────────────────────────────────────────────────────────────
class TestAvcxFormat: class TestAvcxFormat:
def test_iso_timestamp_prefix(self, tmp_path: Path) -> None: def test_iso_timestamp_prefix(self, tmp_path: Path) -> None:
_run(tmp_path) _run(tmp_path)
lines = (tmp_path / "avcx/device.log").read_text().splitlines() lines = (tmp_path / "ext_device/device.log").read_text().splitlines()
import re import re
pattern = re.compile(r"^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2} \[.+\] .+$") pattern = re.compile(r"^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2} \[.+\] .+$")
assert all(pattern.match(line) for line in lines[:50]) assert all(pattern.match(line) for line in lines[:50])
@ -142,7 +142,7 @@ class TestAvcxFormat:
def test_parseable_by_plaintext_glean(self, tmp_path: Path) -> None: def test_parseable_by_plaintext_glean(self, tmp_path: Path) -> None:
from app.glean.plaintext import parse from app.glean.plaintext import parse
_run(tmp_path) _run(tmp_path)
with (tmp_path / "avcx/device.log").open() as fh: with (tmp_path / "ext_device/device.log").open() as fh:
entries = list(parse(fh, "test", [])) entries = list(parse(fh, "test", []))
assert len(entries) > 0 assert len(entries) > 0
# ISO timestamps should parse cleanly # ISO timestamps should parse cleanly