add logging

This commit is contained in:
2025-09-24 11:04:16 +04:00
parent afc808f0d6
commit 994ce07a80
14 changed files with 515 additions and 42 deletions

View File

@@ -21,6 +21,8 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
- Match-3 debug controls include gem count adjustment and board reroll
- Difficulty presets: Easy (3 gems), Normal (5 gems), Hard (8 gems)
- Gameplay mode switching: Space+Enter in game scene switches between match-3 and clickomania modes
- Test scripts located in `tests/` directory for system validation
- Use `test_logging.gd` to validate the logging system functionality
### Audio Configuration
- Music: Located in `assets/audio/music/` directory with loop configuration in AudioManager
@@ -51,11 +53,19 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
- Use F12 key for global debug toggle
- Remove debug prints before committing unless permanently useful
### Logging System Usage
- **ALWAYS** use `DebugManager` logging functions instead of `print()`, `push_error()`, etc.
- Use appropriate log levels: INFO for general messages, WARN for issues, ERROR for failures
- Include meaningful categories to organize log output: `"GameManager"`, `"Match3"`, `"Settings"`
- Leverage structured logging for better debugging and production monitoring
- Use `DebugManager.set_log_level()` to control verbosity during development and testing
## Important File References
### Documentation Structure
- **`docs/MAP.md`** - Complete project architecture and structure
- **`docs/CODE_OF_CONDUCT.md`** - Coding standards and best practices
- **`docs/TESTING.md`** - Testing guidelines and conventions
- **This file** - Claude Code specific development guidelines
### Key Scripts to Understand
@@ -78,12 +88,27 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
- Test debug UI with F12 toggle
- Verify scene transitions work correctly
- Check mobile compatibility if UI changes made
- Use relevant test scripts from `tests/` directory to validate system functionality
- Run `test_logging.gd` after making changes to the logging system
### Common Implementation Patterns
- Scene transitions: Use `GameManager.start_game_with_mode()` and related methods
- Debug integration: Connect to `DebugManager` signals and initialize debug state
- Logging: Use `DebugManager.log_*()` functions with appropriate levels and categories
- Gameplay modes: Implement in `scenes/game/gameplays/` directory following modular pattern
- Scoring system: Connect `score_changed` signal from gameplay to main game scene
- Settings: Use `SettingsManager` for persistent configuration
- Audio: Use `AudioManager` for music and sound effects
- Localization: Use `LocalizationManager` for language switching
### Logging Best Practices
```gdscript
# ✅ Good logging practices
DebugManager.log_info("Scene transition completed", "GameManager")
DebugManager.log_warn("Settings file not found, using defaults", "Settings")
DebugManager.log_error("Failed to load audio resource: " + audio_path, "AudioManager")
# ❌ Avoid these patterns
print("debug") # Use structured logging instead
push_error("error") # Use DebugManager.log_error() with category
```

View File

@@ -123,8 +123,8 @@ func some_deep_function():
### Debug System Integration
- Always connect to DebugManager signals for debug UI
- Use debug prints with clear prefixes
- Remove debug prints before committing (unless permanently useful)
- Use structured logging instead of plain print statements
- Remove temporary debug logs before committing (unless permanently useful)
```gdscript
# ✅ Correct debug integration
@@ -132,27 +132,47 @@ func _connect_to_global_debug() -> void:
DebugManager.debug_ui_toggled.connect(_on_debug_ui_toggled)
debug_ui.visible = DebugManager.is_debug_ui_visible()
# ✅ Good debug prints
print("Match3: Debug UI toggled to: ", visible)
print("TileSystem: Initialized ", tiles.size(), " tiles")
# ✅ Good structured logging
DebugManager.log_debug("Debug UI toggled to: " + str(visible), "Match3")
DebugManager.log_info("Initialized " + str(tiles.size()) + " tiles", "TileSystem")
# ❌ Bad debug prints
print("test") # Not descriptive
print(some_variable) # No context
# ❌ Bad logging practices
print("test") # Not descriptive, use structured logging
print(some_variable) # No context, use proper log level
```
### Logging Standards
- **ALWAYS** use `DebugManager.log_*()` functions instead of `print()` or `push_error()`
- Choose appropriate log levels based on message importance and audience
- Include meaningful categories to organize log output by system/component
- Format messages with clear, descriptive text and relevant context
```gdscript
# ✅ Correct logging usage
DebugManager.log_info("Game scene loaded successfully", "SceneManager")
DebugManager.log_warn("Audio file not found, using default", "AudioManager")
DebugManager.log_error("Failed to save settings: " + error_message, "Settings")
# ❌ Wrong approaches
print("loaded") # Use DebugManager.log_info() with category
push_error("error") # Use DebugManager.log_error() with context
if debug_mode: print("debug info") # Use DebugManager.log_debug()
```
### Error Handling
- Always check if resources loaded successfully
- Use `push_error()` for critical failures
- Use `DebugManager.log_error()` for critical failures
- Provide fallback behavior when possible
- Include meaningful context in error messages
```gdscript
# ✅ Correct error handling
# ✅ Correct error handling with structured logging
func load_scene(path: String) -> void:
var packed_scene := load(path)
if not packed_scene or not packed_scene is PackedScene:
push_error("Failed to load scene at: %s" % path)
DebugManager.log_error("Failed to load scene at: %s" % path, "SceneLoader")
return
DebugManager.log_info("Successfully loaded scene: %s" % path, "SceneLoader")
get_tree().change_scene_to_packed(packed_scene)
```
@@ -253,10 +273,12 @@ func _process(delta):
```gdscript
# ❌ Don't create separate debug systems
var my_debug_enabled = false
print("debug: " + some_info) # Don't use plain print()
# ✅ Use the global debug system
# ✅ Use the global debug and logging systems
if DebugManager.is_debug_enabled():
show_debug_info()
DebugManager.log_debug("Debug information: " + some_info, "MyComponent")
```
## Learning Resources

