fix(hands): хвост логов 2000 строк по замеру, образец чистит общий redact
This commit is contained in:
1 parent
47df446462
commit
69e427469a
2 files changed
+33
-25
No files matched your search
@@ -6,6 +6,11 @@
|
||||
и обратный переход «было → нет» - с временем последнего события, не с временем
|
||||
прохода (логи берутся с `--timestamps`, время в строке настоящее).
|
||||
|
||||
Показанную строку лога чистит общий `security.redact` - тот же, что стоит на
|
||||
логах и на выдаче MCP: правила в одном месте, и он знает литеральные значения
|
||||
секретов из env. Голые блобы без имени рядом он не трогает намеренно - id
|
||||
задач, сессий и коммитов это ровно то, по чему беду потом и опознают.
|
||||
|
||||
Показание всегда несёт свою область: сколько стеков в области, сколько из них
|
||||
прочиталось, какой отрезок логов попал в хвост. Без этого «всё чисто»
|
||||
неотличимо от «половину не посмотрел», поэтому чего не смог - тоже в инжекте.
|
||||
@@ -20,6 +25,8 @@ from dataclasses import dataclass, field
|
||||
from datetime import UTC, datetime, timedelta, tzinfo
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
from beaver_gateway.security.redact import redact
|
||||
|
||||
from beaver_agent.hands.komodo import ANSI
|
||||
|
||||
if TYPE_CHECKING:
|
||||
@@ -43,9 +50,16 @@ SCOPE = ("dell-home", "personal-main")
|
||||
"""Свои серверы. Машины заказчиков (md-cars-*, veris-*, ms-agents-*) не наши:
|
||||
там чужой прод и чужие секреты, и читать их логи в свой контекст - нельзя."""
|
||||
|
||||
TAIL = 500
|
||||
"""Строк на стек. Болтливый стек столько строк проживает за минуты - об этом
|
||||
в инжекте говорится отдельно, а не выдаётся за просмотренный промежуток."""
|
||||
TAIL = 2000
|
||||
"""Строк на контейнер, и число из замера, а не «чтобы хватало».
|
||||
|
||||
Замер 20.09.2026 по всем 36 стекам области: при 500 строках хвост покрывал
|
||||
меньше трёх часов (промежуток между проходами) ровно у одного стека -
|
||||
`dell-home-music`, ~1170 строк/ч, то есть 51 минута; следующий по болтливости
|
||||
`personal-main-caddy` покрывал 11,6 часа, `beaver-agent` - 20 ч, медиана по
|
||||
области около 110 часов. 2000 строк закрывают и music (~3,4 часа) почти
|
||||
бесплатно: тихие стеки отдают столько, сколько у них есть, растут три-четыре
|
||||
болтливых. Где хвост всё равно короче промежутка, инжект говорит об этом сам."""
|
||||
|
||||
SIGNALS: tuple[tuple[str, str], ...] = (
|
||||
("критично", r"\bCRITICAL\b|\bFATAL\b|\bEMERG\b"),
|
||||
@@ -72,11 +86,6 @@ STAMP_RE = re.compile(
|
||||
"""Пустая строка тоже со штампом (`сервис | время` и ничего) - это не мусор."""
|
||||
DIGITS_RE = re.compile(r"\b[0-9a-f]{7,}\b|\d+")
|
||||
"""Числа и хеши в строке - шум: без них «то же самое» узнаётся между проходами."""
|
||||
SECRET_RE = re.compile(
|
||||
r"(?i)\b(?:token|secret|api[-_ ]?key|password|passwd|authorization)\b\s*[=:]\s*\S+"
|
||||
r"|\b[A-Za-z0-9_\-]{32,}\b"
|
||||
)
|
||||
"""Инжект уезжает в чат и в vault: похожее на ключ в показании не нужно."""
|
||||
|
||||
SAMPLE_CHARS = 180
|
||||
MAX_NEW = 25
|
||||
@@ -314,11 +323,6 @@ def _parse(raw: Any) -> datetime | None:
|
||||
return at if at.tzinfo else at.replace(tzinfo=UTC)
|
||||
|
||||
|
||||
def _mask(text: str) -> str:
|
||||
"""Замазать похожее на секрет: строка лога едет мастеру как есть."""
|
||||
return SECRET_RE.sub("<скрыто>", text)
|
||||
|
||||
|
||||
def _normal(text: str) -> str:
|
||||
"""Строка без чисел, хешей и адресов: по ней узнаётся «та же самая беда»."""
|
||||
return DIGITS_RE.sub("#", ANSI.sub("", text)).strip()
|
||||
@@ -374,7 +378,7 @@ def read_stack(stack: str, log: dict[str, Any]) -> StackScan:
|
||||
stack=stack,
|
||||
service=service,
|
||||
signal=signal,
|
||||
sample=(before.sample if before else _mask(rest)[:SAMPLE_CHARS]),
|
||||
sample=(before.sample if before else redact(rest)[:SAMPLE_CHARS]),
|
||||
at=at or (before.at if before else None),
|
||||
count=(before.count if before else 0) + 1,
|
||||
)
|
||||
|
||||
Reference in new issue
Block a user