candyhead commited on
Commit
ed6f503
·
verified ·
1 Parent(s): adcbdb9

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +58 -0
app.py ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import asyncio
2
+ import json
3
+ from datetime import datetime
4
+ from fastapi import FastAPI, Request
5
+ from fastapi.responses import StreamingResponse
6
+ from pydantic import BaseModel
7
+
8
+ app = FastAPI(title="HF Log Streams Service")
9
+
10
+ # 全局广播队列(支持无限多客户端同时订阅)
11
+ log_queue: asyncio.Queue = asyncio.Queue()
12
+
13
+ class LogEntry(BaseModel):
14
+ level: str = "info"
15
+ message: str
16
+ source: str = "external"
17
+ extra: dict | None = None
18
+
19
+ @app.post("/ingest")
20
+ async def ingest_log(log: LogEntry):
21
+ timestamp = datetime.now().isoformat()
22
+ entry = {
23
+ "timestamp": timestamp,
24
+ "level": log.level.upper(),
25
+ "message": log.message,
26
+ "source": log.source,
27
+ "extra": log.extra or {}
28
+ }
29
+
30
+ # 1. 自动出现在 Space 官方 Logs(实时可见)
31
+ print(f"[{timestamp}] [{entry['level']}] {log.message} | source={log.source}")
32
+
33
+ # 2. 广播给所有 SSE 订阅者
34
+ await log_queue.put(entry)
35
+
36
+ return {"status": "ok", "timestamp": timestamp}
37
+
38
+ @app.get("/stream")
39
+ async def stream_logs(request: Request):
40
+ async def event_generator():
41
+ while True:
42
+ if await request.is_disconnected():
43
+ break
44
+ try:
45
+ log_entry = await asyncio.wait_for(log_queue.get(), timeout=30.0)
46
+ yield f"data: {json.dumps(log_entry)}\n\n"
47
+ except asyncio.TimeoutError:
48
+ yield ": ping\n\n" # 保持连接
49
+
50
+ return StreamingResponse(
51
+ event_generator(),
52
+ media_type="text/event-stream",
53
+ headers={"Cache-Control": "no-cache", "Connection": "keep-alive"}
54
+ )
55
+
56
+ @app.get("/")
57
+ async def root():
58
+ return {"message": "Log Streams 服务已就绪!POST /ingest 写日志,GET /stream 订阅实时流"}