chore: 更新公共镜像至 1.5.43
This commit is contained in:
+164
-1
@@ -978,6 +978,83 @@ def cmd_awr_download(client_code: str, date: str, output_path: str = "", as_json
|
||||
print(f"Size: {result['size']} bytes")
|
||||
|
||||
|
||||
def _log_client_code(client_code: str = "") -> str:
|
||||
cfg = get_config() or {}
|
||||
return (client_code or cfg.get("client_code") or cfg.get("server_id") or "").strip()
|
||||
|
||||
|
||||
def _log_api(endpoint: str, payload: Dict[str, Any], timeout: int = 120) -> Dict[str, Any]:
|
||||
cfg = get_config() or {}
|
||||
if not ensure_logged_in(cfg):
|
||||
return {"success": False, "error": "login required", "error_code": "login_required"}
|
||||
client_code = _log_client_code(str(payload.get("client_code") or ""))
|
||||
if not client_code:
|
||||
return {"success": False, "error": "clientCode is required", "error_code": "invalid_request"}
|
||||
body = dict(payload)
|
||||
body["client_code"] = client_code
|
||||
body["timeout"] = max(1, min(int(timeout or 120), 300))
|
||||
try:
|
||||
resp = requests.post(
|
||||
f"{str(cfg.get('transit_url') or TRANSIT_URL).rstrip('/')}/api/log/{endpoint}",
|
||||
json=body,
|
||||
headers=make_headers(),
|
||||
timeout=body["timeout"] + 5,
|
||||
)
|
||||
try:
|
||||
result = resp.json()
|
||||
except Exception:
|
||||
result = {"success": False, "error": resp.text or f"HTTP {resp.status_code}"}
|
||||
if not resp.ok:
|
||||
result.setdefault("success", False)
|
||||
result.setdefault("status_code", resp.status_code)
|
||||
return result
|
||||
except requests.exceptions.RequestException as e:
|
||||
return {"success": False, "error": str(e), "error_code": "request_failed"}
|
||||
|
||||
|
||||
def log_info(path: str, client_code: str = "", timeout: int = 120) -> Dict[str, Any]:
|
||||
return _log_api("info", {"client_code": client_code, "path": path}, timeout)
|
||||
|
||||
|
||||
def log_tail(path: str, client_code: str = "", lines: int = 200,
|
||||
max_bytes: int = 256 * 1024, timeout: int = 120) -> Dict[str, Any]:
|
||||
return _log_api("tail", {
|
||||
"client_code": client_code, "path": path, "lines": lines, "max_bytes": max_bytes,
|
||||
}, timeout)
|
||||
|
||||
|
||||
def log_search(path: str, patterns: List[str], client_code: str = "", regex: bool = False,
|
||||
case_sensitive: bool = False, before_lines: int = 3, after_lines: int = 3,
|
||||
max_matches: int = 100, scan_scope: str = "recent",
|
||||
recent_bytes: int = 100 * 1024 * 1024, timeout: int = 120) -> Dict[str, Any]:
|
||||
return _log_api("search", {
|
||||
"client_code": client_code, "path": path, "patterns": patterns, "regex": regex,
|
||||
"case_sensitive": case_sensitive, "before_lines": before_lines, "after_lines": after_lines,
|
||||
"max_matches": max_matches, "scan_scope": scan_scope, "recent_bytes": recent_bytes,
|
||||
}, timeout)
|
||||
|
||||
|
||||
def set_log_analysis_enabled(enabled: bool, client_code: str = "", timeout: int = 30) -> Dict[str, Any]:
|
||||
return _log_api("config", {"client_code": client_code, "enabled": bool(enabled)}, timeout)
|
||||
|
||||
|
||||
def _print_log_result(result: Dict[str, Any], as_json: bool = False):
|
||||
if as_json or not result.get("success"):
|
||||
print(json.dumps(result, ensure_ascii=False, indent=2))
|
||||
return
|
||||
data = result.get("data") or {}
|
||||
if isinstance(data.get("lines"), list):
|
||||
for entry in data["lines"]:
|
||||
if isinstance(entry, dict):
|
||||
marker = ">" if entry.get("match") else " "
|
||||
print(f"{marker} {entry.get('scan_line', '-')}: {entry.get('text', '')}")
|
||||
else:
|
||||
print(entry)
|
||||
print(f"matches={data.get('matches', '-')} complete={data.get('complete', True)} stop_reason={data.get('stop_reason', '')}")
|
||||
else:
|
||||
print(json.dumps(data, ensure_ascii=False, indent=2))
|
||||
|
||||
|
||||
def _inspection_report_payload(result: Dict[str, Any]) -> Dict[str, Any]:
|
||||
data = result.get("data") or {}
|
||||
if isinstance(data, dict) and data.get("report_json"):
|
||||
@@ -3351,6 +3428,45 @@ def cmd_capabilities(args):
|
||||
"required": []
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "log_info",
|
||||
"description": "Validate one absolute server log path and return bounded file metadata without Oracle access.",
|
||||
"parameters": {"type": "object", "properties": {
|
||||
"path": {"type": "string", "description": "Absolute log file path on the target server."},
|
||||
"clientCode": {"type": "string", "description": "Optional client/server code."}
|
||||
}, "required": ["path"]}
|
||||
},
|
||||
{
|
||||
"name": "log_tail",
|
||||
"description": "Read a bounded tail from one server log file.",
|
||||
"parameters": {"type": "object", "properties": {
|
||||
"path": {"type": "string"}, "clientCode": {"type": "string"},
|
||||
"lines": {"type": "integer", "description": "Default 200, maximum 2000."},
|
||||
"maxBytes": {"type": "integer", "description": "Default 262144, maximum 1048576."}
|
||||
}, "required": ["path"]}
|
||||
},
|
||||
{
|
||||
"name": "log_search",
|
||||
"description": "Stream-search a server log with keywords or RE2 regular expressions and bounded context.",
|
||||
"parameters": {"type": "object", "properties": {
|
||||
"path": {"type": "string"}, "patterns": {"type": "array", "items": {"type": "string"}},
|
||||
"clientCode": {"type": "string"}, "regex": {"type": "boolean"},
|
||||
"caseSensitive": {"type": "boolean"}, "beforeLines": {"type": "integer"},
|
||||
"afterLines": {"type": "integer"}, "maxMatches": {"type": "integer"},
|
||||
"scanScope": {"type": "string", "enum": ["recent", "full"]},
|
||||
"recentBytes": {"type": "integer"}, "timeout": {"type": "integer"}
|
||||
}, "required": ["path", "patterns"]}
|
||||
},
|
||||
{
|
||||
"name": "log_enable",
|
||||
"description": "Enable persisted log analysis for an authorized client.",
|
||||
"parameters": {"type": "object", "properties": {"clientCode": {"type": "string"}}, "required": []}
|
||||
},
|
||||
{
|
||||
"name": "log_disable",
|
||||
"description": "Disable persisted log analysis for an authorized client.",
|
||||
"parameters": {"type": "object", "properties": {"clientCode": {"type": "string"}}, "required": []}
|
||||
},
|
||||
{
|
||||
"name": "awr_list",
|
||||
"description": "List AWR reports already generated and stored by the target Agent.",
|
||||
@@ -3419,7 +3535,7 @@ def cmd_capabilities(args):
|
||||
"analyze", "list", "source", "describe",
|
||||
"search", "query", "discover", "nl2sql",
|
||||
"perm", "qperm", "login", "logout",
|
||||
"status", "switch", "clients", "device_register", "device_login", "ops", "ops_report", "inspection_report", "inspection_latest", "inspection_get", "awr_status", "awr_list", "awr_download", "agent_update", "capabilities"
|
||||
"status", "switch", "clients", "device_register", "device_login", "ops", "ops_report", "inspection_report", "inspection_latest", "inspection_get", "awr_status", "awr_list", "awr_download", "log_info", "log_tail", "log_search", "log_enable", "log_disable", "agent_update", "capabilities"
|
||||
],
|
||||
"python_version": "3.6+",
|
||||
"dependencies": ["requests"]
|
||||
@@ -3612,6 +3728,53 @@ def main():
|
||||
output_path = sys.argv[output_index + 1]
|
||||
cmd_awr_download(sys.argv[2], sys.argv[3], output_path=output_path, as_json="--json" in sys.argv[4:])
|
||||
|
||||
elif cmd == "log_info":
|
||||
parser = argparse.ArgumentParser(prog="oracle_skill.py log_info")
|
||||
parser.add_argument("path")
|
||||
parser.add_argument("--client", default="")
|
||||
parser.add_argument("--timeout", type=int, default=120)
|
||||
parser.add_argument("--json", action="store_true")
|
||||
args = parser.parse_args(sys.argv[2:])
|
||||
_print_log_result(log_info(args.path, args.client, args.timeout), args.json)
|
||||
|
||||
elif cmd == "log_tail":
|
||||
parser = argparse.ArgumentParser(prog="oracle_skill.py log_tail")
|
||||
parser.add_argument("path")
|
||||
parser.add_argument("--client", default="")
|
||||
parser.add_argument("--lines", type=int, default=200)
|
||||
parser.add_argument("--max-bytes", type=int, default=256 * 1024)
|
||||
parser.add_argument("--timeout", type=int, default=120)
|
||||
parser.add_argument("--json", action="store_true")
|
||||
args = parser.parse_args(sys.argv[2:])
|
||||
_print_log_result(log_tail(args.path, args.client, args.lines, args.max_bytes, args.timeout), args.json)
|
||||
|
||||
elif cmd == "log_search":
|
||||
parser = argparse.ArgumentParser(prog="oracle_skill.py log_search")
|
||||
parser.add_argument("path")
|
||||
parser.add_argument("patterns", nargs="+")
|
||||
parser.add_argument("--client", default="")
|
||||
parser.add_argument("--regex", action="store_true")
|
||||
parser.add_argument("--case-sensitive", action="store_true")
|
||||
parser.add_argument("--before", type=int, default=3)
|
||||
parser.add_argument("--after", type=int, default=3)
|
||||
parser.add_argument("--max-matches", type=int, default=100)
|
||||
parser.add_argument("--scope", choices=("recent", "full"), default="recent")
|
||||
parser.add_argument("--recent-bytes", type=int, default=100 * 1024 * 1024)
|
||||
parser.add_argument("--timeout", type=int, default=120)
|
||||
parser.add_argument("--json", action="store_true")
|
||||
args = parser.parse_args(sys.argv[2:])
|
||||
_print_log_result(log_search(
|
||||
args.path, args.patterns, args.client, args.regex, args.case_sensitive,
|
||||
args.before, args.after, args.max_matches, args.scope, args.recent_bytes, args.timeout,
|
||||
), args.json)
|
||||
|
||||
elif cmd in ("log_enable", "log_disable"):
|
||||
parser = argparse.ArgumentParser(prog=f"oracle_skill.py {cmd}")
|
||||
parser.add_argument("client", nargs="?", default="")
|
||||
parser.add_argument("--json", action="store_true")
|
||||
args = parser.parse_args(sys.argv[2:])
|
||||
_print_log_result(set_log_analysis_enabled(cmd == "log_enable", args.client), args.json)
|
||||
|
||||
elif cmd == "agent_update":
|
||||
timeout = int(sys.argv[3]) if len(sys.argv) >= 4 and sys.argv[3].isdigit() else 300
|
||||
cmd_agent_update(sys.argv[2] if len(sys.argv) >= 3 else "", timeout)
|
||||
|
||||
Reference in New Issue
Block a user