bhavinmatariya commited on
Commit
ddbf24a
·
1 Parent(s): 395fb5a

Fix Runtime error

Browse files
Files changed (2) hide show
  1. Dockerfile +1 -0
  2. api/logging_config.py +68 -29
Dockerfile CHANGED
@@ -99,6 +99,7 @@ exit $?' > /app/start.sh && chmod +x /app/start.sh
99
  ENV PORT=8001
100
  ENV NODE_ENV=production
101
  ENV SERVER_BASE_URL=http://localhost:${PORT:-8001}
 
102
 
103
  # Create empty .env file (will be overridden if one exists at runtime)
104
  RUN touch .env
 
99
  ENV PORT=8001
100
  ENV NODE_ENV=production
101
  ENV SERVER_BASE_URL=http://localhost:${PORT:-8001}
102
+ ENV DISABLE_FILE_LOGGING=true
103
 
104
  # Create empty .env file (will be overridden if one exists at runtime)
105
  RUN touch .env
api/logging_config.py CHANGED
@@ -18,31 +18,59 @@ def setup_logging(format: str = None):
18
  LOG_FILE_PATH: Path to log file (default: logs/application.log)
19
  LOG_MAX_SIZE: Max size in MB before rotating (default: 10MB)
20
  LOG_BACKUP_COUNT: Number of backup files to keep (default: 5)
 
21
 
22
  Ensures log directory exists, prevents path traversal, and configures
23
- both rotating file and console handlers.
 
24
  """
 
 
 
25
  # Determine log directory and default file path
26
  base_dir = Path(__file__).parent
27
- log_dir = base_dir / "logs"
28
- log_dir.mkdir(parents=True, exist_ok=True)
29
- default_log_file = log_dir / "application.log"
 
 
 
 
 
 
 
 
 
 
 
 
 
30
 
31
  # Get log level from environment
32
  log_level_str = os.environ.get("LOG_LEVEL", "INFO").upper()
33
  log_level = getattr(logging, log_level_str, logging.INFO)
34
 
35
- # Get log file path
36
- log_file_path = Path(os.environ.get("LOG_FILE_PATH", str(default_log_file)))
37
-
38
- # Secure path check: must be inside logs/ directory
39
- log_dir_resolved = log_dir.resolve()
40
- resolved_path = log_file_path.resolve()
41
- if not str(resolved_path).startswith(str(log_dir_resolved) + os.sep):
42
- raise ValueError(f"LOG_FILE_PATH '{log_file_path}' is outside the trusted log directory '{log_dir_resolved}'")
43
-
44
- # Ensure parent directories exist
45
- resolved_path.parent.mkdir(parents=True, exist_ok=True)
 
 
 
 
 
 
 
 
 
 
46
 
47
  # Get max log file size (default: 10MB)
48
  try:
@@ -60,26 +88,37 @@ def setup_logging(format: str = None):
60
  # Configure format
61
  log_format = format or "%(asctime)s - %(levelname)s - %(name)s - %(filename)s:%(lineno)d - %(message)s"
62
 
63
- # Create handlers
64
- file_handler = RotatingFileHandler(resolved_path, maxBytes=max_bytes, backupCount=backup_count, encoding="utf-8")
 
 
65
  console_handler = logging.StreamHandler()
66
-
67
- # Set format for both handlers
68
  formatter = logging.Formatter(log_format)
69
- file_handler.setFormatter(formatter)
70
  console_handler.setFormatter(formatter)
71
-
72
- # Add filter to suppress "Detected file change" messages
73
- file_handler.addFilter(IgnoreLogChangeDetectedFilter())
74
  console_handler.addFilter(IgnoreLogChangeDetectedFilter())
 
 
 
 
 
 
 
 
 
 
 
 
75
 
76
  # Apply logging configuration
77
- logging.basicConfig(level=log_level, handlers=[file_handler, console_handler], force=True)
78
 
79
  # Log configuration info
80
  logger = logging.getLogger(__name__)
81
- logger.debug(
82
- f"Logging configured: level={log_level_str}, "
83
- f"file={resolved_path}, max_size={max_bytes} bytes, "
84
- f"backup_count={backup_count}"
85
- )
 
 
 
 
18
  LOG_FILE_PATH: Path to log file (default: logs/application.log)
19
  LOG_MAX_SIZE: Max size in MB before rotating (default: 10MB)
20
  LOG_BACKUP_COUNT: Number of backup files to keep (default: 5)
21
+ DISABLE_FILE_LOGGING: Set to "true" to disable file logging (default: false)
22
 
23
  Ensures log directory exists, prevents path traversal, and configures
24
+ both rotating file and console handlers. Falls back to console-only logging
25
+ if file logging fails due to permissions.
26
  """
