MogensR commited on
Commit
01b7e60
·
1 Parent(s): 783cf8c

Update utils/logger.py

Browse files
Files changed (1) hide show
  1. utils/logger.py +55 -10
utils/logger.py CHANGED
@@ -1,3 +1,4 @@
 
1
  """
2
  Logging Management Module
3
  ========================
@@ -28,7 +29,8 @@
28
  import traceback
29
  from functools import wraps
30
  import time
31
- from typing import Dict, List
 
32
 
33
  class ColoredFormatter(logging.Formatter):
34
  """Custom formatter with colors for console output"""
@@ -50,6 +52,7 @@ def format(self, record):
50
 
51
  return super().format(record)
52
 
 
53
  class BackgroundFXLogger:
54
  """Main logger class for BackgroundFX Pro"""
55
 
@@ -82,6 +85,13 @@ def __init__(self,
82
  # Performance tracking
83
  self.performance_data = {}
84
  self.start_times = {}
 
 
 
 
 
 
 
85
 
86
  def _setup_handlers(self):
87
  """Setup logging handlers for console and file output"""
@@ -106,7 +116,8 @@ def _setup_handlers(self):
106
  file_handler = logging.handlers.RotatingFileHandler(
107
  main_log_file,
108
  maxBytes=10*1024*1024, # 10MB
109
- backupCount=5
 
110
  )
111
  file_handler.setLevel(self.level)
112
 
@@ -123,7 +134,8 @@ def _setup_handlers(self):
123
  error_handler = logging.handlers.RotatingFileHandler(
124
  error_log_file,
125
  maxBytes=5*1024*1024, # 5MB
126
- backupCount=3
 
127
  )
128
  error_handler.setLevel(logging.ERROR)
129
  error_handler.setFormatter(file_formatter)
@@ -247,8 +259,11 @@ def _save_performance_data(self):
247
  # Load existing data
248
  existing_data = {}
249
  if self.performance_log_file.exists():
250
- with open(self.performance_log_file, 'r') as f:
251
- existing_data = json.load(f)
 
 
 
252
 
253
  # Merge with new data
254
  existing_data.update(self.performance_data)
@@ -260,7 +275,7 @@ def _save_performance_data(self):
260
  existing_data = {k: existing_data[k] for k in keep_keys}
261
 
262
  # Save updated data
263
- with open(self.performance_log_file, 'w') as f:
264
  json.dump(existing_data, f, indent=2)
265
 
266
  except Exception as e:
@@ -271,7 +286,7 @@ def get_log_files(self) -> Dict[str, str]:
271
  return {
272
  'main_log': str(self.logs_dir / "backgroundfx.log"),
273
  'error_log': str(self.logs_dir / "errors.log"),
274
- 'performance_log': str(self.logs_dir / "performance.json"),
275
  'logs_directory': str(self.logs_dir)
276
  }
277
 
@@ -283,13 +298,13 @@ def get_recent_logs(self, lines: int = 50) -> Dict[str, List[str]]:
283
  # Main log
284
  main_log_file = self.logs_dir / "backgroundfx.log"
285
  if main_log_file.exists():
286
- with open(main_log_file, 'r') as f:
287
  logs['main'] = f.readlines()[-lines:]
288
 
289
  # Error log
290
  error_log_file = self.logs_dir / "errors.log"
291
  if error_log_file.exists():
292
- with open(error_log_file, 'r') as f:
293
  logs['errors'] = f.readlines()[-lines:]
294
 
295
  except Exception as e:
@@ -297,9 +312,11 @@ def get_recent_logs(self, lines: int = 50) -> Dict[str, List[str]]:
297
 
298
  return logs
299
 
 
300
  # Global logger instance
301
  _global_logger: Optional[BackgroundFXLogger] = None
302
 
 
303
  def setup_logging(logs_dir: str = "LOGS",
304
  level: int = logging.INFO,
305
  console_output: bool = True,
@@ -318,6 +335,16 @@ def setup_logging(logs_dir: str = "LOGS",
318
 
319
  return _global_logger
320
 
 
 
 
 
 
 
 
 
 
 
321
  def get_logger(name: str = None) -> BackgroundFXLogger:
322
  """Get logger instance"""
323
  if _global_logger is None:
@@ -336,6 +363,7 @@ def get_logger(name: str = None) -> BackgroundFXLogger:
336
 
337
  return _global_logger
338
 
 
339
  def log_function_call(logger: BackgroundFXLogger = None):
340
  """Decorator to log function calls with timing"""
341
  if logger is None:
@@ -362,6 +390,7 @@ def wrapper(*args, **kwargs):
362
  return wrapper
363
  return decorator
364
 
 
365
  def log_processing_pipeline():
366
  """Decorator for logging processing pipeline steps"""
367
  logger = get_logger()
@@ -384,6 +413,7 @@ def wrapper(*args, **kwargs):
384
  return wrapper
385
  return decorator
386
 
 
387
  # Convenience functions
388
  def log_info(message: str, **kwargs):
389
  """Quick info logging"""
@@ -401,10 +431,25 @@ def log_debug(message: str, **kwargs):
401
  """Quick debug logging"""
402
  get_logger().debug(message, **kwargs)
403
 
 
404
  # Initialize logging on module import
405
  if _global_logger is None:
406
  try:
407
  setup_logging()
408
  log_info("✅ Logging system initialized")
409
  except Exception as e:
410
- print(f"⚠️ Failed to initialize logging: {e}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
  """
