release: bump version to 0.62.0
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import shutil
|
||||
import subprocess
|
||||
@@ -86,6 +87,7 @@ class LogSource:
|
||||
status: str = "ok"
|
||||
buffer_key: str | None = None
|
||||
container_name: str | None = None
|
||||
fallback_locations: tuple[str, ...] = ()
|
||||
|
||||
|
||||
@dataclass
|
||||
@@ -104,22 +106,38 @@ class DailyLogMarker:
|
||||
dominant_level: str
|
||||
|
||||
|
||||
def _planet_state_dir() -> Path:
|
||||
configured = os.getenv("PLANET_STATE_DIR")
|
||||
if configured:
|
||||
return Path(configured).expanduser()
|
||||
xdg_state = os.getenv("XDG_STATE_HOME")
|
||||
if xdg_state:
|
||||
return Path(xdg_state).expanduser() / "planet"
|
||||
return Path.home() / ".local" / "state" / "planet"
|
||||
|
||||
|
||||
def _state_log_path(filename: str) -> str:
|
||||
return str(_planet_state_dir() / filename)
|
||||
|
||||
|
||||
LOG_SOURCES: dict[str, LogSource] = {
|
||||
"backend": LogSource(
|
||||
source_id="backend",
|
||||
name="后端服务",
|
||||
kind="file",
|
||||
location="/tmp/planet_backend.log",
|
||||
location=_state_log_path("backend.log"),
|
||||
description="FastAPI 后端、调度器和采集任务共享日志。",
|
||||
category="service",
|
||||
fallback_locations=("/tmp/planet_backend.log",),
|
||||
),
|
||||
"frontend": LogSource(
|
||||
source_id="frontend",
|
||||
name="前端开发服务",
|
||||
kind="file",
|
||||
location="/tmp/planet_frontend.log",
|
||||
location=_state_log_path("frontend.log"),
|
||||
description="控制台与 Earth 前端开发服务输出。",
|
||||
category="service",
|
||||
fallback_locations=("/tmp/planet_frontend.log",),
|
||||
),
|
||||
"ai-provider": LogSource(
|
||||
source_id="ai-provider",
|
||||
@@ -164,9 +182,18 @@ def normalize_log_levels(level: str | None = None, levels: str | None = None) ->
|
||||
return tuple(normalized_levels)
|
||||
|
||||
|
||||
def resolve_file_log_path(source: LogSource) -> Path:
|
||||
primary = Path(source.location).expanduser()
|
||||
candidates = (primary, *(Path(item).expanduser() for item in source.fallback_locations))
|
||||
for candidate in candidates:
|
||||
if candidate.exists():
|
||||
return candidate
|
||||
return primary
|
||||
|
||||
|
||||
def get_source_status(source: LogSource) -> str:
|
||||
if source.kind == "file":
|
||||
path = Path(source.location)
|
||||
path = resolve_file_log_path(source)
|
||||
if not path.exists():
|
||||
return "missing"
|
||||
return "ok" if path.stat().st_size > 0 else "empty"
|
||||
@@ -190,7 +217,7 @@ def list_log_sources() -> list[dict[str, str]]:
|
||||
"source_id": source.source_id,
|
||||
"name": source.name,
|
||||
"kind": source.kind,
|
||||
"location": source.location,
|
||||
"location": str(resolve_file_log_path(source)) if source.kind == "file" else source.location,
|
||||
"description": source.description,
|
||||
"category": source.category,
|
||||
"status": get_source_status(source),
|
||||
@@ -339,7 +366,7 @@ def build_buffer_entry(payload: dict[str, Any]) -> StructuredLogEntry:
|
||||
|
||||
|
||||
def read_file_entries(source: LogSource, scan_limit: int) -> list[StructuredLogEntry]:
|
||||
path = Path(source.location)
|
||||
path = resolve_file_log_path(source)
|
||||
if not path.exists():
|
||||
return []
|
||||
with path.open("r", encoding="utf-8", errors="replace") as handle:
|
||||
@@ -511,7 +538,7 @@ def read_log_snapshot(
|
||||
"source_id": source.source_id,
|
||||
"name": source.name,
|
||||
"kind": source.kind,
|
||||
"location": source.location,
|
||||
"location": str(resolve_file_log_path(source)) if source.kind == "file" else source.location,
|
||||
"description": source.description,
|
||||
"category": source.category,
|
||||
"status": get_source_status(source),
|
||||
|
||||
Reference in New Issue
Block a user