View File

@@ -15,6 +15,7 @@ skelly/
├── localization/ # Internationalization files
├── scenes/ # Godot scenes (.tscn) and scripts (.gd)
├── src/ # Source code organization
├── tests/ # Test scripts and validation utilities
├── project.godot # Main Godot project configuration
└── icon.svg # Project icon
```
@@ -48,10 +49,13 @@ Located in `src/autoloads/`, these scripts are automatically loaded when the gam
- Uses translation files in `localization/`
5. **DebugManager** (`src/autoloads/DebugManager.gd`)
- Global debug state management
- Global debug state management and centralized logging system
- Debug UI visibility control
- F12 toggle functionality
- Signal-based debug system
- Structured logging with configurable log levels (TRACE, DEBUG, INFO, WARN, ERROR, FATAL)
- Timestamp-based log formatting with category support
- Runtime log level filtering for development and production builds
## Scene Hierarchy & Flow
@@ -175,11 +179,23 @@ assets/
### Game Data (`data/`)
- `default_bus_layout.tres` - Audio bus configuration for Godot
### Documentation (`docs/`)
- `MAP.md` - Project architecture and structure overview
- `CLAUDE.md` - Claude Code development guidelines
- `CODE_OF_CONDUCT.md` - Coding standards and best practices
- `TESTING.md` - Testing guidelines and conventions
### Localization (`localization/`)
- `languages.json` - Available language definitions
- `MainStrings.en.translation` - English translations
- `MainStrings.ru.translation` - Russian translations
### Testing & Validation (`tests/`)
- `test_logging.gd` - DebugManager logging system validation
- `README.md` - Brief directory overview (see docs/TESTING.md for full guidelines)
- Future test scripts for individual components and integration testing
- Temporary test utilities for development and debugging
### Project Configuration
- `project.godot` - Main Godot project settings
- Autoload definitions
@@ -215,6 +231,58 @@ SettingsManager --> localization/languages.json
AudioManager --> data/default_bus_layout.tres
```
## Logging System
The project uses a centralized logging system implemented in DebugManager for consistent, structured logging throughout the application.
### Log Levels
```
TRACE (0) - Detailed execution tracing (debug mode only)
DEBUG (1) - Development debugging information (debug mode only)
INFO (2) - General application information (always visible)
WARN (3) - Warning messages that don't break functionality
ERROR (4) - Error conditions that may affect functionality
FATAL (5) - Critical errors that may cause application failure
```
### Usage Examples
```gdscript
# Basic logging with automatic categorization
DebugManager.log_info("Game started successfully")
DebugManager.log_warn("Settings file not found, using defaults")
DebugManager.log_error("Failed to load audio resource")
# Logging with custom categories for better organization
DebugManager.log_debug("Grid regenerated with 64 tiles", "Match3")
DebugManager.log_info("Language changed to: en", "SettingsManager")
DebugManager.log_error("Invalid scene path provided", "GameManager")
```
### Log Format
```
[timestamp] LEVEL [category]: message
Example: [2025-09-24T10:48:08] INFO [GameManager]: Loading main scene
```
### Runtime Configuration
```gdscript
# Set minimum log level (filters out lower priority messages)
DebugManager.set_log_level(DebugManager.LogLevel.WARN)
# Get current log level
var current_level = DebugManager.get_log_level()
# Check if a specific level would be logged
if DebugManager._should_log(DebugManager.LogLevel.DEBUG):
# Expensive debug calculation here
```
### Integration with Godot Systems
- **WARN/ERROR/FATAL** levels automatically call `push_warning()` and `push_error()`
- **TRACE/DEBUG** levels only display when debug mode is enabled
- **INFO** and higher levels always display regardless of debug mode
- All levels respect the configured minimum log level threshold
## Development Notes
### Current Implementation Status
@@ -233,5 +301,6 @@ AudioManager --> data/default_bus_layout.tres
5. **Data-Driven Configuration** - JSON for settings and translations
6. **Component Architecture** - Reusable UI and game components
7. **Centralized Scoring System** - Global score management across gameplay modes
8. **Structured Logging System** - Centralized logging with level-based filtering and formatted output
This structure provides a clean separation of concerns, making the codebase maintainable and extensible for future features.

