51 lines
1.5 KiB
Python
51 lines
1.5 KiB
Python
"""运行状态 + 统一日志源。
|
||
|
||
日志只有一个出口 log():
|
||
* 控制台:带上时间/级别/key,docker compose logs 也能看
|
||
* 内存:RUNS[key]["log"],/api/log 供前端轮询
|
||
* SQLite:store.run_log_add,/api/log/history 重启后还能查
|
||
新代码不要再自己 print(),也不要直接写 run_log 表。
|
||
"""
|
||
import threading
|
||
import time
|
||
|
||
from study_tool import store
|
||
|
||
RUNS = {}
|
||
RUNS_LOCK = threading.Lock()
|
||
MAX_LINES = 1000 # 每个 key 内存里最多留 1000 行
|
||
TRIM_LINES = 300 # 超了先丢最旧的 300 行
|
||
|
||
|
||
def log(key, msg, level="info", persist=True):
|
||
"""写一条日志,返回拼好的整行。"""
|
||
key = key or "system"
|
||
line = "%s [%s] %s" % (time.strftime("%Y-%m-%d %H:%M:%S"), level, msg)
|
||
try:
|
||
print("%s [%s]" % (line, key), flush=True)
|
||
except UnicodeEncodeError: # Windows 控制台 GBK 编不了 ⚠ 之类
|
||
print(("%s [%s]" % (line, key)).encode("gbk", "replace").decode("gbk"), flush=True)
|
||
with RUNS_LOCK:
|
||
st = RUNS.setdefault(key, {})
|
||
logs = st.setdefault("log", [])
|
||
logs.append(line)
|
||
if len(logs) > MAX_LINES:
|
||
del logs[:TRIM_LINES]
|
||
st["updated"] = time.time()
|
||
if persist:
|
||
try:
|
||
store.run_log_add(key, line)
|
||
except Exception:
|
||
pass
|
||
return line
|
||
|
||
|
||
def set_state(key, **kw):
|
||
with RUNS_LOCK:
|
||
st = RUNS.setdefault(key, {})
|
||
st.update(kw)
|
||
st["updated"] = time.time()
|
||
store.run_state_set(key, RUNS.get(key) or {})
|
||
|
||
|