File size: 3,240 Bytes
cda1137
9fe5a30
 
cda1137
 
9fe5a30
 
 
 
 
 
 
 
 
 
cda1137
9fe5a30
 
 
 
 
 
 
cda1137
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9fe5a30
 
cda1137
9fe5a30
 
 
 
 
 
 
 
 
cda1137
9fe5a30
 
 
 
 
 
cda1137
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9fe5a30
 
 
 
 
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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
"""Structured logging setup using loguru - Container optimized."""

import sys
import os
from pathlib import Path
from loguru import logger
from app.core.config import settings


def setup_logging() -> None:
    """Configure structured logging with loguru."""
    
    # Remove default handler
    logger.remove()
    
    # Always add console handler with custom format
    logger.add(
        sys.stdout,
        level=settings.log_level,
        format="<green>{time:YYYY-MM-DD HH:mm:ss}</green> | <level>{level: <8}</level> | <cyan>{name}</cyan>:<cyan>{function}</cyan>:<cyan>{line}</cyan> - <level>{message}</level>",
        colorize=True
    )
    
    # Only add file logging in development or when explicitly enabled
    if _should_enable_file_logging():
        _setup_file_logging()
    else:
        logger.info("File logging disabled - using stdout only (recommended for containers)")


def _should_enable_file_logging() -> bool:
    """Determine if file logging should be enabled."""
    # Check explicit environment variable
    disable_file_logging = os.getenv("DISABLE_FILE_LOGGING", "false").lower()
    if disable_file_logging == "true":
        return False
    
    # Check if we're likely in a container environment
    container_indicators = [
        os.getenv("CONTAINER_ENV") == "true",
        os.path.exists("/.dockerenv"),
        os.getenv("KUBERNETES_SERVICE_HOST") is not None,
        os.getenv("RAILWAY_ENVIRONMENT") is not None,
        os.getenv("RENDER") is not None,
        os.getenv("HEROKU") is not None,
    ]
    
    if any(container_indicators):
        return False
    
    # Try to write to the logs directory
    try:
        log_dir = _get_log_directory()
        test_file = log_dir / ".write_test"
        test_file.write_text("test")
        test_file.unlink()
        return True
    except (OSError, PermissionError):
        return False


def _setup_file_logging() -> None:
    """Set up file-based logging handlers."""
    log_dir = _get_log_directory()
    
    # Add file handler for errors
    logger.add(
        log_dir / "error.log",
        level="ERROR",
        format="{time:YYYY-MM-DD HH:mm:ss} | {level: <8} | {name}:{function}:{line} - {message}",
        rotation="10 MB",
        retention="30 days",
        compression="zip"
    )
    
    # Add file handler for all logs
    logger.add(
        log_dir / "app.log",
        level="INFO",
        format="{time:YYYY-MM-DD HH:mm:ss} | {level: <8} | {name}:{function}:{line} - {message}",
        rotation="50 MB",
        retention="7 days",
        compression="zip"
    )
    
    logger.info(f"File logging enabled. Logs directory: {log_dir}")


def _get_log_directory() -> Path:
    """Get the appropriate log directory based on environment."""
    # Check for custom log directory from environment
    custom_log_dir = os.getenv("LOG_DIR")
    if custom_log_dir:
        log_dir = Path(custom_log_dir)
    else:
        # Default to logs/ directory
        log_dir = Path("logs")
    
    # Create directory if it doesn't exist
    log_dir.mkdir(parents=True, exist_ok=True)
    return log_dir


def get_logger(name: str):
    """Get a logger instance for a specific module."""
    return logger.bind(name=name)