156
docs/TESTING.md Normal file
View File

@@ -0,0 +1,156 @@
# Tests Directory
This directory contains test scripts and utilities for validating various systems and components in the Skelly project.
## Overview
The `tests/` directory is designed to house:
- System validation scripts
- Component testing utilities
- Integration tests
- Performance benchmarks
- Debugging tools
## Current Test Files
### `test_logging.gd`
Comprehensive test script for the DebugManager logging system.
**Features:**
- Tests all log levels (TRACE, DEBUG, INFO, WARN, ERROR, FATAL)
- Validates log level filtering functionality
- Tests category-based logging organization
- Verifies debug mode integration
- Demonstrates proper logging usage patterns
**Usage:**
```gdscript
# Option 1: Add as temporary autoload
# In project.godot, add: tests/test_logging.gd
# Option 2: Instantiate in a scene
var test_script = preload("res://tests/test_logging.gd").new()
add_child(test_script)
# Option 3: Run directly from editor
# Open the script and run the scene containing it
```
**Expected Output:**
The script will output formatted log messages demonstrating:
- Proper timestamp formatting
- Log level filtering behavior
- Category organization
- Debug mode dependency for TRACE/DEBUG levels
## Adding New Tests
When creating new test files, follow these conventions:
### File Naming
- Use descriptive names starting with `test_`
- Example: `test_audio_manager.gd`, `test_scene_transitions.gd`
### File Structure
```gdscript
extends Node
# Brief description of what this test validates
func _ready():
# Wait for system initialization if needed
await get_tree().process_frame
run_tests()
func run_tests():
print("=== Starting [System Name] Tests ===")
# Individual test functions
test_basic_functionality()
test_edge_cases()
test_error_conditions()
print("=== [System Name] Tests Complete ===")
func test_basic_functionality():
print("\\n--- Test: Basic Functionality ---")
# Test implementation
func test_edge_cases():
print("\\n--- Test: Edge Cases ---")
# Edge case testing
func test_error_conditions():
print("\\n--- Test: Error Conditions ---")
# Error condition testing
```
### Testing Guidelines
1. **Independence**: Each test should be self-contained and not depend on other tests
2. **Cleanup**: Restore original state after testing (settings, debug modes, etc.)
3. **Clear Output**: Use descriptive print statements to show test progress
4. **Error Handling**: Test both success and failure conditions
5. **Documentation**: Include comments explaining complex test scenarios
### Integration with Main Project
- **Temporary Usage**: Test files are meant to be added temporarily during development
- **Not in Production**: These files should not be included in release builds
- **Autoload Testing**: Add to autoloads temporarily for automatic execution
- **Manual Testing**: Run individually when testing specific components
## Test Categories
### System Tests
Test core autoload managers and global systems:
- `test_logging.gd` - DebugManager logging system
- Future: `test_settings.gd` - SettingsManager functionality
- Future: `test_audio.gd` - AudioManager functionality
- Future: `test_scene_management.gd` - GameManager transitions
### Component Tests
Test individual game components:
- Future: `test_match3.gd` - Match-3 gameplay mechanics
- Future: `test_tile_system.gd` - Tile behavior and interactions
- Future: `test_ui_components.gd` - Menu and UI functionality
### Integration Tests
Test system interactions and workflows:
- Future: `test_game_flow.gd` - Complete game session flow
- Future: `test_debug_system.gd` - Debug UI integration
- Future: `test_localization.gd` - Language switching and translations
## Running Tests
### During Development
1. Copy or symlink the test file to your scene
2. Add as a child node or autoload temporarily
3. Run the project and observe console output
4. Remove from project when testing is complete
### Automated Testing
While Godot doesn't have built-in unit testing, these scripts provide:
- Consistent validation approach
- Repeatable test scenarios
- Clear pass/fail output
- System behavior documentation
## Best Practices
1. **Document Expected Behavior**: Include comments about what should happen
2. **Test Boundary Conditions**: Include edge cases and error conditions
3. **Measure Performance**: Add timing for performance-critical components
4. **Visual Validation**: For UI components, include visual checks
5. **Cleanup After Tests**: Restore initial state to avoid side effects
## Contributing
When adding new test files:
1. Follow the naming and structure conventions
2. Update this README with new test descriptions
3. Ensure tests are self-contained and documented
4. Test both success and failure scenarios
5. Include performance considerations where relevant
This testing approach helps maintain code quality and provides validation tools for system changes and refactoring.

