File size: 2,089 Bytes
395651c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
"""log_step (debug), pipeline (debug), access log ở middleware."""

from __future__ import annotations

import json
import logging
import os
from typing import Any

from app.logging_setup import PIPELINE_LOGGER_NAME, STEPS_LOGGER_NAME

_pipeline = logging.getLogger(PIPELINE_LOGGER_NAME)
_steps = logging.getLogger(STEPS_LOGGER_NAME)


def is_debug_mode() -> bool:
    """Chi tiết từng bước chỉ khi LOG_LEVEL=debug."""
    return os.getenv("LOG_LEVEL", "info").strip().lower() == "debug"


def _truncate(val: Any, max_len: int = 2000) -> Any:
    if val is None:
        return None
    if isinstance(val, (int, float, bool)):
        return val
    s = str(val)
    if len(s) > max_len:
        return s[:max_len] + f"... (+{len(s) - max_len} chars)"
    return s


def log_step(step: str, **fields: Any) -> None:
    """Chỉ khi LOG_LEVEL=debug: DB / cache / orchestrator."""
    if not is_debug_mode():
        return
    safe = {k: _truncate(v) for k, v in fields.items()}
    try:
        payload = json.dumps(safe, ensure_ascii=False, default=str)
    except Exception:
        payload = str(safe)
    _steps.debug("[step:%s] %s", step, payload)


def log_pipeline_success(operation: str, **fields: Any) -> None:
    """Chỉ hiện khi debug (pipeline SUCCESS không dùng ở info — đã có app.access)."""
    if not is_debug_mode():
        return
    safe = {k: _truncate(v, 500) for k, v in fields.items()}
    _pipeline.info(
        "SUCCESS %s %s",
        operation,
        json.dumps(safe, ensure_ascii=False, default=str),
    )


def log_pipeline_failure(operation: str, error: str | None = None, **fields: Any) -> None:
    """Thất bại pipeline: luôn dùng WARNING để vẫn thấy khi LOG_LEVEL=warning."""
    if is_debug_mode():
        safe = {k: _truncate(v, 500) for k, v in fields.items()}
        _pipeline.warning(
            "FAIL %s err=%s %s",
            operation,
            _truncate(error, 300),
            json.dumps(safe, ensure_ascii=False, default=str),
        )
    else:
        _pipeline.warning("FAIL %s", operation)