-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathlogging_config.py
More file actions
112 lines (82 loc) · 2.95 KB
/
logging_config.py
File metadata and controls
112 lines (82 loc) · 2.95 KB
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
107
108
109
110
111
112
"""
Centralized logging configuration for the Agentic Interview System.
This module sets up structured logging with:
- Configurable log level via environment variable
- Console output with timestamp, level, module, and message
- Safe defaults that won't crash the app if misconfigured
Usage:
from logging_config import get_logger
logger = get_logger(__name__)
logger.info("Starting interview session", extra={"session_id": 123})
"""
import logging
import os
import sys
from typing import Optional
# Default log level
DEFAULT_LOG_LEVEL = "INFO"
# Log format: timestamp | level | module | message
LOG_FORMAT = "%(asctime)s | %(levelname)-8s | %(name)s | %(message)s"
DATE_FORMAT = "%Y-%m-%d %H:%M:%S"
def get_log_level_from_env() -> str:
"""
Get log level from environment variable.
Returns:
Log level string (DEBUG, INFO, WARNING, ERROR, CRITICAL)
"""
level = os.getenv("LOG_LEVEL", DEFAULT_LOG_LEVEL).upper()
# Validate level
valid_levels = ["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"]
if level not in valid_levels:
print(f"Warning: Invalid LOG_LEVEL '{level}', using '{DEFAULT_LOG_LEVEL}'", file=sys.stderr)
return DEFAULT_LOG_LEVEL
return level
def configure_logging(level: Optional[str] = None):
"""
Configure the root logger with console output.
Args:
level: Log level string (DEBUG, INFO, etc.). If None, reads from environment.
"""
if level is None:
level = get_log_level_from_env()
# Get numeric level
numeric_level = getattr(logging, level, logging.INFO)
# Configure root logger
root_logger = logging.getLogger()
root_logger.setLevel(numeric_level)
# Remove existing handlers to avoid duplicates
root_logger.handlers.clear()
# Create console handler
console_handler = logging.StreamHandler(sys.stdout)
console_handler.setLevel(numeric_level)
# Create formatter
formatter = logging.Formatter(LOG_FORMAT, datefmt=DATE_FORMAT)
console_handler.setFormatter(formatter)
# Add handler to root logger
root_logger.addHandler(console_handler)
def get_logger(name: str) -> logging.Logger:
"""
Get a logger instance for a module.
Args:
name: Logger name (typically __name__ of the calling module)
Returns:
Configured logger instance
"""
return logging.getLogger(name)
# Configure logging on module import
try:
configure_logging()
except Exception as e:
# Safe fallback: use basicConfig if configuration fails
print(f"Warning: Failed to configure logging: {e}", file=sys.stderr)
logging.basicConfig(level=logging.INFO, format=LOG_FORMAT, datefmt=DATE_FORMAT)
# ==============================================================================
# Public API
# ==============================================================================
__all__ = [
"get_logger",
"configure_logging",
"get_log_level_from_env",
"DEFAULT_LOG_LEVEL",
"LOG_FORMAT",
]