feat(syslog): a source's lines to read and search, on its page, its host's and its SNMP device's, and over MCP (#6000)
- /plugins/syslog/sources/<id>: the lines newest first, loading as you scroll, filtered by severity and worse, app, text and time, with day dividers and times to the second in the reader's zone. - The Syslog page links each source and shows its lines in the last hour. - A Syslog panel on a host's page and an SNMP device's: the newest lines of the sources bound to it or at its address. - MCP: list_syslog_sources and search_syslog (source, host, text, severity and worse, app, range, paging by next_before). - Shared: escape_like moves to steward/core/like.py and cut_middle to the MCP shaping module, replacing four inline copies; |when takes seconds=. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -25,6 +25,8 @@ from steward.mcp._context import mcp_app
|
||||
T = TypeVar("T")
|
||||
|
||||
SERIES_POINTS = 60 # max points in any returned series
|
||||
# The longest log line a tool returns whole (container logs, syslog).
|
||||
LOG_LINE_CHARS = 2000
|
||||
|
||||
|
||||
def db_session():
|
||||
@@ -134,6 +136,14 @@ def pick(want: str, rows: Iterable[T], *, kind: str, list_tool: str,
|
||||
raise ValueError(f"no {kind} named or with id {want!r}.{hint} {list_tool} lists them.")
|
||||
|
||||
|
||||
def cut_middle(text: str, limit: int = LOG_LINE_CHARS) -> str:
|
||||
"""Keep both ends of an over-long line and say how much of the middle went."""
|
||||
if text is None or len(text) <= limit:
|
||||
return text
|
||||
keep = limit // 2
|
||||
return f"{text[:keep]} [… {len(text) - 2 * keep} characters omitted …] {text[-keep:]}"
|
||||
|
||||
|
||||
def redact_url(url: str) -> str:
|
||||
"""Drop a password from a URL's userinfo; the rest stays readable."""
|
||||
try:
|
||||
|
||||
Reference in New Issue
Block a user