221 lines
6.0 KiB
Python
221 lines
6.0 KiB
Python
"""
|
|
KIMS API 로깅 모듈
|
|
- API 호출/응답 SQLite 저장
|
|
- AI 학습용 데이터 수집
|
|
"""
|
|
import sqlite3
|
|
import json
|
|
import os
|
|
from datetime import datetime
|
|
from pathlib import Path
|
|
|
|
# DB 파일 경로
|
|
DB_PATH = Path(__file__).parent / 'kims_logs.db'
|
|
|
|
def init_db():
|
|
"""DB 초기화 (테이블 생성)"""
|
|
schema_path = Path(__file__).parent / 'kims_logs_schema.sql'
|
|
|
|
conn = sqlite3.connect(str(DB_PATH))
|
|
cursor = conn.cursor()
|
|
|
|
with open(schema_path, 'r', encoding='utf-8') as f:
|
|
schema = f.read()
|
|
cursor.executescript(schema)
|
|
|
|
conn.commit()
|
|
conn.close()
|
|
print(f"KIMS 로그 DB 초기화 완료: {DB_PATH}")
|
|
|
|
def log_kims_call(
|
|
pre_serial: str = None,
|
|
user_id: int = None,
|
|
source: str = 'admin',
|
|
drug_codes: list = None,
|
|
drug_names: list = None,
|
|
api_status: str = 'SUCCESS',
|
|
http_status: int = 200,
|
|
response_time_ms: int = 0,
|
|
interactions: list = None,
|
|
response_raw: dict = None,
|
|
error_message: str = None
|
|
) -> int:
|
|
"""
|
|
KIMS API 호출 로그 저장
|
|
|
|
Returns:
|
|
log_id: 생성된 로그 ID
|
|
"""
|
|
# DB 없으면 초기화
|
|
if not DB_PATH.exists():
|
|
init_db()
|
|
|
|
conn = sqlite3.connect(str(DB_PATH))
|
|
cursor = conn.cursor()
|
|
|
|
interactions = interactions or []
|
|
drug_codes = drug_codes or []
|
|
drug_names = drug_names or []
|
|
|
|
# 심각한 상호작용 여부 (severity 1 또는 2)
|
|
has_severe = any(
|
|
str(i.get('severity', '5')) in ['1', '2']
|
|
for i in interactions
|
|
)
|
|
|
|
# 메인 로그 삽입
|
|
cursor.execute("""
|
|
INSERT INTO kims_api_logs (
|
|
pre_serial, user_id, source,
|
|
request_drug_codes, request_drug_names, request_drug_count,
|
|
api_status, http_status, response_time_ms,
|
|
interaction_count, has_severe_interaction,
|
|
interactions_json, response_raw, error_message
|
|
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
""", (
|
|
pre_serial,
|
|
user_id,
|
|
source,
|
|
json.dumps(drug_codes, ensure_ascii=False),
|
|
json.dumps(drug_names, ensure_ascii=False),
|
|
len(drug_codes),
|
|
api_status,
|
|
http_status,
|
|
response_time_ms,
|
|
len(interactions),
|
|
1 if has_severe else 0,
|
|
json.dumps(interactions, ensure_ascii=False),
|
|
json.dumps(response_raw, ensure_ascii=False) if response_raw else None,
|
|
error_message
|
|
))
|
|
|
|
log_id = cursor.lastrowid
|
|
|
|
# 상호작용 상세 삽입 (정규화)
|
|
for inter in interactions:
|
|
cursor.execute("""
|
|
INSERT INTO kims_interactions (
|
|
log_id,
|
|
drug1_code, drug1_name, drug1_generic,
|
|
drug2_code, drug2_name, drug2_generic,
|
|
severity_level, severity_desc,
|
|
likelihood_level, likelihood_desc,
|
|
observation, observation_generic,
|
|
clinical_management, action_to_take, reference
|
|
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
""", (
|
|
log_id,
|
|
inter.get('drug1_code'),
|
|
inter.get('drug1_name'),
|
|
inter.get('generic1'),
|
|
inter.get('drug2_code'),
|
|
inter.get('drug2_name'),
|
|
inter.get('generic2'),
|
|
int(inter.get('severity', 5)) if str(inter.get('severity', '')).isdigit() else None,
|
|
inter.get('severity_text'),
|
|
None, # likelihood_level
|
|
inter.get('likelihood'),
|
|
inter.get('description'),
|
|
None, # observation_generic
|
|
inter.get('management'),
|
|
inter.get('action'),
|
|
None # reference
|
|
))
|
|
|
|
conn.commit()
|
|
conn.close()
|
|
|
|
return log_id
|
|
|
|
def get_recent_logs(limit: int = 50):
|
|
"""최근 로그 조회"""
|
|
if not DB_PATH.exists():
|
|
return []
|
|
|
|
conn = sqlite3.connect(str(DB_PATH))
|
|
conn.row_factory = sqlite3.Row
|
|
cursor = conn.cursor()
|
|
|
|
cursor.execute("""
|
|
SELECT * FROM kims_api_logs
|
|
ORDER BY created_at DESC
|
|
LIMIT ?
|
|
""", (limit,))
|
|
|
|
rows = cursor.fetchall()
|
|
conn.close()
|
|
|
|
return [dict(row) for row in rows]
|
|
|
|
def get_log_detail(log_id: int):
|
|
"""로그 상세 조회 (상호작용 포함)"""
|
|
if not DB_PATH.exists():
|
|
return None
|
|
|
|
conn = sqlite3.connect(str(DB_PATH))
|
|
conn.row_factory = sqlite3.Row
|
|
cursor = conn.cursor()
|
|
|
|
# 메인 로그
|
|
cursor.execute("SELECT * FROM kims_api_logs WHERE id = ?", (log_id,))
|
|
log = cursor.fetchone()
|
|
|
|
if not log:
|
|
conn.close()
|
|
return None
|
|
|
|
# 상호작용 상세
|
|
cursor.execute("""
|
|
SELECT * FROM kims_interactions
|
|
WHERE log_id = ?
|
|
ORDER BY severity_level ASC
|
|
""", (log_id,))
|
|
interactions = cursor.fetchall()
|
|
|
|
conn.close()
|
|
|
|
result = dict(log)
|
|
result['interactions_detail'] = [dict(i) for i in interactions]
|
|
|
|
return result
|
|
|
|
def get_stats():
|
|
"""통계 조회"""
|
|
if not DB_PATH.exists():
|
|
return {}
|
|
|
|
conn = sqlite3.connect(str(DB_PATH))
|
|
conn.row_factory = sqlite3.Row
|
|
cursor = conn.cursor()
|
|
|
|
# 전체 통계
|
|
cursor.execute("""
|
|
SELECT
|
|
COUNT(*) as total_calls,
|
|
SUM(CASE WHEN api_status = 'SUCCESS' THEN 1 ELSE 0 END) as success_count,
|
|
SUM(CASE WHEN interaction_count > 0 THEN 1 ELSE 0 END) as with_interaction,
|
|
SUM(CASE WHEN has_severe_interaction = 1 THEN 1 ELSE 0 END) as with_severe,
|
|
AVG(response_time_ms) as avg_response_ms
|
|
FROM kims_api_logs
|
|
""")
|
|
stats = dict(cursor.fetchone())
|
|
|
|
# 최근 7일 일별 통계
|
|
cursor.execute("""
|
|
SELECT * FROM kims_stats
|
|
ORDER BY date DESC
|
|
LIMIT 7
|
|
""")
|
|
daily = [dict(row) for row in cursor.fetchall()]
|
|
|
|
conn.close()
|
|
|
|
stats['daily'] = daily
|
|
return stats
|
|
|
|
|
|
if __name__ == '__main__':
|
|
# DB 초기화 테스트
|
|
init_db()
|
|
print("KIMS 로그 DB 초기화 완료!")
|