log refactor
This commit is contained in:
@@ -24,6 +24,7 @@ from typing import Any, Dict, List, Optional, Set, Tuple, Callable
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from ...core.logger import logger, belief_scope
|
||||
from ...core.cot_logger import MarkerLogger
|
||||
from ...core.config_manager import ConfigManager
|
||||
from ...models.translate import (
|
||||
TranslationJob,
|
||||
@@ -39,6 +40,7 @@ from ...core.superset_client import SupersetClient
|
||||
from .dictionary import DictionaryManager
|
||||
from .preview import DEFAULT_EXECUTION_PROMPT_TEMPLATE
|
||||
|
||||
log = MarkerLogger("TranslationExecutor")
|
||||
|
||||
# #region MAX_RETRIES_PER_BATCH [C:1] [TYPE Constant] [SEMANTICS translate,executor,retry]
|
||||
MAX_RETRIES_PER_BATCH = 3
|
||||
@@ -83,7 +85,7 @@ class TranslationExecutor:
|
||||
if not job:
|
||||
raise ValueError(f"Job '{run.job_id}' not found for run '{run.id}'")
|
||||
|
||||
logger.reason("Starting translation execution", {
|
||||
log.reason("Starting translation execution", payload={
|
||||
"run_id": run.id,
|
||||
"job_id": job.id,
|
||||
"batch_size": job.batch_size,
|
||||
@@ -103,7 +105,7 @@ class TranslationExecutor:
|
||||
# Preview-based: fetch rows from the accepted preview session
|
||||
source_rows = self._fetch_source_rows(job.id, run.id)
|
||||
if not source_rows:
|
||||
logger.explore("No source rows to translate", {"run_id": run.id})
|
||||
log.explore("No source rows to translate", payload={"run_id": run.id}, error="Preview produced 0 source rows for translation")
|
||||
run.status = "COMPLETED"
|
||||
run.completed_at = datetime.now(timezone.utc)
|
||||
self.db.flush()
|
||||
@@ -119,7 +121,7 @@ class TranslationExecutor:
|
||||
for i in range(0, total_rows, batch_size)
|
||||
]
|
||||
|
||||
logger.reason(f"Processing {len(batches)} batches", {
|
||||
log.reason(f"Processing {len(batches)} batches", payload={
|
||||
"run_id": run.id,
|
||||
"total_rows": total_rows,
|
||||
"batch_size": batch_size,
|
||||
@@ -163,7 +165,7 @@ class TranslationExecutor:
|
||||
run.completed_at = datetime.now(timezone.utc)
|
||||
self.db.flush()
|
||||
|
||||
logger.reflect("Translation execution complete", {
|
||||
log.reflect("Translation execution complete", payload={
|
||||
"run_id": run.id,
|
||||
"status": run.status,
|
||||
"total": total_rows,
|
||||
@@ -193,7 +195,7 @@ class TranslationExecutor:
|
||||
.first()
|
||||
)
|
||||
if not session:
|
||||
logger.explore("No accepted preview session found", {"job_id": job_id})
|
||||
log.explore("No accepted preview session found", error="Preview session has no accepted rows", payload={"job_id": job_id})
|
||||
return []
|
||||
|
||||
# Fetch APPROVED or all records from the session
|
||||
@@ -216,7 +218,7 @@ class TranslationExecutor:
|
||||
"source_data": rec.source_data or {},
|
||||
})
|
||||
|
||||
logger.reason(f"Fetched {len(source_rows)} source rows from preview", {
|
||||
log.reason(f"Fetched {len(source_rows)} source rows from preview", payload={
|
||||
"run_id": run_id,
|
||||
"session_id": session.id,
|
||||
})
|
||||
@@ -278,7 +280,8 @@ class TranslationExecutor:
|
||||
headers={"Content-Type": "application/json"},
|
||||
)
|
||||
except Exception as e:
|
||||
logger.explore("Chart data API failed during full fetch", {
|
||||
log.explore("Chart data API failed during full fetch", error="Chart data API error",
|
||||
payload={
|
||||
"offset": len(all_rows),
|
||||
"error": str(e),
|
||||
})
|
||||
@@ -292,7 +295,7 @@ class TranslationExecutor:
|
||||
break # No more data
|
||||
|
||||
all_rows.extend(rows)
|
||||
logger.reason(f"Fetched {len(rows)} rows (total: {len(all_rows)})", {
|
||||
log.reason(f"Fetched {len(rows)} rows (total: {len(all_rows)})", payload={
|
||||
"offset": len(all_rows) - len(rows),
|
||||
})
|
||||
|
||||
@@ -319,7 +322,7 @@ class TranslationExecutor:
|
||||
"approved_translation": None,
|
||||
})
|
||||
|
||||
logger.reason(f"Prepared {len(source_rows)} source rows for full translation", {
|
||||
log.reason(f"Prepared {len(source_rows)} source rows for full translation", payload={
|
||||
"job_id": job.id,
|
||||
})
|
||||
return source_rows
|
||||
@@ -416,7 +419,7 @@ class TranslationExecutor:
|
||||
self.db.flush()
|
||||
|
||||
batch_latency = int((time.monotonic() - batch_start) * 1000)
|
||||
logger.reason(f"Batch {batch_index} complete", {
|
||||
log.reason(f"Batch {batch_index} complete", payload={
|
||||
"batch_id": batch_id,
|
||||
"latency_ms": batch_latency,
|
||||
**result,
|
||||
@@ -490,7 +493,8 @@ class TranslationExecutor:
|
||||
except Exception as e:
|
||||
last_error = str(e)
|
||||
retries += 1
|
||||
logger.explore(f"LLM call failed (attempt {attempt})", {
|
||||
log.explore("LLM call failed", error="LLM call failed, retrying",
|
||||
payload={
|
||||
"batch_id": batch_id,
|
||||
"error": last_error,
|
||||
"attempt": attempt,
|
||||
@@ -498,7 +502,8 @@ class TranslationExecutor:
|
||||
if attempt < MAX_RETRIES_PER_BATCH:
|
||||
time.sleep(2 ** attempt) # Exponential backoff
|
||||
else:
|
||||
logger.explore("LLM call exhausted retries", {
|
||||
log.explore("LLM call exhausted retries", error="LLM retries exhausted",
|
||||
payload={
|
||||
"batch_id": batch_id,
|
||||
"last_error": last_error,
|
||||
})
|
||||
@@ -527,7 +532,8 @@ class TranslationExecutor:
|
||||
translations = self._parse_llm_response(llm_response, len(batch_rows))
|
||||
except ValueError as e:
|
||||
# Parse failure — mark all rows as SKIPPED
|
||||
logger.explore("LLM response parse failed", {
|
||||
log.explore("LLM response parse failed", error="Failed to parse LLM JSON response",
|
||||
payload={
|
||||
"batch_id": batch_id,
|
||||
"error": str(e),
|
||||
"response_preview": llm_response[:500] if llm_response else "",
|
||||
@@ -693,7 +699,7 @@ class TranslationExecutor:
|
||||
if provider_type in ("openai", "openai_compatible"):
|
||||
payload["response_format"] = {"type": "json_object"}
|
||||
|
||||
logger.reason(
|
||||
log.reason(
|
||||
f"LLM request model={payload.get('model')} "
|
||||
f"provider_type={provider_type} "
|
||||
f"response_format={'yes' if 'response_format' in payload else 'no'} "
|
||||
@@ -701,11 +707,11 @@ class TranslationExecutor:
|
||||
)
|
||||
response = http_requests.post(url, headers=headers, json=payload, timeout=180)
|
||||
if not response.ok:
|
||||
logger.explore(
|
||||
f"LLM API error status={response.status_code} "
|
||||
f"model={payload.get('model')} "
|
||||
f"body={response.text[:2000]}"
|
||||
)
|
||||
log.explore("LLM API error", error=f"LLM API returned status {response.status_code}", payload={
|
||||
"status_code": response.status_code,
|
||||
"model": payload.get('model'),
|
||||
"body": response.text[:2000],
|
||||
})
|
||||
response.raise_for_status()
|
||||
data = response.json()
|
||||
|
||||
@@ -717,7 +723,8 @@ class TranslationExecutor:
|
||||
if not content:
|
||||
# Log full response for diagnostics
|
||||
finish_reason = choices[0].get("finish_reason", "unknown")
|
||||
logger.explore("LLM returned empty content", {
|
||||
log.explore("LLM returned empty content", error="Empty response from LLM",
|
||||
payload={
|
||||
"finish_reason": finish_reason,
|
||||
"model": payload.get("model"),
|
||||
"prompt_len": len(prompt),
|
||||
|
||||
Reference in New Issue
Block a user