27
+ # Check if file logging should be disabled
28
+ disable_file_logging = os.environ.get("DISABLE_FILE_LOGGING", "false").lower() == "true"
29
+
30
  # Determine log directory and default file path
31
  base_dir = Path(__file__).parent
32
+
33
+ # In containerized environments, use /tmp for logs if the default location isn't writable
34
+ try:
35
+ log_dir = base_dir / "logs"
36
+ log_dir.mkdir(parents=True, exist_ok=True)
37
+ default_log_file = log_dir / "application.log"
38
+ except (PermissionError, OSError):
39
+ # Fall back to /tmp for containerized environments
40
+ log_dir = Path("/tmp/deepwiki-logs")
41
+ try:
42
+ log_dir.mkdir(parents=True, exist_ok=True)
43
+ default_log_file = log_dir / "application.log"
44
+ except (PermissionError, OSError):
45
+ # If even /tmp fails, disable file logging
46
+ disable_file_logging = True
47
+ default_log_file = None
48
 
49
  # Get log level from environment
50
  log_level_str = os.environ.get("LOG_LEVEL", "INFO").upper()
51
  log_level = getattr(logging, log_level_str, logging.INFO)
52
 
53
+ # Get log file path (only if file logging is enabled)
54
+ resolved_path = None
55
+ if not disable_file_logging and default_log_file:
56
+ log_file_path = Path(os.environ.get("LOG_FILE_PATH", str(default_log_file)))
57
+
58
+ # Secure path check: must be inside logs/ directory
59
+ log_dir_resolved = log_dir.resolve()
60
+ resolved_path = log_file_path.resolve()
61
+ if not str(resolved_path).startswith(str(log_dir_resolved) + os.sep):
62
+ print(f"Warning: LOG_FILE_PATH '{log_file_path}' is outside the trusted log directory '{log_dir_resolved}'. Falling back to console logging.")
63
+ disable_file_logging = True
64
+ resolved_path = None
65
+
66
+ # Ensure parent directories exist
67
+ if resolved_path:
68
+ try:
69
+ resolved_path.parent.mkdir(parents=True, exist_ok=True)
70
+ except (PermissionError, OSError):
71
+ print("Warning: Cannot create log directory. Falling back to console logging.")
72
+ disable_file_logging = True
73
+ resolved_path = None
74
 
75
  # Get max log file size (default: 10MB)
76
  try:
 
88
  # Configure format
89
  log_format = format or "%(asctime)s - %(levelname)s - %(name)s - %(filename)s:%(lineno)d - %(message)s"
90
 
91
+ # Create handlers list
92
+ handlers = []
93
+
94
+ # Create console handler (always present)
95
  console_handler = logging.StreamHandler()
 
 
96
  formatter = logging.Formatter(log_format)
 
97
  console_handler.setFormatter(formatter)
 
 
 
98
  console_handler.addFilter(IgnoreLogChangeDetectedFilter())
99
+ handlers.append(console_handler)
100
+
101
+ # Create file handler only if file logging is enabled and path is available
102
+ file_handler = None
103
+ if not disable_file_logging and resolved_path:
104
+ try:
105
+ file_handler = RotatingFileHandler(resolved_path, maxBytes=max_bytes, backupCount=backup_count, encoding="utf-8")
106
+ file_handler.setFormatter(formatter)
107
+ file_handler.addFilter(IgnoreLogChangeDetectedFilter())
108
+ handlers.append(file_handler)
109
+ except (PermissionError, OSError) as e:
110
+ print(f"Warning: Cannot create file handler: {e}. Using console logging only.")
111
 
112
  # Apply logging configuration
113
+ logging.basicConfig(level=log_level, handlers=handlers, force=True)
114
 
115
  # Log configuration info
116
  logger = logging.getLogger(__name__)
117
+ if file_handler and resolved_path:
118
+ logger.debug(
119
+ f"Logging configured: level={log_level_str}, "
120
+ f"file={resolved_path}, max_size={max_bytes} bytes, "
121
+ f"backup_count={backup_count}"
122
+ )
123
+ else:
124
+ logger.debug(f"Logging configured: level={log_level_str}, console only (file logging disabled)")