feat(P2): stock/music-lab/insta-lab/realestate-lab access_log 적용 + AGENT_CONTAINER_MAP 4개 매핑
This commit is contained in:
@@ -45,10 +45,9 @@ import re as _re
|
|||||||
# path_prefix_regex: lotto 컨테이너에 personal/blog/todo 도 같이 있어
|
# path_prefix_regex: lotto 컨테이너에 personal/blog/todo 도 같이 있어
|
||||||
# /api/lotto 만 골라내기 위한 정규식. business log (source='log') 는 모두 통과.
|
# /api/lotto 만 골라내기 위한 정규식. business log (source='log') 는 모두 통과.
|
||||||
AGENT_CONTAINER_MAP: dict[str, tuple[str, int, _re.Pattern]] = {
|
AGENT_CONTAINER_MAP: dict[str, tuple[str, int, _re.Pattern]] = {
|
||||||
"lotto": ("lotto", 8000, _re.compile(r"^/api/lotto")),
|
"lotto": ("lotto", 8000, _re.compile(r"^/api/lotto")),
|
||||||
# Phase 2 에서 추가:
|
"stock": ("stock", 8000, _re.compile(r"^/api/(stock|trade|portfolio)")),
|
||||||
# "stock": ("stock", 8000, _re.compile(r"^/api/(stock|trade|portfolio)")),
|
"music": ("music-lab", 8000, _re.compile(r"^/api/music")),
|
||||||
# "music": ("music-lab", 8000, _re.compile(r"^/api/music")),
|
"insta": ("insta-lab", 8000, _re.compile(r"^/api/insta")),
|
||||||
# "insta": ("insta-lab", 8000, _re.compile(r"^/api/insta")),
|
"realestate": ("realestate-lab", 8000, _re.compile(r"^/api/realestate")),
|
||||||
# "realestate": ("realestate-lab", 8000, _re.compile(r"^/api/realestate")),
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,8 +51,15 @@ services:
|
|||||||
- OLLAMA_MODEL=${OLLAMA_MODEL:-qwen3:14b}
|
- OLLAMA_MODEL=${OLLAMA_MODEL:-qwen3:14b}
|
||||||
- CORS_ALLOW_ORIGINS=${CORS_ALLOW_ORIGINS:-http://localhost:3007,http://localhost:8080}
|
- CORS_ALLOW_ORIGINS=${CORS_ALLOW_ORIGINS:-http://localhost:3007,http://localhost:8080}
|
||||||
- WEBAI_API_KEY=${WEBAI_API_KEY:-}
|
- WEBAI_API_KEY=${WEBAI_API_KEY:-}
|
||||||
|
- PYTHONPATH=/app:/shared
|
||||||
volumes:
|
volumes:
|
||||||
- ${RUNTIME_PATH}/data/stock:/app/data
|
- ${RUNTIME_PATH}/data/stock:/app/data
|
||||||
|
- ${RUNTIME_PATH}/_shared:/shared/_shared:ro
|
||||||
|
logging:
|
||||||
|
driver: "json-file"
|
||||||
|
options:
|
||||||
|
max-size: "10m"
|
||||||
|
max-file: "3"
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:8000/health')"]
|
test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:8000/health')"]
|
||||||
interval: 60s
|
interval: 60s
|
||||||
@@ -86,9 +93,16 @@ services:
|
|||||||
- REDIS_URL=${REDIS_URL:-redis://redis:6379}
|
- REDIS_URL=${REDIS_URL:-redis://redis:6379}
|
||||||
- INTERNAL_API_KEY=${INTERNAL_API_KEY:-}
|
- INTERNAL_API_KEY=${INTERNAL_API_KEY:-}
|
||||||
- MUSIC_RENDER_URL=${MUSIC_RENDER_URL:-http://192.168.45.59:18711}
|
- MUSIC_RENDER_URL=${MUSIC_RENDER_URL:-http://192.168.45.59:18711}
|
||||||
|
- PYTHONPATH=/app:/shared
|
||||||
volumes:
|
volumes:
|
||||||
- ${RUNTIME_PATH}/data/music:/app/data
|
- ${RUNTIME_PATH}/data/music:/app/data
|
||||||
- ${RUNTIME_PATH:-.}/data/videos:/app/data/videos
|
- ${RUNTIME_PATH:-.}/data/videos:/app/data/videos
|
||||||
|
- ${RUNTIME_PATH}/_shared:/shared/_shared:ro
|
||||||
|
logging:
|
||||||
|
driver: "json-file"
|
||||||
|
options:
|
||||||
|
max-size: "10m"
|
||||||
|
max-file: "3"
|
||||||
depends_on:
|
depends_on:
|
||||||
- redis
|
- redis
|
||||||
healthcheck:
|
healthcheck:
|
||||||
@@ -163,8 +177,15 @@ services:
|
|||||||
- CORS_ALLOW_ORIGINS=${CORS_ALLOW_ORIGINS:-http://localhost:3007,http://localhost:8080}
|
- CORS_ALLOW_ORIGINS=${CORS_ALLOW_ORIGINS:-http://localhost:3007,http://localhost:8080}
|
||||||
- REDIS_URL=${REDIS_URL:-redis://redis:6379}
|
- REDIS_URL=${REDIS_URL:-redis://redis:6379}
|
||||||
- INTERNAL_API_KEY=${INTERNAL_API_KEY:-}
|
- INTERNAL_API_KEY=${INTERNAL_API_KEY:-}
|
||||||
|
- PYTHONPATH=/app:/shared
|
||||||
volumes:
|
volumes:
|
||||||
- ${RUNTIME_PATH}/data/insta:/app/data
|
- ${RUNTIME_PATH}/data/insta:/app/data
|
||||||
|
- ${RUNTIME_PATH}/_shared:/shared/_shared:ro
|
||||||
|
logging:
|
||||||
|
driver: "json-file"
|
||||||
|
options:
|
||||||
|
max-size: "10m"
|
||||||
|
max-file: "3"
|
||||||
depends_on:
|
depends_on:
|
||||||
- redis
|
- redis
|
||||||
healthcheck:
|
healthcheck:
|
||||||
@@ -185,8 +206,15 @@ services:
|
|||||||
- DATA_GO_KR_API_KEY=${DATA_GO_KR_API_KEY:-}
|
- DATA_GO_KR_API_KEY=${DATA_GO_KR_API_KEY:-}
|
||||||
- CORS_ALLOW_ORIGINS=${CORS_ALLOW_ORIGINS:-http://localhost:3007,http://localhost:8080}
|
- CORS_ALLOW_ORIGINS=${CORS_ALLOW_ORIGINS:-http://localhost:3007,http://localhost:8080}
|
||||||
- AGENT_OFFICE_URL=${AGENT_OFFICE_URL:-http://agent-office:8000}
|
- AGENT_OFFICE_URL=${AGENT_OFFICE_URL:-http://agent-office:8000}
|
||||||
|
- PYTHONPATH=/app:/shared
|
||||||
volumes:
|
volumes:
|
||||||
- ${RUNTIME_PATH}/data/realestate:/app/data
|
- ${RUNTIME_PATH}/data/realestate:/app/data
|
||||||
|
- ${RUNTIME_PATH}/_shared:/shared/_shared:ro
|
||||||
|
logging:
|
||||||
|
driver: "json-file"
|
||||||
|
options:
|
||||||
|
max-size: "10m"
|
||||||
|
max-file: "3"
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:8000/health')"]
|
test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:8000/health')"]
|
||||||
interval: 60s
|
interval: 60s
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ from fastapi import FastAPI, HTTPException, BackgroundTasks, Body, Query
|
|||||||
from fastapi.middleware.cors import CORSMiddleware
|
from fastapi.middleware.cors import CORSMiddleware
|
||||||
from fastapi.responses import FileResponse
|
from fastapi.responses import FileResponse
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
|
from _shared.access_log import install as install_access_log
|
||||||
|
|
||||||
from .config import (
|
from .config import (
|
||||||
CORS_ALLOW_ORIGINS, NAVER_CLIENT_ID, ANTHROPIC_API_KEY,
|
CORS_ALLOW_ORIGINS, NAVER_CLIENT_ID, ANTHROPIC_API_KEY,
|
||||||
@@ -27,6 +28,7 @@ REDIS_URL = os.getenv("REDIS_URL", "redis://redis:6379")
|
|||||||
redis_client = aioredis.from_url(REDIS_URL, decode_responses=False)
|
redis_client = aioredis.from_url(REDIS_URL, decode_responses=False)
|
||||||
|
|
||||||
app = FastAPI()
|
app = FastAPI()
|
||||||
|
install_access_log(app)
|
||||||
app.include_router(internal_router)
|
app.include_router(internal_router)
|
||||||
|
|
||||||
app.add_middleware(
|
app.add_middleware(
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ from typing import Any, Dict, List, Optional
|
|||||||
from fastapi import FastAPI, HTTPException, BackgroundTasks, Query
|
from fastapi import FastAPI, HTTPException, BackgroundTasks, Query
|
||||||
from fastapi.middleware.cors import CORSMiddleware
|
from fastapi.middleware.cors import CORSMiddleware
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
|
from _shared.access_log import install as install_access_log
|
||||||
|
|
||||||
from .db import (
|
from .db import (
|
||||||
init_db,
|
init_db,
|
||||||
@@ -34,6 +35,7 @@ import redis.asyncio as aioredis
|
|||||||
from .internal_router import router as internal_router
|
from .internal_router import router as internal_router
|
||||||
|
|
||||||
app = FastAPI()
|
app = FastAPI()
|
||||||
|
install_access_log(app)
|
||||||
|
|
||||||
REDIS_URL = os.getenv("REDIS_URL", "redis://redis:6379")
|
REDIS_URL = os.getenv("REDIS_URL", "redis://redis:6379")
|
||||||
redis_client = aioredis.from_url(REDIS_URL, decode_responses=False)
|
redis_client = aioredis.from_url(REDIS_URL, decode_responses=False)
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ from contextlib import asynccontextmanager
|
|||||||
from fastapi import BackgroundTasks, FastAPI, Query, HTTPException
|
from fastapi import BackgroundTasks, FastAPI, Query, HTTPException
|
||||||
from fastapi.middleware.cors import CORSMiddleware
|
from fastapi.middleware.cors import CORSMiddleware
|
||||||
from apscheduler.schedulers.background import BackgroundScheduler
|
from apscheduler.schedulers.background import BackgroundScheduler
|
||||||
|
from _shared.access_log import install as install_access_log
|
||||||
|
|
||||||
from .db import (
|
from .db import (
|
||||||
init_db, get_announcements, get_announcement, create_announcement,
|
init_db, get_announcements, get_announcement, create_announcement,
|
||||||
@@ -68,6 +69,7 @@ async def lifespan(app: FastAPI):
|
|||||||
|
|
||||||
|
|
||||||
app = FastAPI(lifespan=lifespan)
|
app = FastAPI(lifespan=lifespan)
|
||||||
|
install_access_log(app)
|
||||||
|
|
||||||
_cors_origins = os.getenv("CORS_ALLOW_ORIGINS", "http://localhost:3007,http://localhost:8080").split(",")
|
_cors_origins = os.getenv("CORS_ALLOW_ORIGINS", "http://localhost:3007,http://localhost:8080").split(",")
|
||||||
app.add_middleware(
|
app.add_middleware(
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ from fastapi.middleware.cors import CORSMiddleware
|
|||||||
import requests
|
import requests
|
||||||
from apscheduler.schedulers.background import BackgroundScheduler
|
from apscheduler.schedulers.background import BackgroundScheduler
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
|
from _shared.access_log import install as install_access_log
|
||||||
|
|
||||||
logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(name)s] %(levelname)s %(message)s")
|
logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(name)s] %(levelname)s %(message)s")
|
||||||
logger = logging.getLogger("stock")
|
logger = logging.getLogger("stock")
|
||||||
@@ -28,6 +29,7 @@ from .auth import verify_webai_key
|
|||||||
from . import webai_cache
|
from . import webai_cache
|
||||||
|
|
||||||
app = FastAPI()
|
app = FastAPI()
|
||||||
|
install_access_log(app)
|
||||||
|
|
||||||
# Screener 라우터 등록
|
# Screener 라우터 등록
|
||||||
from app.screener.router import router as screener_router
|
from app.screener.router import router as screener_router
|
||||||
|
|||||||
Reference in New Issue
Block a user