log refactor
This commit is contained in:
@@ -30,7 +30,10 @@ from ...schemas.auth import (
|
||||
)
|
||||
from ...models.auth import User, Role, ADGroupMapping
|
||||
from ...dependencies import has_permission, get_plugin_loader
|
||||
from ...core.cot_logger import MarkerLogger
|
||||
from ...core.logger import logger, belief_scope
|
||||
|
||||
log = MarkerLogger("AdminApi")
|
||||
from ...services.rbac_permission_catalog import (
|
||||
discover_declared_permissions,
|
||||
sync_permission_catalog,
|
||||
@@ -167,25 +170,17 @@ async def delete_user(
|
||||
_=Depends(has_permission("admin:users", "WRITE")),
|
||||
):
|
||||
with belief_scope("api.admin.delete_user"):
|
||||
logger.info(
|
||||
f"[DEBUG] Attempting to delete user context={{'user_id': '{user_id}'}}"
|
||||
)
|
||||
log.reason(f"Attempting to delete user {user_id}")
|
||||
repo = AuthRepository(db)
|
||||
user = repo.get_user_by_id(user_id)
|
||||
if not user:
|
||||
logger.warning(
|
||||
f"[DEBUG] User not found for deletion context={{'user_id': '{user_id}'}}"
|
||||
)
|
||||
log.explore(f"User not found for deletion: {user_id}", error="User not found")
|
||||
raise HTTPException(status_code=404, detail="User not found")
|
||||
|
||||
logger.info(
|
||||
f"[DEBUG] Found user to delete context={{'username': '{user.username}'}}"
|
||||
)
|
||||
log.reason(f"Found user to delete: {user.username}")
|
||||
db.delete(user)
|
||||
db.commit()
|
||||
logger.info(
|
||||
f"[DEBUG] Successfully deleted user context={{'user_id': '{user_id}'}}"
|
||||
)
|
||||
log.reflect(f"Successfully deleted user {user_id}")
|
||||
return None
|
||||
|
||||
|
||||
@@ -348,10 +343,7 @@ async def list_permissions(
|
||||
db=db, declared_permissions=declared_permissions
|
||||
)
|
||||
if inserted_count > 0:
|
||||
logger.info(
|
||||
"[api.admin.list_permissions][Action] Synchronized %s missing RBAC permissions into auth catalog",
|
||||
inserted_count,
|
||||
)
|
||||
log.reason(f"Synchronized {inserted_count} missing RBAC permissions into auth catalog")
|
||||
|
||||
repo = AuthRepository(db)
|
||||
return repo.list_permissions()
|
||||
|
||||
@@ -18,7 +18,10 @@ from src.dependencies import (
|
||||
get_current_user, has_permission,
|
||||
)
|
||||
from src.core.database import get_db
|
||||
from src.core.cot_logger import MarkerLogger
|
||||
from src.core.logger import logger, belief_scope
|
||||
|
||||
log = MarkerLogger("DashboardListing")
|
||||
from src.models.auth import User
|
||||
from src.services.profile_service import ProfileService
|
||||
from ._helpers import _normalize_filter_values, _dashboard_git_filter_value
|
||||
@@ -73,16 +76,16 @@ async def get_dashboards(
|
||||
f"page_context={page_context}, applyp={apply_profile_default}, overhide={override_show_all}",
|
||||
):
|
||||
if page < 1:
|
||||
logger.error(f"[get_dashboards][Coherence:Failed] Invalid page: {page}")
|
||||
log.explore(f"Invalid page: {page}", error="Page must be >= 1")
|
||||
raise HTTPException(status_code=400, detail="Page must be >= 1")
|
||||
if page_size < 1 or page_size > 100:
|
||||
logger.error(f"[get_dashboards][Coherence:Failed] Invalid page_size: {page_size}")
|
||||
log.explore(f"Invalid page_size: {page_size}", error="Page size must be between 1 and 100")
|
||||
raise HTTPException(status_code=400, detail="Page size must be between 1 and 100")
|
||||
|
||||
environments = config_manager.get_environments()
|
||||
env = next((e for e in environments if e.id == env_id), None)
|
||||
if not env:
|
||||
logger.error(f"[get_dashboards][Coherence:Failed] Environment not found: {env_id}")
|
||||
log.explore(f"Environment not found: {env_id}", error="Environment not found")
|
||||
raise HTTPException(status_code=404, detail="Environment not found")
|
||||
|
||||
bound_username: Optional[str] = None
|
||||
@@ -151,7 +154,8 @@ async def get_dashboards(
|
||||
)
|
||||
except Exception as profile_error:
|
||||
logger.explore(
|
||||
f"[EXPLORE] Profile preference unavailable; continuing without profile-default filter: {profile_error}"
|
||||
f"Profile preference unavailable; continuing without profile-default filter",
|
||||
error=str(profile_error),
|
||||
)
|
||||
|
||||
try:
|
||||
@@ -193,10 +197,7 @@ async def get_dashboards(
|
||||
total = page_payload["total"]
|
||||
total_pages = page_payload["total_pages"]
|
||||
except Exception as page_error:
|
||||
logger.warning(
|
||||
"[get_dashboards][Action] Page-based fetch failed; using compatibility fallback: %s",
|
||||
page_error,
|
||||
)
|
||||
log.explore(f"Page-based fetch failed; using compatibility fallback", error=str(page_error))
|
||||
if can_apply_slug_filter:
|
||||
dashboards = await resource_service.get_dashboards_with_status(
|
||||
env,
|
||||
@@ -251,7 +252,7 @@ async def get_dashboards(
|
||||
if not actor_aliases:
|
||||
actor_aliases = [bound_username]
|
||||
logger.reason(
|
||||
"[REASON] Applying profile actor filter "
|
||||
f"Applying profile actor filter "
|
||||
f"(env={env_id}, bound_username={bound_username}, actor_aliases={actor_aliases!r}, "
|
||||
f"dashboards_before={len(dashboards)})"
|
||||
)
|
||||
@@ -269,7 +270,7 @@ async def get_dashboards(
|
||||
)
|
||||
if index < max_actor_samples:
|
||||
logger.reflect(
|
||||
"[REFLECT] Profile actor filter sample "
|
||||
f"Profile actor filter sample "
|
||||
f"(env={env_id}, dashboard_id={dashboard.get('id')}, "
|
||||
f"bound_username={bound_username!r}, actor_aliases={actor_aliases!r}, "
|
||||
f"owners={owners_value!r}, created_by={created_by_value!r}, "
|
||||
@@ -279,7 +280,7 @@ async def get_dashboards(
|
||||
filtered_dashboards.append(dashboard)
|
||||
|
||||
logger.reflect(
|
||||
"[REFLECT] Profile actor filter summary "
|
||||
f"Profile actor filter summary "
|
||||
f"(env={env_id}, bound_username={bound_username!r}, "
|
||||
f"dashboards_before={len(dashboards)}, dashboards_after={len(filtered_dashboards)})"
|
||||
)
|
||||
@@ -365,10 +366,7 @@ async def get_dashboards(
|
||||
end_idx = start_idx + page_size
|
||||
paginated_dashboards = dashboards[start_idx:end_idx]
|
||||
|
||||
logger.info(
|
||||
f"[get_dashboards][Coherence:OK] Returning {len(paginated_dashboards)} dashboards "
|
||||
f"(page {page}/{total_pages}, total: {total}, profile_filter_applied={effective_profile_filter.applied})"
|
||||
)
|
||||
log.reflect(f"Returning {len(paginated_dashboards)} dashboards (page {page}/{total_pages}, total: {total}, profile_filter_applied={effective_profile_filter.applied})")
|
||||
|
||||
response_dashboards = _project_dashboard_response_items(
|
||||
paginated_dashboards
|
||||
@@ -386,9 +384,7 @@ async def get_dashboards(
|
||||
except HTTPException:
|
||||
raise
|
||||
except Exception as e:
|
||||
logger.error(
|
||||
f"[get_dashboards][Coherence:Failed] Failed to fetch dashboards: {e}"
|
||||
)
|
||||
log.explore("Failed to fetch dashboards", error=str(e))
|
||||
raise HTTPException(
|
||||
status_code=503, detail=f"Failed to fetch dashboards: {str(e)}"
|
||||
)
|
||||
|
||||
@@ -13,8 +13,9 @@ from fastapi import APIRouter, Depends, Header, HTTPException, Query, Response,
|
||||
from pydantic import BaseModel, Field
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from src.core.cot_logger import MarkerLogger
|
||||
from src.core.database import get_db
|
||||
from src.core.logger import belief_scope, logger
|
||||
from src.core.logger import belief_scope
|
||||
from src.dependencies import (
|
||||
get_config_manager,
|
||||
get_current_user,
|
||||
@@ -69,6 +70,8 @@ from src.services.dataset_review.repositories.session_repository import (
|
||||
DatasetReviewSessionVersionConflictError,
|
||||
)
|
||||
|
||||
log = MarkerLogger("DatasetReviewDeps")
|
||||
|
||||
|
||||
# [DEF:StartSessionRequest:Class]
|
||||
# @COMPLEXITY: 1
|
||||
@@ -445,7 +448,7 @@ def _enforce_session_version(repository, session, expected_version):
|
||||
try:
|
||||
repository.require_session_version(session, expected_version)
|
||||
except DatasetReviewSessionVersionConflictError as exc:
|
||||
logger.explore("Dataset review optimistic-lock conflict detected", extra={"session_id": exc.session_id, "expected_version": exc.expected_version, "actual_version": exc.actual_version})
|
||||
log.explore("Dataset review optimistic-lock conflict detected", payload={"session_id": exc.session_id, "expected_version": exc.expected_version, "actual_version": exc.actual_version}, error="Optimistic lock conflict")
|
||||
raise _build_session_version_conflict_http_exception(exc) from exc
|
||||
return session
|
||||
|
||||
|
||||
@@ -10,7 +10,8 @@ from typing import Any, List, Optional, Union, cast
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException, Query, Response, status
|
||||
|
||||
from src.core.logger import belief_scope, logger
|
||||
from src.core.cot_logger import MarkerLogger
|
||||
from src.core.logger import belief_scope
|
||||
from src.dependencies import get_config_manager, get_current_user, has_permission
|
||||
from src.models.auth import User
|
||||
from src.models.dataset_review import (
|
||||
@@ -89,6 +90,8 @@ from src.api.routes.dataset_review_pkg._dependencies import (
|
||||
_build_session_version_conflict_http_exception,
|
||||
)
|
||||
|
||||
log = MarkerLogger("DatasetReviewRoutes")
|
||||
|
||||
router = APIRouter(prefix="/api/dataset-orchestration", tags=["Dataset Orchestration"])
|
||||
|
||||
|
||||
@@ -110,17 +113,17 @@ async def list_sessions(
|
||||
current_user: User = Depends(get_current_user),
|
||||
):
|
||||
with belief_scope("dataset_review.list_sessions"):
|
||||
logger.reason(
|
||||
log.reason(
|
||||
"Listing dataset review sessions",
|
||||
extra={"user_id": current_user.id, "page": page, "page_size": page_size},
|
||||
payload={"user_id": current_user.id, "page": page, "page_size": page_size},
|
||||
)
|
||||
sessions = repository.list_sessions_for_user(current_user.id)
|
||||
start = (page - 1) * page_size
|
||||
end = start + page_size
|
||||
items = [_serialize_session_summary(s) for s in sessions[start:end]]
|
||||
logger.reflect(
|
||||
log.reflect(
|
||||
"Session page assembled",
|
||||
extra={
|
||||
payload={
|
||||
"user_id": current_user.id,
|
||||
"returned": len(items),
|
||||
"total": len(sessions),
|
||||
@@ -156,9 +159,9 @@ async def start_session(
|
||||
current_user: User = Depends(get_current_user),
|
||||
):
|
||||
with belief_scope("start_session"):
|
||||
logger.reason(
|
||||
log.reason(
|
||||
"Starting dataset review session",
|
||||
extra={
|
||||
payload={
|
||||
"user_id": current_user.id,
|
||||
"environment_id": request.environment_id,
|
||||
},
|
||||
@@ -173,10 +176,7 @@ async def start_session(
|
||||
)
|
||||
)
|
||||
except ValueError as exc:
|
||||
logger.explore(
|
||||
"Session start rejected",
|
||||
extra={"user_id": current_user.id, "error": str(exc)},
|
||||
)
|
||||
log.explore("Session start rejected", error="Session start rejected by orchestrator", payload={"user_id": current_user.id, "error": str(exc)})
|
||||
detail = str(exc)
|
||||
sc = (
|
||||
status.HTTP_404_NOT_FOUND
|
||||
@@ -184,8 +184,8 @@ async def start_session(
|
||||
else status.HTTP_400_BAD_REQUEST
|
||||
)
|
||||
raise HTTPException(status_code=sc, detail=detail) from exc
|
||||
logger.reflect(
|
||||
"Session started", extra={"session_id": result.session.session_id}
|
||||
log.reflect(
|
||||
"Session started", payload={"session_id": result.session.session_id}
|
||||
)
|
||||
return _serialize_session_summary(result.session)
|
||||
|
||||
|
||||
@@ -13,7 +13,9 @@ from typing import Optional
|
||||
from fastapi import HTTPException
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from src.core.logger import logger
|
||||
from src.core.cot_logger import MarkerLogger
|
||||
|
||||
log = MarkerLogger("GitHelpers")
|
||||
from src.core.superset_client import SupersetClient
|
||||
from src.dependencies import get_config_manager
|
||||
from src.models.auth import User
|
||||
@@ -52,7 +54,7 @@ def _build_no_repo_status_payload() -> dict:
|
||||
# @PRE: `error` is a non-HTTPException instance.
|
||||
# @POST: Raises HTTPException(500) with route-specific context.
|
||||
def _handle_unexpected_git_route_error(route_name: str, error: Exception) -> None:
|
||||
logger.error(f"[{route_name}][Coherence:Failed] {error}")
|
||||
log.explore(f"{route_name} failed: {error}", error=str(error))
|
||||
raise HTTPException(status_code=500, detail=f"{route_name} failed: {str(error)}")
|
||||
# [/DEF:_handle_unexpected_git_route_error:Function]
|
||||
|
||||
@@ -66,8 +68,8 @@ def _resolve_repository_status(dashboard_id: int) -> dict:
|
||||
git_service = get_git_service()
|
||||
repo_path = git_service._get_repo_path(dashboard_id)
|
||||
if not os.path.exists(repo_path):
|
||||
logger.debug(
|
||||
f"[get_repository_status][Action] Repository is not initialized for dashboard {dashboard_id}"
|
||||
log.reason(
|
||||
f"Repository is not initialized for dashboard {dashboard_id}"
|
||||
)
|
||||
return _build_no_repo_status_payload()
|
||||
|
||||
@@ -75,8 +77,8 @@ def _resolve_repository_status(dashboard_id: int) -> dict:
|
||||
return git_service.get_status(dashboard_id)
|
||||
except HTTPException as e:
|
||||
if e.status_code == 404:
|
||||
logger.debug(
|
||||
f"[get_repository_status][Action] Repository is not initialized for dashboard {dashboard_id}"
|
||||
log.reason(
|
||||
f"Repository is not initialized for dashboard {dashboard_id}"
|
||||
)
|
||||
return _build_no_repo_status_payload()
|
||||
raise
|
||||
@@ -300,11 +302,7 @@ def _resolve_current_user_git_identity(
|
||||
.first()
|
||||
)
|
||||
except Exception as resolve_error:
|
||||
logger.warning(
|
||||
"[_resolve_current_user_git_identity][Action] Failed to load profile preference for user %s: %s",
|
||||
user_id,
|
||||
resolve_error,
|
||||
)
|
||||
log.explore(f"Failed to load profile preference for user {user_id}: {resolve_error}", error=str(resolve_error))
|
||||
return None
|
||||
|
||||
if not preference:
|
||||
|
||||
@@ -10,7 +10,10 @@ from fastapi import Depends, HTTPException
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from src.core.database import get_db
|
||||
from src.core.logger import belief_scope, logger
|
||||
from src.core.cot_logger import MarkerLogger
|
||||
from src.core.logger import belief_scope
|
||||
|
||||
log = MarkerLogger("GitRepoOps")
|
||||
from src.dependencies import get_config_manager, get_current_user, has_permission
|
||||
from src.models.auth import User
|
||||
from src.models.git import GitRepository, GitServerConfig
|
||||
@@ -133,23 +136,13 @@ async def pull_changes(
|
||||
config_url = config_row.url
|
||||
config_provider = config_row.provider
|
||||
except Exception as diagnostics_error:
|
||||
logger.warning(
|
||||
"[pull_changes][Action] Failed to load repository binding diagnostics for dashboard %s: %s",
|
||||
dashboard_id,
|
||||
diagnostics_error,
|
||||
)
|
||||
logger.info(
|
||||
"[pull_changes][Action] Route diagnostics dashboard_ref=%s env_id=%s resolved_dashboard_id=%s "
|
||||
"binding_exists=%s binding_local_path=%s binding_remote_url=%s binding_config_id=%s config_provider=%s config_url=%s",
|
||||
dashboard_ref,
|
||||
env_id,
|
||||
dashboard_id,
|
||||
bool(db_repo),
|
||||
(db_repo.local_path if db_repo else None),
|
||||
(db_repo.remote_url if db_repo else None),
|
||||
(db_repo.config_id if db_repo else None),
|
||||
config_provider,
|
||||
config_url,
|
||||
log.explore(f"Failed to load repository binding diagnostics for dashboard {dashboard_id}: {diagnostics_error}", error=str(diagnostics_error))
|
||||
log.reason(
|
||||
f"Route diagnostics dashboard_ref={dashboard_ref} env_id={env_id} resolved_dashboard_id={dashboard_id} "
|
||||
f"binding_exists={bool(db_repo)} binding_local_path={(db_repo.local_path if db_repo else None)} "
|
||||
f"binding_remote_url={(db_repo.remote_url if db_repo else None)} "
|
||||
f"binding_config_id={(db_repo.config_id if db_repo else None)} "
|
||||
f"config_provider={config_provider} config_url={config_url}"
|
||||
)
|
||||
_apply_git_identity_from_profile(dashboard_id, db, current_user)
|
||||
_gs.pull_changes(dashboard_id)
|
||||
@@ -197,11 +190,7 @@ async def get_repository_status_batch(
|
||||
with belief_scope("get_repository_status_batch"):
|
||||
dashboard_ids = list(dict.fromkeys(request.dashboard_ids))
|
||||
if len(dashboard_ids) > MAX_REPOSITORY_STATUS_BATCH:
|
||||
logger.warning(
|
||||
"[get_repository_status_batch][Action] Batch size %s exceeds limit %s. Truncating request.",
|
||||
len(dashboard_ids),
|
||||
MAX_REPOSITORY_STATUS_BATCH,
|
||||
)
|
||||
log.explore(f"Batch size {len(dashboard_ids)} exceeds limit {MAX_REPOSITORY_STATUS_BATCH}. Truncating request.", error="Batch size exceeds limit")
|
||||
dashboard_ids = dashboard_ids[:MAX_REPOSITORY_STATUS_BATCH]
|
||||
|
||||
statuses = {}
|
||||
@@ -215,9 +204,7 @@ async def get_repository_status_batch(
|
||||
"sync_status": "ERROR",
|
||||
}
|
||||
except Exception as e:
|
||||
logger.error(
|
||||
f"[get_repository_status_batch][Coherence:Failed] Failed for dashboard {dashboard_id}: {e}"
|
||||
)
|
||||
log.explore(f"Failed for dashboard {dashboard_id}: {e}", error=str(e))
|
||||
statuses[str(dashboard_id)] = {
|
||||
**_build_no_repo_status_payload(),
|
||||
"sync_state": "ERROR",
|
||||
|
||||
@@ -10,7 +10,10 @@ from fastapi import Depends, HTTPException
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from src.core.database import get_db
|
||||
from src.core.logger import belief_scope, logger
|
||||
from src.core.cot_logger import MarkerLogger
|
||||
from src.core.logger import belief_scope
|
||||
|
||||
log = MarkerLogger("GitRepoRoutes")
|
||||
from src.dependencies import get_config_manager, get_current_user, has_permission
|
||||
from src.models.auth import User
|
||||
from src.models.git import GitRepository, GitServerConfig
|
||||
@@ -64,9 +67,7 @@ async def init_repository(
|
||||
raise HTTPException(status_code=404, detail="Git configuration not found")
|
||||
|
||||
try:
|
||||
logger.info(
|
||||
f"[init_repository][Action] Initializing repo for dashboard {dashboard_id}"
|
||||
)
|
||||
log.reason(f"Initializing repo for dashboard {dashboard_id}")
|
||||
_gs.init_repo(
|
||||
dashboard_id,
|
||||
init_data.remote_url,
|
||||
@@ -97,15 +98,10 @@ async def init_repository(
|
||||
db_repo.current_branch = "dev"
|
||||
|
||||
db.commit()
|
||||
logger.info(
|
||||
f"[init_repository][Coherence:OK] Repository initialized for dashboard {dashboard_id}"
|
||||
)
|
||||
return {"status": "success", "message": "Repository initialized"}
|
||||
except Exception as e:
|
||||
db.rollback()
|
||||
logger.error(
|
||||
f"[init_repository][Coherence:Failed] Failed to init repository: {e}"
|
||||
)
|
||||
log.explore("Failed to init repository", error=str(e))
|
||||
if isinstance(e, HTTPException):
|
||||
raise
|
||||
_handle_unexpected_git_route_error("init_repository", e)
|
||||
|
||||
@@ -11,7 +11,9 @@
|
||||
from fastapi import APIRouter, Depends, HTTPException, status
|
||||
from typing import List, Optional
|
||||
import httpx
|
||||
from ...core.logger import logger
|
||||
from ...core.cot_logger import MarkerLogger
|
||||
|
||||
log = MarkerLogger("LlmRoutes")
|
||||
from ...schemas.auth import User
|
||||
from ...dependencies import get_current_user as get_current_active_user
|
||||
from ...plugins.llm_analysis.models import (
|
||||
@@ -80,8 +82,8 @@ async def get_providers(
|
||||
"""
|
||||
Get all LLM provider configurations.
|
||||
"""
|
||||
logger.info(
|
||||
f"[llm_routes][get_providers][Action] Fetching providers for user: {current_user.username}"
|
||||
log.reason(
|
||||
f"Fetching providers for user: {current_user.username}"
|
||||
)
|
||||
service = LLMProviderService(db)
|
||||
providers = service.get_all_providers()
|
||||
@@ -289,8 +291,8 @@ async def fetch_models_for_provider(
|
||||
3. {base_url}/api/tags (Ollama format)
|
||||
Returns empty list if none respond — user can enter model name manually.
|
||||
"""
|
||||
logger.info(
|
||||
f"[llm_routes][fetch_models] Fetching models for {request.base_url}"
|
||||
log.reason(
|
||||
f"Fetching models for {request.base_url}"
|
||||
)
|
||||
|
||||
# Resolve API key: prefer direct, fall back to stored key via provider_id
|
||||
@@ -300,9 +302,7 @@ async def fetch_models_for_provider(
|
||||
svc = LLMProviderService(db)
|
||||
api_key = svc.get_decrypted_api_key(request.provider_id)
|
||||
except Exception:
|
||||
logger.warning(
|
||||
f"[llm_routes][fetch_models] Could not resolve API key for provider {request.provider_id}"
|
||||
)
|
||||
log.explore(f"Could not resolve API key for provider {request.provider_id}", error="API key resolution failed")
|
||||
|
||||
base = request.base_url.rstrip("/")
|
||||
|
||||
@@ -343,8 +343,8 @@ async def fetch_models_for_provider(
|
||||
for m in raw
|
||||
)
|
||||
if models:
|
||||
logger.info(
|
||||
f"[llm_routes][fetch_models] Found {len(models)} models at {url}"
|
||||
log.reason(
|
||||
f"Found {len(models)} models at {url}"
|
||||
)
|
||||
return FetchModelsResponse(
|
||||
models=models, total=len(models)
|
||||
@@ -359,8 +359,8 @@ async def fetch_models_for_provider(
|
||||
for m in models_list
|
||||
)
|
||||
if models:
|
||||
logger.info(
|
||||
f"[llm_routes][fetch_models] Found {len(models)} Ollama models at {url}"
|
||||
log.reason(
|
||||
f"Found {len(models)} Ollama models at {url}"
|
||||
)
|
||||
return FetchModelsResponse(
|
||||
models=models, total=len(models)
|
||||
@@ -374,16 +374,11 @@ async def fetch_models_for_provider(
|
||||
last_error = f"Error at {url}: {str(e)[:100]}"
|
||||
|
||||
# All endpoints failed — return empty list with no error (user can type manually)
|
||||
logger.warning(
|
||||
f"[llm_routes][fetch_models] No model endpoint responded for {request.base_url}. "
|
||||
f"Last error: {last_error}"
|
||||
)
|
||||
log.explore(f"No model endpoint responded for {request.base_url}. Last error: {last_error}", error=f"No model endpoint responded for {request.base_url}")
|
||||
return FetchModelsResponse(models=[], total=0)
|
||||
|
||||
except Exception as e:
|
||||
logger.error(
|
||||
f"[llm_routes][fetch_models] Unexpected error for {request.base_url}: {e}"
|
||||
)
|
||||
log.explore(f"Unexpected error for {request.base_url}: {e}", error=str(e))
|
||||
return FetchModelsResponse(models=[], total=0)
|
||||
|
||||
|
||||
@@ -402,8 +397,8 @@ async def test_connection(
|
||||
current_user: User = Depends(get_current_active_user),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
logger.info(
|
||||
f"[llm_routes][test_connection][Action] Testing connection for provider_id: {provider_id}"
|
||||
log.reason(
|
||||
f"Testing connection for provider_id: {provider_id}"
|
||||
)
|
||||
"""
|
||||
Test connection to an LLM provider.
|
||||
@@ -419,9 +414,7 @@ async def test_connection(
|
||||
|
||||
# Check if API key was successfully decrypted
|
||||
if not api_key:
|
||||
logger.error(
|
||||
f"[llm_routes][test_connection] Failed to decrypt API key for provider {provider_id}"
|
||||
)
|
||||
log.explore(f"Failed to decrypt API key for provider {provider_id}", error="API key decryption failed")
|
||||
raise HTTPException(
|
||||
status_code=500,
|
||||
detail="Failed to decrypt API key. The provider may have been encrypted with a different encryption key. Please update the provider with a new API key.",
|
||||
@@ -459,8 +452,8 @@ async def test_provider_config(
|
||||
"""
|
||||
from ...plugins.llm_analysis.service import LLMClient
|
||||
|
||||
logger.info(
|
||||
f"[llm_routes][test_provider_config][Action] Testing config for {config.name}"
|
||||
log.reason(
|
||||
f"Testing config for {config.name}"
|
||||
)
|
||||
|
||||
# Check if API key is provided
|
||||
|
||||
@@ -346,7 +346,6 @@ async def trigger_sync_now(
|
||||
_=Depends(has_permission("plugin:migration", "EXECUTE")),
|
||||
):
|
||||
with belief_scope("trigger_sync_now"):
|
||||
from ...core.logger import logger
|
||||
from ...models.mapping import Environment as EnvironmentModel
|
||||
|
||||
config = config_manager.get_config()
|
||||
@@ -366,8 +365,8 @@ async def trigger_sync_now(
|
||||
credentials_id=env.id, # Use env.id as credentials reference
|
||||
)
|
||||
db.add(db_env)
|
||||
logger.info(
|
||||
f"[trigger_sync_now][Action] Created environment row for {env.id}"
|
||||
logger.reason(
|
||||
f"Created environment row for {env.id}"
|
||||
)
|
||||
else:
|
||||
existing.name = env.name
|
||||
@@ -382,10 +381,10 @@ async def trigger_sync_now(
|
||||
client = SupersetClient(env)
|
||||
service.sync_environment(env.id, client)
|
||||
results["synced"].append(env.id)
|
||||
logger.info(f"[trigger_sync_now][Action] Synced environment {env.id}")
|
||||
logger.reason(f"Synced environment {env.id}")
|
||||
except Exception as e:
|
||||
results["failed"].append({"env_id": env.id, "error": str(e)})
|
||||
logger.error(f"[trigger_sync_now][Error] Failed to sync {env.id}: {e}")
|
||||
logger.explore(f"Failed to sync {env.id}", error=str(e))
|
||||
|
||||
return {
|
||||
"status": "completed",
|
||||
|
||||
@@ -22,7 +22,8 @@ from fastapi import APIRouter, Depends, HTTPException, Query
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from ...core.database import get_db
|
||||
from ...core.logger import logger, belief_scope
|
||||
from ...core.logger import belief_scope
|
||||
from ...core.cot_logger import MarkerLogger
|
||||
from ...dependencies import (
|
||||
get_config_manager,
|
||||
get_current_user,
|
||||
@@ -43,6 +44,8 @@ from ...services.profile_service import (
|
||||
)
|
||||
# [/SECTION]
|
||||
|
||||
log = MarkerLogger("Profile")
|
||||
|
||||
router = APIRouter(prefix="/api/profile", tags=["profile"])
|
||||
|
||||
|
||||
@@ -73,7 +76,7 @@ async def get_preferences(
|
||||
plugin_loader=Depends(get_plugin_loader),
|
||||
):
|
||||
with belief_scope("profile.get_preferences", f"user_id={current_user.id}"):
|
||||
logger.reason("[REASON] Resolving current user preference")
|
||||
log.reason("Resolving current user preference")
|
||||
service = _get_profile_service(db, config_manager, plugin_loader)
|
||||
return service.get_my_preference(current_user)
|
||||
# [/DEF:get_preferences:Function]
|
||||
@@ -95,13 +98,13 @@ async def update_preferences(
|
||||
with belief_scope("profile.update_preferences", f"user_id={current_user.id}"):
|
||||
service = _get_profile_service(db, config_manager, plugin_loader)
|
||||
try:
|
||||
logger.reason("[REASON] Attempting preference save")
|
||||
log.reason("Attempting preference save")
|
||||
return service.update_my_preference(current_user=current_user, payload=payload)
|
||||
except ProfileValidationError as exc:
|
||||
logger.reflect("[REFLECT] Preference validation failed")
|
||||
log.reflect("Preference validation failed")
|
||||
raise HTTPException(status_code=422, detail=exc.errors) from exc
|
||||
except ProfileAuthorizationError as exc:
|
||||
logger.explore("[EXPLORE] Cross-user mutation guard blocked request")
|
||||
log.explore("Cross-user mutation guard blocked request", error="User attempted to mutate another user's resource")
|
||||
raise HTTPException(status_code=403, detail=str(exc)) from exc
|
||||
# [/DEF:update_preferences:Function]
|
||||
|
||||
@@ -138,13 +141,13 @@ async def lookup_superset_accounts(
|
||||
sort_order=sort_order,
|
||||
)
|
||||
try:
|
||||
logger.reason("[REASON] Executing Superset account lookup")
|
||||
log.reason("Executing Superset account lookup")
|
||||
return service.lookup_superset_accounts(
|
||||
current_user=current_user,
|
||||
request=lookup_request,
|
||||
)
|
||||
except EnvironmentNotFoundError as exc:
|
||||
logger.explore("[EXPLORE] Lookup request references unknown environment")
|
||||
log.explore("Lookup request references unknown environment", error="EnvironmentNotFoundError raised during Superset account lookup")
|
||||
raise HTTPException(status_code=404, detail=str(exc)) from exc
|
||||
# [/DEF:lookup_superset_accounts:Function]
|
||||
|
||||
|
||||
@@ -19,7 +19,10 @@ from ...core.config_models import AppConfig, Environment, GlobalSettings, Loggin
|
||||
from ...models.storage import StorageConfig
|
||||
from ...dependencies import get_config_manager, has_permission
|
||||
from ...core.config_manager import ConfigManager
|
||||
from ...core.logger import logger, belief_scope
|
||||
from ...core.logger import belief_scope
|
||||
from ...core.cot_logger import MarkerLogger
|
||||
|
||||
log = MarkerLogger("Settings")
|
||||
from ...core.superset_client import SupersetClient
|
||||
from ...services.llm_prompt_templates import normalize_llm_settings
|
||||
from ...models.llm import ValidationPolicy
|
||||
@@ -98,7 +101,7 @@ async def get_settings(
|
||||
_=Depends(has_permission("admin:settings", "READ")),
|
||||
):
|
||||
with belief_scope("get_settings"):
|
||||
logger.info("[get_settings][Entry] Fetching all settings")
|
||||
log.reason("Fetching all settings")
|
||||
config = config_manager.get_config().copy(deep=True)
|
||||
config.settings.llm = normalize_llm_settings(config.settings.llm)
|
||||
# Mask passwords
|
||||
@@ -141,7 +144,7 @@ async def update_global_settings(
|
||||
_=Depends(has_permission("admin:settings", "WRITE")),
|
||||
):
|
||||
with belief_scope("update_global_settings"):
|
||||
logger.info("[update_global_settings][Entry] Updating global settings")
|
||||
log.reason("Updating global settings")
|
||||
|
||||
config_manager.update_global_settings(settings)
|
||||
return settings
|
||||
@@ -204,7 +207,7 @@ async def get_environments(
|
||||
_=Depends(has_permission("admin:settings", "READ")),
|
||||
):
|
||||
with belief_scope("get_environments"):
|
||||
logger.info("[get_environments][Entry] Fetching environments")
|
||||
log.reason("Fetching environments")
|
||||
environments = config_manager.get_environments()
|
||||
return [
|
||||
env.copy(update={"url": _normalize_superset_env_url(env.url)})
|
||||
@@ -229,16 +232,14 @@ async def add_environment(
|
||||
_=Depends(has_permission("admin:settings", "WRITE")),
|
||||
):
|
||||
with belief_scope("add_environment"):
|
||||
logger.info(f"[add_environment][Entry] Adding environment {env.id}")
|
||||
log.reason("Adding environment", payload={"env_id": env.id})
|
||||
env = env.copy(update={"url": _normalize_superset_env_url(env.url)})
|
||||
|
||||
# Validate connection before adding (fast path)
|
||||
try:
|
||||
_validate_superset_connection_fast(env)
|
||||
except Exception as e:
|
||||
logger.error(
|
||||
f"[add_environment][Coherence:Failed] Connection validation failed: {e}"
|
||||
)
|
||||
log.explore("Connection validation failed", payload={"env_id": env.id}, error=str(e))
|
||||
raise HTTPException(
|
||||
status_code=400, detail=f"Connection validation failed: {e}"
|
||||
)
|
||||
@@ -265,7 +266,7 @@ async def update_environment(
|
||||
config_manager: ConfigManager = Depends(get_config_manager),
|
||||
):
|
||||
with belief_scope("update_environment"):
|
||||
logger.info(f"[update_environment][Entry] Updating environment {id}")
|
||||
log.reason("Updating environment", payload={"id": id})
|
||||
|
||||
env = env.copy(update={"url": _normalize_superset_env_url(env.url)})
|
||||
|
||||
@@ -282,9 +283,7 @@ async def update_environment(
|
||||
try:
|
||||
_validate_superset_connection_fast(env_to_validate)
|
||||
except Exception as e:
|
||||
logger.error(
|
||||
f"[update_environment][Coherence:Failed] Connection validation failed: {e}"
|
||||
)
|
||||
log.explore("Connection validation failed", payload={"id": id}, error=str(e))
|
||||
raise HTTPException(
|
||||
status_code=400, detail=f"Connection validation failed: {e}"
|
||||
)
|
||||
@@ -308,7 +307,7 @@ async def delete_environment(
|
||||
id: str, config_manager: ConfigManager = Depends(get_config_manager)
|
||||
):
|
||||
with belief_scope("delete_environment"):
|
||||
logger.info(f"[delete_environment][Entry] Deleting environment {id}")
|
||||
log.reason("Deleting environment", payload={"id": id})
|
||||
config_manager.delete_environment(id)
|
||||
return {"message": f"Environment {id} deleted"}
|
||||
|
||||
@@ -328,7 +327,7 @@ async def test_environment_connection(
|
||||
id: str, config_manager: ConfigManager = Depends(get_config_manager)
|
||||
):
|
||||
with belief_scope("test_environment_connection"):
|
||||
logger.info(f"[test_environment_connection][Entry] Testing environment {id}")
|
||||
log.reason("Testing environment connection", payload={"id": id})
|
||||
|
||||
# Find environment
|
||||
env = next((e for e in config_manager.get_environments() if e.id == id), None)
|
||||
@@ -338,14 +337,10 @@ async def test_environment_connection(
|
||||
try:
|
||||
_validate_superset_connection_fast(env)
|
||||
|
||||
logger.info(
|
||||
f"[test_environment_connection][Coherence:OK] Connection successful for {id}"
|
||||
)
|
||||
log.reflect("Connection successful", payload={"id": id})
|
||||
return {"status": "success", "message": "Connection successful"}
|
||||
except Exception as e:
|
||||
logger.error(
|
||||
f"[test_environment_connection][Coherence:Failed] Connection failed for {id}: {e}"
|
||||
)
|
||||
log.explore("Connection failed", payload={"id": id}, error=str(e))
|
||||
return {"status": "error", "message": str(e)}
|
||||
|
||||
|
||||
@@ -389,9 +384,7 @@ async def update_logging_config(
|
||||
_=Depends(has_permission("admin:settings", "WRITE")),
|
||||
):
|
||||
with belief_scope("update_logging_config"):
|
||||
logger.info(
|
||||
f"[update_logging_config][Entry] Updating logging config: level={config.level}, task_log_level={config.task_log_level}"
|
||||
)
|
||||
log.reason("Updating logging config", payload={"level": config.level, "task_log_level": config.task_log_level})
|
||||
|
||||
# Get current settings and update logging config
|
||||
settings = config_manager.get_config().settings
|
||||
@@ -444,7 +437,7 @@ async def get_consolidated_settings(
|
||||
_=Depends(has_permission("admin:settings", "READ")),
|
||||
):
|
||||
with belief_scope("get_consolidated_settings"):
|
||||
logger.reason("Fetching consolidated settings payload")
|
||||
log.reason("Fetching consolidated settings payload")
|
||||
|
||||
config = config_manager.get_config()
|
||||
|
||||
@@ -491,9 +484,9 @@ async def get_consolidated_settings(
|
||||
notifications=notifications_payload,
|
||||
features=config.settings.features.model_dump(),
|
||||
)
|
||||
logger.reflect(
|
||||
log.reflect(
|
||||
"Consolidated settings payload assembled",
|
||||
extra={
|
||||
payload={
|
||||
"environment_count": len(response_payload.environments),
|
||||
"provider_count": len(response_payload.llm_providers),
|
||||
},
|
||||
@@ -516,9 +509,7 @@ async def update_consolidated_settings(
|
||||
_=Depends(has_permission("admin:settings", "WRITE")),
|
||||
):
|
||||
with belief_scope("update_consolidated_settings"):
|
||||
logger.info(
|
||||
"[update_consolidated_settings][Entry] Applying consolidated settings patch"
|
||||
)
|
||||
log.reason("Applying consolidated settings patch")
|
||||
|
||||
current_config = config_manager.get_config()
|
||||
current_settings = current_config.settings
|
||||
|
||||
@@ -13,7 +13,7 @@ from typing import Any, Dict, List, Optional
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from ....core.database import get_db
|
||||
from ....core.logger import logger, belief_scope
|
||||
from ....core.cot_logger import MarkerLogger
|
||||
from ....schemas.auth import User
|
||||
from ....dependencies import get_current_user, has_permission
|
||||
from ....plugins.translate.dictionary import DictionaryManager
|
||||
@@ -25,6 +25,7 @@ from ....schemas.translate import (
|
||||
|
||||
from ._router import router
|
||||
|
||||
log = MarkerLogger("TranslateCorrectionRoutes")
|
||||
|
||||
# ============================================================
|
||||
# Corrections
|
||||
@@ -44,7 +45,7 @@ async def submit_correction(
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""Submit a term correction from a run result review."""
|
||||
logger.info(f"[translate_routes][submit_correction] User: {current_user.username}")
|
||||
log.reason("Correction request", payload={"user": current_user.username})
|
||||
if not payload.dictionary_id:
|
||||
raise HTTPException(status_code=422, detail="dictionary_id is required")
|
||||
try:
|
||||
@@ -78,7 +79,7 @@ async def submit_bulk_corrections(
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""Submit multiple term corrections atomically."""
|
||||
logger.info(f"[translate_routes][submit_bulk_corrections] User: {current_user.username}")
|
||||
log.reason("Bulk correction request", payload={"user": current_user.username})
|
||||
try:
|
||||
corr_list = []
|
||||
for c in payload.corrections:
|
||||
|
||||
@@ -13,8 +13,11 @@ from typing import Any, Dict, List, Optional
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from ....core.database import get_db
|
||||
from ....core.logger import logger, belief_scope
|
||||
from ....core.logger import belief_scope
|
||||
from ....core.cot_logger import MarkerLogger
|
||||
from ....schemas.auth import User
|
||||
|
||||
log = MarkerLogger("TranslateDictRoutes")
|
||||
from ....dependencies import get_current_user, has_permission
|
||||
from ....plugins.translate.dictionary import DictionaryManager
|
||||
from ....schemas.translate import (
|
||||
@@ -49,12 +52,12 @@ async def list_dictionaries(
|
||||
):
|
||||
"""List all terminology dictionaries."""
|
||||
with belief_scope("list_dictionaries"):
|
||||
logger.reason(f"User: {current_user.username}")
|
||||
log.reason("List dictionaries", payload={"user": current_user.username})
|
||||
dicts, total = DictionaryManager.list_dictionaries(db, page=page, page_size=page_size)
|
||||
dict_ids = [d.id for d in dicts]
|
||||
counts = _get_dictionary_entry_counts(db, dict_ids) if dict_ids else {}
|
||||
items = [_dict_to_response(d, counts.get(d.id, 0)) for d in dicts]
|
||||
logger.reflect("Dictionaries listed", {"total": total, "returned": len(items)})
|
||||
log.reflect("Dictionaries listed", payload={"total": total, "returned": len(items)})
|
||||
return {"items": items, "total": total, "page": page, "page_size": page_size}
|
||||
# #endregion list_dictionaries
|
||||
|
||||
@@ -74,12 +77,12 @@ async def get_dictionary(
|
||||
):
|
||||
"""Get a terminology dictionary by ID."""
|
||||
with belief_scope("get_dictionary"):
|
||||
logger.reason(f"Dict: {dictionary_id}, User: {current_user.username}")
|
||||
log.reason("Get dictionary", payload={"dict_id": dictionary_id, "user": current_user.username})
|
||||
try:
|
||||
d = DictionaryManager.get_dictionary(db, dictionary_id)
|
||||
from ....models.translate import DictionaryEntry
|
||||
entry_count = db.query(DictionaryEntry.id).filter(DictionaryEntry.dictionary_id == dictionary_id).count()
|
||||
logger.reflect("Dictionary found", {"id": dictionary_id})
|
||||
log.reflect("Dictionary found", payload={"id": dictionary_id})
|
||||
return _dict_to_response(d, entry_count)
|
||||
except ValueError as e:
|
||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(e))
|
||||
@@ -101,7 +104,7 @@ async def create_dictionary(
|
||||
):
|
||||
"""Create a new terminology dictionary."""
|
||||
with belief_scope("create_dictionary"):
|
||||
logger.reason(f"User: {current_user.username}")
|
||||
log.reason("Create dictionary", payload={"user": current_user.username})
|
||||
d = DictionaryManager.create_dictionary(
|
||||
db,
|
||||
name=payload.name,
|
||||
@@ -111,7 +114,7 @@ async def create_dictionary(
|
||||
description=payload.description,
|
||||
is_active=payload.is_active,
|
||||
)
|
||||
logger.reflect("Dictionary created", {"id": d.id})
|
||||
log.reflect("Dictionary created", payload={"id": d.id})
|
||||
return _dict_to_response(d, 0)
|
||||
# #endregion create_dictionary
|
||||
|
||||
@@ -132,7 +135,7 @@ async def update_dictionary(
|
||||
):
|
||||
"""Update a terminology dictionary."""
|
||||
with belief_scope("update_dictionary"):
|
||||
logger.reason(f"Dict: {dictionary_id}, User: {current_user.username}")
|
||||
log.reason("Update dictionary", payload={"dict_id": dictionary_id, "user": current_user.username})
|
||||
try:
|
||||
d = DictionaryManager.update_dictionary(
|
||||
db,
|
||||
@@ -145,7 +148,7 @@ async def update_dictionary(
|
||||
)
|
||||
from ....models.translate import DictionaryEntry
|
||||
entry_count = db.query(DictionaryEntry.id).filter(DictionaryEntry.dictionary_id == dictionary_id).count()
|
||||
logger.reflect("Dictionary updated", {"id": dictionary_id})
|
||||
log.reflect("Dictionary updated", payload={"id": dictionary_id})
|
||||
return _dict_to_response(d, entry_count)
|
||||
except ValueError as e:
|
||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(e))
|
||||
@@ -167,10 +170,10 @@ async def delete_dictionary(
|
||||
):
|
||||
"""Delete a terminology dictionary."""
|
||||
with belief_scope("delete_dictionary"):
|
||||
logger.reason(f"Dict: {dictionary_id}, User: {current_user.username}")
|
||||
log.reason("Delete dictionary", payload={"dict_id": dictionary_id, "user": current_user.username})
|
||||
try:
|
||||
DictionaryManager.delete_dictionary(db, dictionary_id)
|
||||
logger.reflect("Dictionary deleted", {"id": dictionary_id})
|
||||
log.reflect("Dictionary deleted", payload={"id": dictionary_id})
|
||||
return None
|
||||
except ValueError as e:
|
||||
if "active/scheduled" in str(e):
|
||||
@@ -200,7 +203,7 @@ async def list_dictionary_entries(
|
||||
):
|
||||
"""List entries for a dictionary."""
|
||||
with belief_scope("list_dictionary_entries"):
|
||||
logger.reason(f"Dict: {dictionary_id}, User: {current_user.username}")
|
||||
log.reason("List dictionary entries", payload={"dict_id": dictionary_id, "user": current_user.username})
|
||||
try:
|
||||
entries, total = DictionaryManager.list_entries(db, dictionary_id, page=page, page_size=page_size)
|
||||
items = [
|
||||
@@ -216,7 +219,7 @@ async def list_dictionary_entries(
|
||||
}
|
||||
for e in entries
|
||||
]
|
||||
logger.reflect("Entries listed", {"dict_id": dictionary_id, "total": total})
|
||||
log.reflect("Entries listed", payload={"dict_id": dictionary_id, "total": total})
|
||||
return {"items": items, "total": total, "page": page, "page_size": page_size}
|
||||
except ValueError as e:
|
||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(e))
|
||||
@@ -239,7 +242,7 @@ async def add_dictionary_entry(
|
||||
):
|
||||
"""Add a new entry to a dictionary."""
|
||||
with belief_scope("add_dictionary_entry"):
|
||||
logger.reason(f"Dict: {dictionary_id}, User: {current_user.username}")
|
||||
log.reason("Add dictionary entry", payload={"dict_id": dictionary_id, "user": current_user.username})
|
||||
try:
|
||||
entry = DictionaryManager.add_entry(
|
||||
db, dictionary_id,
|
||||
@@ -247,7 +250,7 @@ async def add_dictionary_entry(
|
||||
target_term=payload.target_term,
|
||||
context_notes=payload.context_notes,
|
||||
)
|
||||
logger.reflect("Entry added", {"entry_id": entry.id})
|
||||
log.reflect("Entry added", payload={"entry_id": entry.id})
|
||||
return {
|
||||
"id": entry.id,
|
||||
"dictionary_id": entry.dictionary_id,
|
||||
@@ -282,7 +285,7 @@ async def edit_dictionary_entry(
|
||||
):
|
||||
"""Update an existing dictionary entry."""
|
||||
with belief_scope("edit_dictionary_entry"):
|
||||
logger.reason(f"Entry: {entry_id}, User: {current_user.username}")
|
||||
log.reason("Edit dictionary entry", payload={"entry_id": entry_id, "user": current_user.username})
|
||||
try:
|
||||
entry = DictionaryManager.edit_entry(
|
||||
db, entry_id,
|
||||
@@ -290,7 +293,7 @@ async def edit_dictionary_entry(
|
||||
target_term=payload.target_term,
|
||||
context_notes=payload.context_notes,
|
||||
)
|
||||
logger.reflect("Entry updated", {"entry_id": entry_id})
|
||||
log.reflect("Entry updated", payload={"entry_id": entry_id})
|
||||
return {
|
||||
"id": entry.id,
|
||||
"dictionary_id": entry.dictionary_id,
|
||||
@@ -324,10 +327,10 @@ async def delete_dictionary_entry(
|
||||
):
|
||||
"""Delete a dictionary entry."""
|
||||
with belief_scope("delete_dictionary_entry"):
|
||||
logger.reason(f"Entry: {entry_id}, User: {current_user.username}")
|
||||
log.reason("Delete dictionary entry", payload={"entry_id": entry_id, "user": current_user.username})
|
||||
try:
|
||||
DictionaryManager.delete_entry(db, entry_id)
|
||||
logger.reflect("Entry deleted", {"entry_id": entry_id})
|
||||
log.reflect("Entry deleted", payload={"entry_id": entry_id})
|
||||
return None
|
||||
except ValueError as e:
|
||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(e))
|
||||
@@ -350,7 +353,7 @@ async def import_dictionary_entries(
|
||||
):
|
||||
"""Import entries into a terminology dictionary from CSV/TSV content."""
|
||||
with belief_scope("import_dictionary_entries"):
|
||||
logger.reason(f"Dict: {dictionary_id}, User: {current_user.username}")
|
||||
log.reason("Import dictionary entries", payload={"dict_id": dictionary_id, "user": current_user.username})
|
||||
|
||||
if payload.on_conflict not in ("overwrite", "keep_existing", "cancel"):
|
||||
raise HTTPException(
|
||||
@@ -367,7 +370,7 @@ async def import_dictionary_entries(
|
||||
on_conflict=payload.on_conflict,
|
||||
preview_only=payload.preview_only,
|
||||
)
|
||||
logger.reflect("Import completed", {
|
||||
log.reflect("Import completed", payload={
|
||||
"dict_id": dictionary_id,
|
||||
"total": result["total"],
|
||||
"errors": len(result["errors"]),
|
||||
|
||||
@@ -15,8 +15,11 @@ from typing import Any, Dict, List, Optional
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from ....core.database import get_db
|
||||
from ....core.logger import logger, belief_scope
|
||||
from ....core.logger import belief_scope
|
||||
from ....core.cot_logger import MarkerLogger
|
||||
from ....schemas.auth import User
|
||||
|
||||
log = MarkerLogger("TranslateJobRoutes")
|
||||
from ....dependencies import get_current_user, has_permission, get_config_manager
|
||||
from ....core.config_manager import ConfigManager
|
||||
from ....plugins.translate.service import (
|
||||
@@ -53,7 +56,7 @@ async def list_jobs(
|
||||
config_manager: ConfigManager = Depends(get_config_manager),
|
||||
):
|
||||
"""List all translation jobs."""
|
||||
logger.info(f"[translate_routes][list_jobs] User: {current_user.username}")
|
||||
log.reason("Listing jobs", payload={"user": current_user.username})
|
||||
try:
|
||||
service = TranslateJobService(db, config_manager, current_user.username)
|
||||
total, jobs = service.list_jobs(
|
||||
@@ -83,7 +86,7 @@ async def get_job(
|
||||
config_manager: ConfigManager = Depends(get_config_manager),
|
||||
):
|
||||
"""Get a translation job by ID."""
|
||||
logger.info(f"[translate_routes][get_job] Job: {job_id}, User: {current_user.username}")
|
||||
log.reason("Getting job", payload={"job_id": job_id, "user": current_user.username})
|
||||
try:
|
||||
service = TranslateJobService(db, config_manager, current_user.username)
|
||||
job = service.get_job(job_id)
|
||||
@@ -109,7 +112,7 @@ async def create_job(
|
||||
config_manager: ConfigManager = Depends(get_config_manager),
|
||||
):
|
||||
"""Create a new translation job."""
|
||||
logger.info(f"[translate_routes][create_job] User: {current_user.username}")
|
||||
log.reason("Creating job", payload={"user": current_user.username})
|
||||
try:
|
||||
service = TranslateJobService(db, config_manager, current_user.username)
|
||||
job = service.create_job(payload)
|
||||
@@ -136,7 +139,7 @@ async def update_job(
|
||||
config_manager: ConfigManager = Depends(get_config_manager),
|
||||
):
|
||||
"""Update a translation job."""
|
||||
logger.info(f"[translate_routes][update_job] Job: {job_id}, User: {current_user.username}")
|
||||
log.reason("Updating job", payload={"job_id": job_id, "user": current_user.username})
|
||||
try:
|
||||
service = TranslateJobService(db, config_manager, current_user.username)
|
||||
job = service.update_job(job_id, payload)
|
||||
@@ -162,7 +165,7 @@ async def delete_job(
|
||||
config_manager: ConfigManager = Depends(get_config_manager),
|
||||
):
|
||||
"""Delete a translation job."""
|
||||
logger.info(f"[translate_routes][delete_job] Job: {job_id}, User: {current_user.username}")
|
||||
log.reason("Deleting job", payload={"job_id": job_id, "user": current_user.username})
|
||||
try:
|
||||
service = TranslateJobService(db, config_manager, current_user.username)
|
||||
service.delete_job(job_id)
|
||||
@@ -186,7 +189,7 @@ async def duplicate_job(
|
||||
config_manager: ConfigManager = Depends(get_config_manager),
|
||||
):
|
||||
"""Duplicate a translation job."""
|
||||
logger.info(f"[translate_routes][duplicate_job] Job: {job_id}, User: {current_user.username}")
|
||||
log.reason("Duplicating job", payload={"job_id": job_id, "user": current_user.username})
|
||||
try:
|
||||
service = TranslateJobService(db, config_manager, current_user.username)
|
||||
new_job = service.duplicate_job(job_id)
|
||||
@@ -223,7 +226,7 @@ async def list_datasources(
|
||||
datasets = service.fetch_available_datasources(env_id, search)
|
||||
return datasets
|
||||
except Exception as e:
|
||||
logger.error(f"[translate_routes][list_datasources] Error: {e}")
|
||||
log.explore("List datasources failed", error=str(e))
|
||||
raise HTTPException(status_code=status.HTTP_502_BAD_GATEWAY, detail=str(e))
|
||||
# #endregion list_datasources
|
||||
|
||||
@@ -244,10 +247,11 @@ async def get_datasource_columns(
|
||||
config_manager: ConfigManager = Depends(get_config_manager),
|
||||
):
|
||||
"""Get column metadata and database dialect for a Superset datasource."""
|
||||
logger.info(
|
||||
f"[translate_routes][get_datasource_columns] "
|
||||
f"Datasource: {datasource_id}, Env: {env_id}, User: {current_user.username}"
|
||||
)
|
||||
log.reason("Getting datasource columns", payload={
|
||||
"datasource_id": datasource_id,
|
||||
"env_id": env_id,
|
||||
"user": current_user.username,
|
||||
})
|
||||
try:
|
||||
result = fetch_datasource_columns_service(
|
||||
datasource_id=datasource_id,
|
||||
@@ -258,7 +262,7 @@ async def get_datasource_columns(
|
||||
except ValueError as e:
|
||||
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e))
|
||||
except Exception as e:
|
||||
logger.error(f"[translate_routes][get_datasource_columns] Error: {e}")
|
||||
log.explore("Get datasource columns failed", error=str(e))
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_502_BAD_GATEWAY,
|
||||
detail=f"Failed to fetch datasource columns from Superset: {e}",
|
||||
|
||||
@@ -10,13 +10,14 @@ from typing import Any, Dict, List, Optional
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from ....core.database import get_db
|
||||
from ....core.logger import logger, belief_scope
|
||||
from ....core.cot_logger import MarkerLogger
|
||||
from ....schemas.auth import User
|
||||
from ....dependencies import get_current_user, has_permission
|
||||
from ....plugins.translate.metrics import TranslationMetrics
|
||||
|
||||
from ._router import router
|
||||
|
||||
log = MarkerLogger("TranslateMetricsRoutes")
|
||||
|
||||
# ============================================================
|
||||
# Metrics
|
||||
@@ -33,7 +34,7 @@ async def get_metrics(
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""Get translation metrics."""
|
||||
logger.info(f"[translate_routes][get_metrics] User: {current_user.username}")
|
||||
log.reason("Metrics request", payload={"user": current_user.username})
|
||||
try:
|
||||
metrics_svc = TranslationMetrics(db)
|
||||
if job_id:
|
||||
@@ -55,7 +56,7 @@ async def get_job_metrics(
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""Get aggregated metrics for a specific job."""
|
||||
logger.info(f"[translate_routes][get_job_metrics] Job: {job_id}, User: {current_user.username}")
|
||||
log.reason("Job metrics request", payload={"job_id": job_id, "user": current_user.username})
|
||||
try:
|
||||
metrics_svc = TranslationMetrics(db)
|
||||
return metrics_svc.get_job_metrics(job_id)
|
||||
|
||||
@@ -14,8 +14,10 @@ from typing import Any, Dict, List, Optional
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from ....core.database import get_db
|
||||
from ....core.logger import logger, belief_scope
|
||||
from ....core.cot_logger import MarkerLogger
|
||||
from ....schemas.auth import User
|
||||
|
||||
log = MarkerLogger("TranslatePreviewRoutes")
|
||||
from ....dependencies import get_current_user, has_permission, get_config_manager
|
||||
from ....core.config_manager import ConfigManager
|
||||
from ....plugins.translate.preview import TranslationPreview
|
||||
@@ -50,7 +52,7 @@ async def preview_translation(
|
||||
config_manager: ConfigManager = Depends(get_config_manager),
|
||||
):
|
||||
"""Preview a translation before applying it."""
|
||||
logger.info(f"[translate_routes][preview_translation] Job: {job_id}, User: {current_user.username}")
|
||||
log.reason("Preview translation", payload={"job_id": job_id, "user": current_user.username})
|
||||
if payload is None:
|
||||
payload = PreviewRequest()
|
||||
try:
|
||||
@@ -65,7 +67,7 @@ async def preview_translation(
|
||||
except ValueError as e:
|
||||
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e))
|
||||
except Exception as e:
|
||||
logger.error(f"[translate_routes][preview_translation] Error: {e}")
|
||||
log.explore("Preview translation error", error=str(e))
|
||||
raise HTTPException(status_code=status.HTTP_502_BAD_GATEWAY, detail=f"Preview failed: {e}")
|
||||
# #endregion preview_translation
|
||||
|
||||
@@ -87,7 +89,7 @@ async def update_preview_row(
|
||||
config_manager: ConfigManager = Depends(get_config_manager),
|
||||
):
|
||||
"""Approve, edit, or reject a preview row."""
|
||||
logger.info(f"[translate_routes][update_preview_row] Job: {job_id}, Row: {row_key}, Action: {payload.action}")
|
||||
log.reason("Update preview row", payload={"job_id": job_id, "row": row_key, "action": payload.action})
|
||||
try:
|
||||
preview_service = TranslationPreview(db, config_manager, current_user.username)
|
||||
result = preview_service.update_preview_row(
|
||||
@@ -118,7 +120,7 @@ async def accept_preview_session(
|
||||
config_manager: ConfigManager = Depends(get_config_manager),
|
||||
):
|
||||
"""Accept a preview session, enabling full translation execution."""
|
||||
logger.info(f"[translate_routes][accept_preview_session] Job: {job_id}, User: {current_user.username}")
|
||||
log.reason("Accept preview session", payload={"job_id": job_id, "user": current_user.username})
|
||||
try:
|
||||
preview_service = TranslationPreview(db, config_manager, current_user.username)
|
||||
result = preview_service.accept_preview_session(job_id=job_id)
|
||||
@@ -143,7 +145,7 @@ async def apply_preview(
|
||||
config_manager: ConfigManager = Depends(get_config_manager),
|
||||
):
|
||||
"""Apply a preview session by session ID."""
|
||||
logger.info(f"[translate_routes][apply_preview] Session: {session_id}, User: {current_user.username}")
|
||||
log.reason("Apply preview", payload={"session_id": session_id, "user": current_user.username})
|
||||
# Find job_id from session
|
||||
from ....models.translate import TranslationPreviewSession
|
||||
session = db.query(TranslationPreviewSession).filter(TranslationPreviewSession.id == session_id).first()
|
||||
@@ -174,7 +176,7 @@ async def get_preview_records(
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""Get records for a preview session."""
|
||||
logger.info(f"[translate_routes][get_preview_records] Session: {session_id}, User: {current_user.username}")
|
||||
log.reason("Get preview records", payload={"session_id": session_id, "user": current_user.username})
|
||||
try:
|
||||
from ....models.translate import TranslationPreviewSession, TranslationPreviewRecord
|
||||
session = db.query(TranslationPreviewSession).filter(TranslationPreviewSession.id == session_id).first()
|
||||
@@ -201,7 +203,7 @@ async def get_preview_records(
|
||||
except HTTPException:
|
||||
raise
|
||||
except Exception as e:
|
||||
logger.error(f"[translate_routes][get_preview_records] Error: {e}")
|
||||
log.explore("Get preview records error", error=str(e))
|
||||
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e))
|
||||
# #endregion get_preview_records
|
||||
|
||||
|
||||
@@ -11,8 +11,10 @@ from typing import Any, Dict, List, Optional
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from ....core.database import get_db
|
||||
from ....core.logger import logger, belief_scope
|
||||
from ....core.cot_logger import MarkerLogger
|
||||
from ....schemas.auth import User
|
||||
|
||||
log = MarkerLogger("TranslateRunListRoutes")
|
||||
from ....dependencies import get_current_user, has_permission, get_config_manager
|
||||
from ....core.config_manager import ConfigManager
|
||||
from ....plugins.translate.orchestrator import TranslationOrchestrator
|
||||
@@ -43,7 +45,7 @@ async def list_runs(
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""List all runs with cross-job filtering and pagination."""
|
||||
logger.info(f"[translate_routes][list_runs] User: {current_user.username}")
|
||||
log.reason("Listing runs", payload={"user": current_user.username})
|
||||
try:
|
||||
from ....models.translate import TranslationRun
|
||||
query = db.query(TranslationRun)
|
||||
@@ -103,7 +105,7 @@ async def list_runs(
|
||||
|
||||
return {"items": items, "total": total, "page": page, "page_size": page_size}
|
||||
except Exception as e:
|
||||
logger.error(f"[translate_routes][list_runs] Error: {e}")
|
||||
log.explore("List runs error", error=str(e))
|
||||
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e))
|
||||
# #endregion list_runs
|
||||
|
||||
@@ -126,7 +128,7 @@ async def get_run_detail(
|
||||
config_manager: ConfigManager = Depends(get_config_manager),
|
||||
):
|
||||
"""Get detailed run info with config_snapshot, records, events."""
|
||||
logger.info(f"[translate_routes][get_run_detail] Run: {run_id}, User: {current_user.username}")
|
||||
log.reason("Get run detail", payload={"run_id": run_id, "user": current_user.username})
|
||||
try:
|
||||
orch = TranslationOrchestrator(db, config_manager, current_user.username)
|
||||
status_info = orch.get_run_status(run_id)
|
||||
@@ -167,7 +169,7 @@ async def download_skipped_csv(
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""Download skipped translation records as CSV."""
|
||||
logger.info(f"[translate_routes][download_skipped_csv] Run: {run_id}, User: {current_user.username}")
|
||||
log.reason("Download skipped CSV", payload={"run_id": run_id, "user": current_user.username})
|
||||
try:
|
||||
from ....models.translate import TranslationRecord
|
||||
from fastapi.responses import StreamingResponse
|
||||
@@ -200,7 +202,7 @@ async def download_skipped_csv(
|
||||
headers={"Content-Disposition": f"attachment; filename=skipped_{run_id}.csv"},
|
||||
)
|
||||
except Exception as e:
|
||||
logger.error(f"[translate_routes][download_skipped_csv] Error: {e}")
|
||||
log.explore("Download skipped CSV error", error=str(e))
|
||||
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e))
|
||||
# #endregion download_skipped_csv
|
||||
|
||||
|
||||
@@ -14,8 +14,10 @@ from typing import Any, Dict, List, Optional
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from ....core.database import get_db, SessionLocal
|
||||
from ....core.logger import logger, belief_scope
|
||||
from ....core.cot_logger import MarkerLogger
|
||||
from ....schemas.auth import User
|
||||
|
||||
log = MarkerLogger("TranslateRunRoutes")
|
||||
from ....dependencies import get_current_user, has_permission, get_config_manager
|
||||
from ....core.config_manager import ConfigManager
|
||||
from ....plugins.translate.orchestrator import TranslationOrchestrator
|
||||
@@ -50,7 +52,7 @@ async def run_translation(
|
||||
By default runs translation on preview-approved rows only.
|
||||
Set full_translation=true to fetch ALL rows from the Superset source dataset.
|
||||
"""
|
||||
logger.info(f"[translate_routes][run_translation] Job: {job_id}, User: {current_user.username}, full={full_translation}")
|
||||
log.reason("Run translation", payload={"job_id": job_id, "user": current_user.username, "full_translation": full_translation})
|
||||
try:
|
||||
orch = TranslationOrchestrator(db, config_manager, current_user.username)
|
||||
run = orch.start_run(job_id=job_id, is_scheduled=False)
|
||||
@@ -68,7 +70,7 @@ async def run_translation(
|
||||
if thread_run:
|
||||
thread_orch.execute_run(thread_run, full_translation=full_translation)
|
||||
except Exception as e:
|
||||
logger.error(f"[translate_routes][run_translation] Background execution error: {e}")
|
||||
log.explore("Background execution error", error=str(e))
|
||||
finally:
|
||||
thread_db.close()
|
||||
|
||||
@@ -77,7 +79,7 @@ async def run_translation(
|
||||
except ValueError as e:
|
||||
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e))
|
||||
except Exception as e:
|
||||
logger.error(f"[translate_routes][run_translation] Error: {e}")
|
||||
log.explore("Run translation error", error=str(e))
|
||||
raise HTTPException(status_code=status.HTTP_502_BAD_GATEWAY, detail=f"Run failed: {e}")
|
||||
# #endregion run_translation
|
||||
|
||||
@@ -97,7 +99,7 @@ async def retry_run(
|
||||
config_manager: ConfigManager = Depends(get_config_manager),
|
||||
):
|
||||
"""Retry failed batches in a translation run."""
|
||||
logger.info(f"[translate_routes][retry_run] Run: {run_id}, User: {current_user.username}")
|
||||
log.reason("Retry run", payload={"run_id": run_id, "user": current_user.username})
|
||||
try:
|
||||
orch = TranslationOrchestrator(db, config_manager, current_user.username)
|
||||
run = orch.retry_failed_batches(run_id)
|
||||
@@ -105,7 +107,7 @@ async def retry_run(
|
||||
except ValueError as e:
|
||||
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e))
|
||||
except Exception as e:
|
||||
logger.error(f"[translate_routes][retry_run] Error: {e}")
|
||||
log.explore("Retry run error", error=str(e))
|
||||
raise HTTPException(status_code=status.HTTP_502_BAD_GATEWAY, detail=f"Retry failed: {e}")
|
||||
# #endregion retry_run
|
||||
|
||||
@@ -125,7 +127,7 @@ async def retry_insert(
|
||||
config_manager: ConfigManager = Depends(get_config_manager),
|
||||
):
|
||||
"""Retry the SQL insert phase for a completed run."""
|
||||
logger.info(f"[translate_routes][retry_insert] Run: {run_id}, User: {current_user.username}")
|
||||
log.reason("Retry insert", payload={"run_id": run_id, "user": current_user.username})
|
||||
try:
|
||||
orch = TranslationOrchestrator(db, config_manager, current_user.username)
|
||||
run = orch.retry_insert(run_id)
|
||||
@@ -133,7 +135,7 @@ async def retry_insert(
|
||||
except ValueError as e:
|
||||
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e))
|
||||
except Exception as e:
|
||||
logger.error(f"[translate_routes][retry_insert] Error: {e}")
|
||||
log.explore("Retry insert error", error=str(e))
|
||||
raise HTTPException(status_code=status.HTTP_502_BAD_GATEWAY, detail=f"Retry insert failed: {e}")
|
||||
# #endregion retry_insert
|
||||
|
||||
@@ -153,7 +155,7 @@ async def cancel_run(
|
||||
config_manager: ConfigManager = Depends(get_config_manager),
|
||||
):
|
||||
"""Cancel a running translation."""
|
||||
logger.info(f"[translate_routes][cancel_run] Run: {run_id}, User: {current_user.username}")
|
||||
log.reason("Cancel run", payload={"run_id": run_id, "user": current_user.username})
|
||||
try:
|
||||
orch = TranslationOrchestrator(db, config_manager, current_user.username)
|
||||
run = orch.cancel_run(run_id)
|
||||
@@ -177,7 +179,7 @@ async def get_run_history(
|
||||
config_manager: ConfigManager = Depends(get_config_manager),
|
||||
):
|
||||
"""Get run history for a translation job."""
|
||||
logger.info(f"[translate_routes][get_run_history] Job: {job_id}, User: {current_user.username}")
|
||||
log.reason("Get run history", payload={"job_id": job_id, "user": current_user.username})
|
||||
try:
|
||||
orch = TranslationOrchestrator(db, config_manager, current_user.username)
|
||||
total, runs = orch.get_run_history(job_id, page=page, page_size=page_size)
|
||||
@@ -199,7 +201,7 @@ async def get_run_status(
|
||||
config_manager: ConfigManager = Depends(get_config_manager),
|
||||
):
|
||||
"""Get status and statistics for a translation run."""
|
||||
logger.info(f"[translate_routes][get_run_status] Run: {run_id}, User: {current_user.username}")
|
||||
log.reason("Get run status", payload={"run_id": run_id, "user": current_user.username})
|
||||
try:
|
||||
orch = TranslationOrchestrator(db, config_manager, current_user.username)
|
||||
return orch.get_run_status(run_id)
|
||||
@@ -223,7 +225,7 @@ async def get_run_records(
|
||||
config_manager: ConfigManager = Depends(get_config_manager),
|
||||
):
|
||||
"""Get paginated records for a translation run."""
|
||||
logger.info(f"[translate_routes][get_run_records] Run: {run_id}, User: {current_user.username}")
|
||||
log.reason("Get run records", payload={"run_id": run_id, "user": current_user.username})
|
||||
try:
|
||||
orch = TranslationOrchestrator(db, config_manager, current_user.username)
|
||||
return orch.get_run_records(run_id, page=page, page_size=page_size, status_filter=status)
|
||||
@@ -247,7 +249,7 @@ async def get_batches(
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""Get batches for a translation run."""
|
||||
logger.info(f"[translate_routes][get_batches] Run: {run_id}, User: {current_user.username}")
|
||||
log.reason("Get batches", payload={"run_id": run_id, "user": current_user.username})
|
||||
try:
|
||||
from ....models.translate import TranslationBatch
|
||||
batches = (
|
||||
@@ -272,7 +274,7 @@ async def get_batches(
|
||||
for b in batches
|
||||
]
|
||||
except Exception as e:
|
||||
logger.error(f"[translate_routes][get_batches] Error: {e}")
|
||||
log.explore("Get batches error", error=str(e))
|
||||
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e))
|
||||
# #endregion get_batches
|
||||
|
||||
|
||||
@@ -14,8 +14,10 @@ from typing import Any, Dict, List, Optional
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from ....core.database import get_db
|
||||
from ....core.logger import logger, belief_scope
|
||||
from ....core.cot_logger import MarkerLogger
|
||||
from ....schemas.auth import User
|
||||
|
||||
log = MarkerLogger("TranslateScheduleRoutes")
|
||||
from ....dependencies import get_current_user, has_permission, get_config_manager
|
||||
from ....core.config_manager import ConfigManager
|
||||
from ....plugins.translate.scheduler import TranslationScheduler
|
||||
@@ -40,7 +42,7 @@ async def get_schedule(
|
||||
config_manager: ConfigManager = Depends(get_config_manager),
|
||||
):
|
||||
"""Get schedule for a translation job."""
|
||||
logger.info(f"[translate_routes][get_schedule] Job: {job_id}, User: {current_user.username}")
|
||||
log.reason("Get schedule", payload={"job_id": job_id, "user": current_user.username})
|
||||
try:
|
||||
scheduler = TranslationScheduler(db, config_manager, current_user.username)
|
||||
schedule = scheduler.get_schedule(job_id)
|
||||
@@ -77,7 +79,7 @@ async def set_schedule(
|
||||
config_manager: ConfigManager = Depends(get_config_manager),
|
||||
):
|
||||
"""Set or update schedule for a translation job."""
|
||||
logger.info(f"[translate_routes][set_schedule] Job: {job_id}, User: {current_user.username}")
|
||||
log.reason("Set schedule", payload={"job_id": job_id, "user": current_user.username})
|
||||
try:
|
||||
scheduler = TranslationScheduler(db, config_manager, current_user.username)
|
||||
# Check if schedule already exists
|
||||
@@ -139,7 +141,7 @@ async def enable_schedule(
|
||||
config_manager: ConfigManager = Depends(get_config_manager),
|
||||
):
|
||||
"""Enable a schedule for a translation job."""
|
||||
logger.info(f"[translate_routes][enable_schedule] Job: {job_id}, User: {current_user.username}")
|
||||
log.reason("Enable schedule", payload={"job_id": job_id, "user": current_user.username})
|
||||
try:
|
||||
scheduler = TranslationScheduler(db, config_manager, current_user.username)
|
||||
schedule = scheduler.set_schedule_active(job_id, is_active=True)
|
||||
@@ -172,7 +174,7 @@ async def disable_schedule(
|
||||
config_manager: ConfigManager = Depends(get_config_manager),
|
||||
):
|
||||
"""Disable a schedule for a translation job."""
|
||||
logger.info(f"[translate_routes][disable_schedule] Job: {job_id}, User: {current_user.username}")
|
||||
log.reason("Disable schedule", payload={"job_id": job_id, "user": current_user.username})
|
||||
try:
|
||||
scheduler = TranslationScheduler(db, config_manager, current_user.username)
|
||||
scheduler.set_schedule_active(job_id, is_active=False)
|
||||
@@ -200,7 +202,7 @@ async def delete_schedule(
|
||||
config_manager: ConfigManager = Depends(get_config_manager),
|
||||
):
|
||||
"""Delete schedule for a translation job."""
|
||||
logger.info(f"[translate_routes][delete_schedule] Job: {job_id}, User: {current_user.username}")
|
||||
log.reason(f"Delete schedule", payload={"job_id": job_id, "user": current_user.username})
|
||||
try:
|
||||
scheduler = TranslationScheduler(db, config_manager, current_user.username)
|
||||
scheduler.delete_schedule(job_id)
|
||||
@@ -226,7 +228,7 @@ async def get_next_executions(
|
||||
config_manager: ConfigManager = Depends(get_config_manager),
|
||||
):
|
||||
"""Preview next N executions for a job's schedule."""
|
||||
logger.info(f"[translate_routes][get_next_executions] Job: {job_id}, User: {current_user.username}")
|
||||
log.reason(f"Get next executions", payload={"job_id": job_id, "user": current_user.username})
|
||||
try:
|
||||
scheduler = TranslationScheduler(db, config_manager, current_user.username)
|
||||
schedule = scheduler.get_schedule(job_id)
|
||||
|
||||
Reference in New Issue
Block a user