View File

@@ -19,7 +19,7 @@ func _ready():
var orig_stream = _load_stream()
if not orig_stream:
push_error("Failed to load music stream: %s" % MUSIC_PATH)
DebugManager.log_error("Failed to load music stream: %s" % MUSIC_PATH, "AudioManager")
return
var stream = orig_stream.duplicate(true) as AudioStream

View File

@@ -2,16 +2,26 @@ extends Node
signal debug_toggled(enabled: bool)
enum LogLevel {
TRACE = 0,
DEBUG = 1,
INFO = 2,
WARN = 3,
ERROR = 4,
FATAL = 5
}
var debug_enabled: bool = false
var debug_overlay_visible: bool = false
var current_log_level: LogLevel = LogLevel.INFO
func _ready():
print("DebugManager loaded")
log_info("DebugManager loaded")
func toggle_debug():
debug_enabled = !debug_enabled
debug_toggled.emit(debug_enabled)
print("Debug mode: ", "ON" if debug_enabled else "OFF")
log_info("Debug mode: " + ("ON" if debug_enabled else "OFF"))
func set_debug_enabled(enabled: bool):
if debug_enabled != enabled:
@@ -30,6 +40,70 @@ func set_overlay_visible(visible: bool):
func is_overlay_visible() -> bool:
return debug_overlay_visible
func log_debug(message: String, category: String = "DEBUG"):
func set_log_level(level: LogLevel):
current_log_level = level
log_info("Log level set to: " + _log_level_to_string(level))
func get_log_level() -> LogLevel:
return current_log_level
func _should_log(level: LogLevel) -> bool:
return level >= current_log_level
func _log_level_to_string(level: LogLevel) -> String:
match level:
LogLevel.TRACE:
return "TRACE"
LogLevel.DEBUG:
return "DEBUG"
LogLevel.INFO:
return "INFO"
LogLevel.WARN:
return "WARN"
LogLevel.ERROR:
return "ERROR"
LogLevel.FATAL:
return "FATAL"
_:
return "UNKNOWN"
func _format_log_message(level: LogLevel, message: String, category: String = "") -> String:
var timestamp = Time.get_datetime_string_from_system()
var level_str = _log_level_to_string(level)
var category_str = (" [" + category + "]") if category != "" else ""
return "[%s] %s%s: %s" % [timestamp, level_str, category_str, message]
func log_trace(message: String, category: String = ""):
if _should_log(LogLevel.TRACE):
var formatted = _format_log_message(LogLevel.TRACE, message, category)
if debug_enabled:
print("[", category, "] ", message)
print(formatted)
func log_debug(message: String, category: String = ""):
if _should_log(LogLevel.DEBUG):
var formatted = _format_log_message(LogLevel.DEBUG, message, category)
if debug_enabled:
print(formatted)
func log_info(message: String, category: String = ""):
if _should_log(LogLevel.INFO):
var formatted = _format_log_message(LogLevel.INFO, message, category)
print(formatted)
func log_warn(message: String, category: String = ""):
if _should_log(LogLevel.WARN):
var formatted = _format_log_message(LogLevel.WARN, message, category)
print(formatted)
push_warning(formatted)
func log_error(message: String, category: String = ""):
if _should_log(LogLevel.ERROR):
var formatted = _format_log_message(LogLevel.ERROR, message, category)
print(formatted)
push_error(formatted)
func log_fatal(message: String, category: String = ""):
if _should_log(LogLevel.FATAL):
var formatted = _format_log_message(LogLevel.FATAL, message, category)
print(formatted)
push_error(formatted)

