Import AITURK IDE 1.0.0-beta.1 from Hermes 63279301; preserve MIT license
This commit is contained in:
@@ -0,0 +1,92 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Exercise Gateway Health & Diagnostics Export against a local OTLP capture collector."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
import tempfile
|
||||
import time
|
||||
from pathlib import Path
|
||||
|
||||
REPO_ROOT = Path(__file__).resolve().parents[2]
|
||||
if str(REPO_ROOT) not in sys.path:
|
||||
sys.path.insert(0, str(REPO_ROOT))
|
||||
|
||||
|
||||
def main() -> None:
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--endpoint", default="http://127.0.0.1:4318/v1/traces")
|
||||
parser.add_argument("--log", required=True, help="JSONL file written by otel_capture_collector.py")
|
||||
parser.add_argument("--wait", type=float, default=7.0)
|
||||
args = parser.parse_args()
|
||||
|
||||
hermes_home = Path(tempfile.mkdtemp(prefix="hermes-otel-smoke-"))
|
||||
os.environ["HERMES_HOME"] = str(hermes_home)
|
||||
|
||||
from gateway.status import write_runtime_status
|
||||
from agent.monitoring.gateway_health_export import start_gateway_health_export
|
||||
from agent.monitoring import emitter
|
||||
|
||||
config = {
|
||||
"monitoring": {
|
||||
"local": True,
|
||||
"gateway_health_export": {
|
||||
"enabled": True,
|
||||
"metrics_enabled": True,
|
||||
"diagnostic_events_enabled": True,
|
||||
"warning_error_events_enabled": True,
|
||||
"export_interval_seconds": 5,
|
||||
"logs_export_interval_seconds": 5,
|
||||
"resource_attributes": {
|
||||
"service.name": "hermes-gateway-smoke",
|
||||
"deployment.environment.name": "local-smoke",
|
||||
},
|
||||
},
|
||||
"export": {
|
||||
"otlp": {
|
||||
"enabled": True,
|
||||
"endpoint": args.endpoint,
|
||||
"headers_env": {},
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
runtime = start_gateway_health_export(config)
|
||||
if not runtime.enabled:
|
||||
raise SystemExit(f"gateway health exporter did not enable: {runtime.reason}")
|
||||
|
||||
write_runtime_status(gateway_state="starting", active_agents=0)
|
||||
write_runtime_status(gateway_state="running", active_agents=2)
|
||||
write_runtime_status(platform="slack", platform_state="running")
|
||||
write_runtime_status(
|
||||
platform="slack",
|
||||
platform_state="fatal",
|
||||
error_code="auth_failed",
|
||||
error_message="Bearer *** rejected for smoke@example.com",
|
||||
)
|
||||
logging.getLogger("gateway.platforms.slack").warning("Slack token *** rejected for smoke@example.com")
|
||||
emitter.get_emitter().flush(timeout=2.0)
|
||||
time.sleep(args.wait)
|
||||
write_runtime_status(gateway_state="stopped", active_agents=0)
|
||||
runtime.shutdown()
|
||||
emitter.get_emitter().flush(timeout=2.0)
|
||||
|
||||
log_path = Path(args.log)
|
||||
rows = [json.loads(line) for line in log_path.read_text(encoding="utf-8").splitlines() if line.strip()]
|
||||
paths = {row["path"] for row in rows}
|
||||
print(json.dumps({"hermes_home": str(hermes_home), "requests": len(rows), "paths": sorted(paths)}, indent=2))
|
||||
if "/v1/traces" not in paths:
|
||||
raise SystemExit("missing /v1/traces request")
|
||||
if "/v1/logs" not in paths:
|
||||
raise SystemExit("missing /v1/logs request")
|
||||
if "/v1/metrics" not in paths:
|
||||
raise SystemExit("missing /v1/metrics request")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,59 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Tiny local OTLP/HTTP capture collector for Hermes gateway health smoke tests.
|
||||
|
||||
This is not a production collector. It accepts OTLP protobuf POSTs on /v1/traces,
|
||||
/v1/metrics, and /v1/logs, records request metadata as JSONL, and returns 200 so
|
||||
local exporters can be exercised without Docker or a vendor backend.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import time
|
||||
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
class CaptureHandler(BaseHTTPRequestHandler):
|
||||
log_path: Path
|
||||
|
||||
def do_POST(self) -> None: # noqa: N802 - BaseHTTPRequestHandler API
|
||||
length = int(self.headers.get("content-length") or 0)
|
||||
body = self.rfile.read(length) if length else b""
|
||||
record = {
|
||||
"ts": time.time(),
|
||||
"path": self.path,
|
||||
"content_type": self.headers.get("content-type"),
|
||||
"content_length": length,
|
||||
"body_prefix_hex": body[:24].hex(),
|
||||
}
|
||||
with self.log_path.open("a", encoding="utf-8") as fh:
|
||||
fh.write(json.dumps(record, sort_keys=True) + "\n")
|
||||
self.send_response(200)
|
||||
self.end_headers()
|
||||
self.wfile.write(b"{}")
|
||||
|
||||
def log_message(self, format: str, *args) -> None:
|
||||
# Keep tmux panes clean; JSONL file is the assertion surface.
|
||||
return
|
||||
|
||||
|
||||
def main() -> None:
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--host", default="127.0.0.1")
|
||||
parser.add_argument("--port", type=int, default=4318)
|
||||
parser.add_argument("--log", required=True)
|
||||
args = parser.parse_args()
|
||||
|
||||
log_path = Path(args.log).expanduser().resolve()
|
||||
log_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
log_path.write_text("", encoding="utf-8")
|
||||
CaptureHandler.log_path = log_path
|
||||
server = ThreadingHTTPServer((args.host, args.port), CaptureHandler)
|
||||
print(f"OTLP capture collector listening on http://{args.host}:{args.port}; log={log_path}", flush=True)
|
||||
server.serve_forever()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user