Remove logviewer, clean up docker-compose logging sections

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
q 2026-04-18 15:37:04 +03:00
parent e49e3417eb
commit aad36f0ac5
3 changed files with 0 additions and 209 deletions

View file

@ -44,15 +44,6 @@ services:
- qdrant - qdrant
ports: ports:
- "8001:8000" - "8001:8000"
logging:
driver: json-file
options:
max-size: "20m"
max-file: "5"
tag: "index-service"
labels: "service"
labels:
- "service=index-service"
search: search:
build: build:
@ -64,12 +55,3 @@ services:
condition: service_completed_successfully condition: service_completed_successfully
ports: ports:
- "8002:8000" - "8002:8000"
logging:
driver: json-file
options:
max-size: "20m"
max-file: "5"
tag: "search-service"
labels: "service"
labels:
- "service=search-service"

View file

@ -1,179 +0,0 @@
#!/usr/bin/env python3
"""
CLI tool to query and analyze Docker logs from index-service and search-service.
Usage:
python3 analyze.py # tail both services, live
python3 analyze.py --service search # filter by service
python3 analyze.py --level ERROR # filter by log level
python3 analyze.py --grep "qdrant" # grep in log message
python3 analyze.py --last 100 # last N lines per service
python3 analyze.py --since 10m # since N minutes/hours ago (e.g. 10m, 2h)
python3 analyze.py --stats # show request count / error rate summary
"""
import argparse
import json
import re
import subprocess
import sys
from datetime import datetime, timezone
SERVICES = {
"index": "hackaton-index-1",
"search": "hackaton-search-1",
}
def _run(cmd: list[str], **kwargs) -> subprocess.CompletedProcess:
return subprocess.run(cmd, capture_output=True, text=True, **kwargs)
def _detect_container_name(service: str) -> str:
"""Find the actual running container name for a service."""
candidates = [
f"hackaton-{service}-1",
f"hackaton_{service}_1",
f"{service}-1",
f"{service}_1",
]
result = _run(["docker", "ps", "--format", "{{.Names}}"])
running = result.stdout.splitlines()
for name in candidates:
if name in running:
return name
# fallback: try matching by label
result2 = _run(
["docker", "ps", "--filter", f"label=service={service}-service", "--format", "{{.Names}}"]
)
names = result2.stdout.strip().splitlines()
if names:
return names[0]
return candidates[0]
def _docker_logs(container: str, since: str | None, last: int) -> list[str]:
cmd = ["docker", "logs", "--timestamps"]
if since:
cmd += ["--since", since]
if last:
cmd += ["--tail", str(last)]
cmd.append(container)
result = _run(cmd)
lines = (result.stdout + result.stderr).splitlines()
return lines
def _parse_line(raw: str) -> dict:
"""Try to extract structured fields from a log line."""
# Docker prepends an RFC3339 timestamp
ts_match = re.match(r"^(\d{4}-\d{2}-\d{2}T[\d:.+Z-]+)\s+(.*)", raw)
ts = ""
message = raw
if ts_match:
ts = ts_match.group(1)
message = ts_match.group(2)
level = "INFO"
for lvl in ("CRITICAL", "ERROR", "WARNING", "WARN", "INFO", "DEBUG"):
if lvl in message.upper():
level = lvl if lvl != "WARN" else "WARNING"
break
return {"ts": ts, "level": level, "message": message, "raw": raw}
def _color(level: str) -> str:
return {
"ERROR": "\033[31m",
"CRITICAL": "\033[35m",
"WARNING": "\033[33m",
"INFO": "\033[0m",
"DEBUG": "\033[36m",
}.get(level, "\033[0m")
RESET = "\033[0m"
def cmd_tail(args: argparse.Namespace) -> None:
services = [args.service] if args.service else list(SERVICES.keys())
for svc in services:
container = _detect_container_name(svc)
lines = _docker_logs(container, args.since, args.last)
print(f"\n{'='*60}")
print(f" {svc.upper()} SERVICE ({container})")
print(f"{'='*60}")
count = 0
for raw in lines:
parsed = _parse_line(raw)
if args.level and parsed["level"] != args.level.upper():
continue
if args.grep and args.grep.lower() not in parsed["message"].lower():
continue
color = _color(parsed["level"])
print(f"{color}{parsed['raw']}{RESET}")
count += 1
print(f"{count} lines shown")
def cmd_stats(args: argparse.Namespace) -> None:
services = [args.service] if args.service else list(SERVICES.keys())
for svc in services:
container = _detect_container_name(svc)
lines = _docker_logs(container, args.since, args.last)
counts: dict[str, int] = {"ERROR": 0, "WARNING": 0, "INFO": 0, "DEBUG": 0, "CRITICAL": 0}
requests = 0
errors_5xx = 0
for raw in lines:
parsed = _parse_line(raw)
lvl = parsed["level"]
counts[lvl] = counts.get(lvl, 0) + 1
msg = parsed["message"]
if re.search(r'"(GET|POST|PUT|DELETE|PATCH)\s', msg):
requests += 1
if re.search(r'" 5\d\d ', msg):
errors_5xx += 1
print(f"\n{'='*50}")
print(f" STATS: {svc.upper()} SERVICE")
print(f"{'='*50}")
print(f" Total lines : {sum(counts.values())}")
print(f" HTTP requests: {requests}")
print(f" 5xx errors : {errors_5xx}")
print(f" ERROR lines : {counts['ERROR']}")
print(f" WARNING lines: {counts['WARNING']}")
print(f" INFO lines : {counts['INFO']}")
def main() -> None:
parser = argparse.ArgumentParser(
description="Analyze Docker logs for index-service and search-service",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog=__doc__,
)
parser.add_argument("--service", choices=list(SERVICES.keys()), help="Filter by service")
parser.add_argument("--level", help="Filter by log level (ERROR, WARNING, INFO, DEBUG)")
parser.add_argument("--grep", help="Substring filter on log message")
parser.add_argument("--last", type=int, default=200, help="Last N lines per service (default 200)")
parser.add_argument("--since", help="Show logs since duration (e.g. 10m, 2h, 30s)")
parser.add_argument("--stats", action="store_true", help="Show stats summary instead of log lines")
args = parser.parse_args()
try:
if args.stats:
cmd_stats(args)
else:
cmd_tail(args)
except KeyboardInterrupt:
print("\nInterrupted.")
except FileNotFoundError:
print("ERROR: docker not found in PATH", file=sys.stderr)
sys.exit(1)
if __name__ == "__main__":
main()

View file

@ -1,12 +0,0 @@
services:
dozzle:
image: amir20/dozzle:latest
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
ports:
- "9999:8080"
environment:
DOZZLE_FILTER: "label=service"
DOZZLE_LEVEL: info
DOZZLE_ENABLE_ACTIONS: "false"
restart: unless-stopped