View File

@@ -18,7 +18,7 @@ func start_game_with_mode(gameplay_mode: String) -> void:
pending_gameplay_mode = gameplay_mode
var packed_scene := load(GAME_SCENE_PATH)
if not packed_scene or not packed_scene is PackedScene:
push_error("Failed to load Game scene at: %s" % GAME_SCENE_PATH)
DebugManager.log_error("Failed to load Game scene at: %s" % GAME_SCENE_PATH, "GameManager")
return
get_tree().change_scene_to_packed(packed_scene)
# Wait one frame for the scene to be ready, then set gameplay mode
@@ -27,14 +27,13 @@ func start_game_with_mode(gameplay_mode: String) -> void:
get_tree().current_scene.set_gameplay_mode(pending_gameplay_mode)
func save_game() -> void:
print("Game saved (mock)")
DebugManager.log_info("Game saved (mock)", "GameManager")
func exit_to_main_menu() -> void:
print("GameManager: Attempting to exit to main menu")
DebugManager.log_info("Attempting to exit to main menu", "GameManager")
var packed_scene := load(MAIN_SCENE_PATH)
if not packed_scene or not packed_scene is PackedScene:
push_error("Failed to load Main scene at: %s" % MAIN_SCENE_PATH)
DebugManager.log_error("Failed to load Main scene at: %s" % MAIN_SCENE_PATH, "GameManager")
return
print("GameManager: Loading main scene")
DebugManager.log_info("Loading main scene", "GameManager")
get_tree().change_scene_to_packed(packed_scene)

View File