3
  Logging Management Module
4
  ========================
 
29
  import traceback
30
  from functools import wraps
31
  import time
32
+ from typing import Dict, List
33
+
34
 
35
  class ColoredFormatter(logging.Formatter):
36
  """Custom formatter with colors for console output"""
 
52
 
53
  return super().format(record)
54
 
55
+
56
  class BackgroundFXLogger:
57
  """Main logger class for BackgroundFX Pro"""
58
 
 
85
  # Performance tracking
86
  self.performance_data = {}
87
  self.start_times = {}
88
+
89
+ def __getattr__(self, name):
90
+ """
91
+ Delegate unknown attributes/methods to the underlying stdlib logger.
92
+ This makes BackgroundFXLogger behave like logging.Logger where needed.
93
+ """
94
+ return getattr(self.logger, name)
95
 
96
  def _setup_handlers(self):
97
  """Setup logging handlers for console and file output"""
 
116
  file_handler = logging.handlers.RotatingFileHandler(
117
  main_log_file,
118
  maxBytes=10*1024*1024, # 10MB
119
+ backupCount=5,
120
+ encoding="utf-8"
121
  )
122
  file_handler.setLevel(self.level)
123
 
 
134
  error_handler = logging.handlers.RotatingFileHandler(
135
  error_log_file,
136
  maxBytes=5*1024*1024, # 5MB
137
+ backupCount=3,
138
+ encoding="utf-8"
139
  )
140
  error_handler.setLevel(logging.ERROR)
141
  error_handler.setFormatter(file_formatter)
 
259
  # Load existing data
260
  existing_data = {}
261
  if self.performance_log_file.exists():
262
+ with open(self.performance_log_file, 'r', encoding="utf-8") as f:
263
+ try:
264
+ existing_data = json.load(f)
265
+ except json.JSONDecodeError:
266
+ existing_data = {}
267
 
268
  # Merge with new data
269
  existing_data.update(self.performance_data)
 
275
  existing_data = {k: existing_data[k] for k in keep_keys}
276
 
277
  # Save updated data
278
+ with open(self.performance_log_file, 'w', encoding="utf-8") as f:
279
  json.dump(existing_data, f, indent=2)
280
 
281
  except Exception as e:
 
286
  return {
287
  'main_log': str(self.logs_dir / "backgroundfx.log"),
288
  'error_log': str(self.logs_dir / "errors.log"),
289
+ 'performance_log': str(self.performance_log_file),
290
  'logs_directory': str(self.logs_dir)
291
  }
292
 
 
298
  # Main log
299
  main_log_file = self.logs_dir / "backgroundfx.log"
300
  if main_log_file.exists():
301
+ with open(main_log_file, 'r', encoding="utf-8") as f:
302
  logs['main'] = f.readlines()[-lines:]
303
 
304
  # Error log
305
  error_log_file = self.logs_dir / "errors.log"
306
  if error_log_file.exists():
307
+ with open(error_log_file, 'r', encoding="utf-8") as f:
308
  logs['errors'] = f.readlines()[-lines:]
309
 
310
  except Exception as e:
 
312
 
313
  return logs
314
 
315
+
316
  # Global logger instance
317
  _global_logger: Optional[BackgroundFXLogger] = None
318
 
319
+
320
  def setup_logging(logs_dir: str = "LOGS",
321
  level: int = logging.INFO,
322
  console_output: bool = True,
 
335
 
336
  return _global_logger
337
 
338
+
339
+ # --- Backward-compat alias for legacy imports ---
340
+ def setup_logger(*args, **kwargs):
341
+ """
342
+ Alias for old code: `from utils.logger import setup_logger`.
343
+ Behaves the same as setup_logging and returns a BackgroundFXLogger.
344
+ """
345
+ return setup_logging(*args, **kwargs)
346
+
347
+
348
  def get_logger(name: str = None) -> BackgroundFXLogger:
349
  """Get logger instance"""
350
  if _global_logger is None:
 
363
 
364
  return _global_logger
365
 
366
+
367
  def log_function_call(logger: BackgroundFXLogger = None):
368
  """Decorator to log function calls with timing"""
369
  if logger is None:
 
390
  return wrapper
391
  return decorator
392
 
393
+
394
  def log_processing_pipeline():
395
  """Decorator for logging processing pipeline steps"""
396
  logger = get_logger()
 
413
  return wrapper
414
  return decorator
415
 
416
+
417
  # Convenience functions
418
  def log_info(message: str, **kwargs):
419
  """Quick info logging"""
 
431
  """Quick debug logging"""
432
  get_logger().debug(message, **kwargs)
433
 
434
+
435
  # Initialize logging on module import
436
  if _global_logger is None:
437
  try:
438
  setup_logging()
439
  log_info("✅ Logging system initialized")
440
  except Exception as e:
441
+ print(f"⚠️ Failed to initialize logging: {e}")
442
+
443
+
444
+ __all__ = [
445
+ "BackgroundFXLogger",
446
+ "setup_logging",
447
+ "setup_logger", # alias for legacy code
448
+ "get_logger",
449
+ "log_function_call",
450
+ "log_processing_pipeline",
451
+ "log_info",
452
+ "log_error",
453
+ "log_warning",
454
+ "log_debug",
455
+ ]