@@ -18,7 +18,7 @@ var default_settings = {
var languages_data = {}
func _ready():
print("SettingsManager ready")
DebugManager.log_info("SettingsManager ready", "SettingsManager")
load_languages()
load_settings()
@@ -27,10 +27,10 @@ func load_settings():
if config.load(SETTINGS_FILE) == OK:
for key in default_settings.keys():
settings[key] = config.get_value("settings", key, default_settings[key])
print("Settings loaded: ", settings)
DebugManager.log_info("Settings loaded: " + str(settings), "SettingsManager")
else:
print("No settings file found, using defaults")
print("Language is set to: ", settings["language"])
DebugManager.log_warn("No settings file found, using defaults", "SettingsManager")
DebugManager.log_info("Language is set to: " + str(settings["language"]), "SettingsManager")
TranslationServer.set_locale(settings["language"])
AudioServer.set_bus_volume_db(AudioServer.get_bus_index("Master"), linear_to_db(settings["master_volume"]))
AudioServer.set_bus_volume_db(AudioServer.get_bus_index("Music"), linear_to_db(settings["music_volume"]))
@@ -42,7 +42,7 @@ func save_settings():
for key in settings.keys():
config.set_value("settings", key, settings[key])
config.save(SETTINGS_FILE)
print("Settings saved: ", settings)
DebugManager.log_info("Settings saved: " + str(settings), "SettingsManager")
func get_setting(key: String):
return settings.get(key)
@@ -65,7 +65,7 @@ func _apply_setting_side_effect(key: String, value) -> void:
func load_languages():
var file = FileAccess.open(LANGUAGES_JSON_PATH, FileAccess.READ)
if not file:
print("Could not open languages.json")
DebugManager.log_error("Could not open languages.json", "SettingsManager")
return
var json_string = file.get_as_text()
@@ -73,12 +73,12 @@ func load_languages():
var json = JSON.new()
if json.parse(json_string) != OK:
print("Error parsing languages.json")
DebugManager.log_error("Error parsing languages.json", "SettingsManager")
return
languages_data = json.data
if languages_data.has("languages"):
print("Languages loaded: ", languages_data.languages.keys())
DebugManager.log_info("Languages loaded: " + str(languages_data.languages.keys()), "SettingsManager")
func get_languages_data():
return languages_data

22
tests/README.md Normal file
View File

@@ -0,0 +1,22 @@
# Tests Directory
This directory contains test scripts and validation utilities for the Skelly project.
## Documentation
For complete testing guidelines, conventions, and usage instructions, see:
**[docs/TESTING.md](../docs/TESTING.md)**
## Current Files
- `test_logging.gd` - Comprehensive logging system validation script
## Quick Usage
```gdscript
# Add as temporary autoload or run in scene
var test_script = preload("res://tests/test_logging.gd").new()
add_child(test_script)
```
See [docs/TESTING.md](../docs/TESTING.md) for detailed usage instructions and conventions.

106
tests/test_logging.gd Normal file
View File

@@ -0,0 +1,106 @@
extends Node
# Test script for the DebugManager logging system
# This script validates all log levels, filtering, and formatting functionality
# Usage: Add to scene or autoload temporarily to run tests
func _ready():
# Wait a frame for DebugManager to initialize
await get_tree().process_frame
test_logging_system()
func test_logging_system():
print("=== Starting Logging System Tests ===")
# Test 1: Basic log level functionality
test_basic_logging()
# Test 2: Log level filtering
test_log_level_filtering()
# Test 3: Category functionality
test_category_logging()
# Test 4: Debug mode integration
test_debug_mode_integration()
print("=== Logging System Tests Complete ===")
func test_basic_logging():
print("\n--- Test 1: Basic Log Level Functionality ---")
# Reset to INFO level for consistent testing
DebugManager.set_log_level(DebugManager.LogLevel.INFO)
DebugManager.log_trace("TRACE: This should not appear (below INFO level)")
DebugManager.log_debug("DEBUG: This should not appear (below INFO level)")
DebugManager.log_info("INFO: This message should appear")
DebugManager.log_warn("WARN: This warning should appear")
DebugManager.log_error("ERROR: This error should appear")
DebugManager.log_fatal("FATAL: This fatal error should appear")
func test_log_level_filtering():
print("\n--- Test 2: Log Level Filtering ---")
# Test DEBUG level
print("Setting log level to DEBUG...")
DebugManager.set_log_level(DebugManager.LogLevel.DEBUG)
DebugManager.log_trace("TRACE: Should not appear (below DEBUG)")
DebugManager.log_debug("DEBUG: Should appear with debug enabled")
DebugManager.log_info("INFO: Should appear")
# Test ERROR level (very restrictive)
print("Setting log level to ERROR...")
DebugManager.set_log_level(DebugManager.LogLevel.ERROR)
DebugManager.log_debug("DEBUG: Should not appear (below ERROR)")
DebugManager.log_warn("WARN: Should not appear (below ERROR)")
DebugManager.log_error("ERROR: Should appear")
DebugManager.log_fatal("FATAL: Should appear")
# Reset to INFO for remaining tests
DebugManager.set_log_level(DebugManager.LogLevel.INFO)
func test_category_logging():
print("\n--- Test 3: Category Functionality ---")
DebugManager.log_info("Message without category")
DebugManager.log_info("Message with TEST category", "TEST")
DebugManager.log_info("Message with LOGGING category", "LOGGING")
DebugManager.log_warn("Warning with VALIDATION category", "VALIDATION")
DebugManager.log_error("Error with SYSTEM category", "SYSTEM")
func test_debug_mode_integration():
print("\n--- Test 4: Debug Mode Integration ---")
# Set to TRACE level to test debug mode dependency
DebugManager.set_log_level(DebugManager.LogLevel.TRACE)
var original_debug_state = DebugManager.is_debug_enabled()
# Test with debug mode OFF
DebugManager.set_debug_enabled(false)
print("Debug mode OFF - TRACE and DEBUG should not appear:")
DebugManager.log_trace("TRACE: Should NOT appear (debug mode OFF)")
DebugManager.log_debug("DEBUG: Should NOT appear (debug mode OFF)")
DebugManager.log_info("INFO: Should appear regardless of debug mode")
# Test with debug mode ON
DebugManager.set_debug_enabled(true)
print("Debug mode ON - TRACE and DEBUG should appear:")
DebugManager.log_trace("TRACE: Should appear (debug mode ON)")
DebugManager.log_debug("DEBUG: Should appear (debug mode ON)")
DebugManager.log_info("INFO: Should still appear")
# Restore original debug state
DebugManager.set_debug_enabled(original_debug_state)
DebugManager.set_log_level(DebugManager.LogLevel.INFO)
# Helper function to validate log level enum values
func test_log_level_enum():
print("\n--- Log Level Enum Values ---")
print("TRACE: ", DebugManager.LogLevel.TRACE)
print("DEBUG: ", DebugManager.LogLevel.DEBUG)
print("INFO: ", DebugManager.LogLevel.INFO)
print("WARN: ", DebugManager.LogLevel.WARN)
print("ERROR: ", DebugManager.LogLevel.ERROR)
print("FATAL: ", DebugManager.LogLevel.FATAL)