logcoe is designed as a lightweight, thread-safe logging library that provides flexible output management with minimal performance overhead. The architecture follows a singleton pattern with internal implementation hiding for API stability.
┌─────────────────────────────────────┐
│ User Application │
│ (Client Code) │
└──────────────────┬──────────────────┘
│
┌──────────────────▼──────────────────┐
│ logcoe API │
│ (Public Interface Functions) │
└──────────────────┬──────────────────┘
│
┌──────────────────▼──────────────────┐
│ LoggerImpl │
│ (Internal Implementation) │
│ │
│ ┌─────────────┬─────────────────┐ │
│ │ Mutex │ Output Streams │ │
│ │ Protection │ Management │ │
│ └─────────────┴─────────────────┘ │
│ ┌─────────────┬─────────────────┐ │
│ │ Log Level │ Timestamp │ │
│ │ Filtering │ Formatting │ │
│ └─────────────┴─────────────────┘ │
└─────────────────────────────────────┘
- File:
include/logcoe.hpp - Purpose: Provides clean, stable interface for client applications
- Key Features:
- Simple function-based API
- No exposed implementation details
- Header-only public interface
- All functions forward to LoggerImpl
- File:
src/logcoe.cpp(anonymous namespace) - Purpose: Contains all logging logic and state management
- Design Pattern: Singleton with static members
static std::mutex s_mutex;- Ensures thread-safe access to all static members and operations
static LogLevel s_logLevel;
static bool s_useFile;
static bool s_useConsole;
static std::string s_timeFormat;- Maintains current logger configuration, Can be changed at runtime
static std::string s_filename;
static std::ofstream s_fileStream;
static std::ostream* s_consoleStream;- File Output: Direct file stream management with automatic opening/closing
- Console Output: Configurable output stream (default: std::cout)
initialize() called
↓
Acquire mutex lock
↓
Set configuration parameters
↓
Open file stream (if enabled)
↓
Set console stream pointer
↓
Write initialization message
↓
Release mutex lock
debug/info/warning/error() called
↓
log() internal function
↓
Acquire mutex lock
↓
Check log level filtering
↓
Generate timestamp
↓
Format message with metadata
↓
writeToOutputs()
↓
Write to console (if enabled)
↓
Write to file (if enabled)
↓
Flush streams (if requested)
↓
Release mutex lock
setLogLevel/setFileOutput/etc() called
↓
Acquire mutex lock
↓
Flush existing streams
↓
Update configuration
↓
Reinitialize streams (if needed)
↓
Release mutex lock
- Single Global Mutex:
std::mutex s_mutex - Lock Scope: Every public API call acquires lock for entire duration
- Configuration Consistency: All threads see consistent logger state
- Message Integrity: No interleaved log messages
- Stream Safety: No concurrent access to output streams
- Atomic Updates: Configuration changes are atomic
std::time_t time_t_now = std::chrono::system_clock::to_time_t(now);
std::tm tm_now;
#ifdef _WIN32
localtime_s(&tm_now, &time_t_now);
#else
localtime_r(&time_t_now, &tm_now);
#endif- Windows: Uses
localtime_sfor thread safety - Unix/Linux/macOS: Uses
localtime_rfor thread safety
- Path Handling: Uses standard C++ filesystem operations
- File Permissions: Relies on OS default permissions
- CMake: FetchContent compatible
- Compiler Support: C++17 standard requirements
- Library Type: Static library
- Lifetime: All state stored in static variables
- Initialization: Lazy initialization through
initialize() - Cleanup: Explicit cleanup through
shutdown()
- File Streams: RAII through std::ofstream
- Memory Allocation: No dynamic allocation for core operations
- Exception Safety: Basic exception safety guarantees
DEBUG (0) < INFO (1) < WARNING (2) < ERROR (3) < NONE (4)
if (static_cast<int>(level) < static_cast<int>(s_logLevel))
return;- Numeric Comparison: Log levels assigned integer values
- Early Return: Filtered messages exit immediately
[timestamp] [LEVEL] [source]: <message>
- Timestamp: Configurable format using strftime
- Level: String representation of LogLevel enum
- Source: Optional component identifier
- Message: User-provided content
- File Open Errors: Logged to console, file output disabled
- Write Failures: Silent failure, no exceptions
- Configuration Errors: Invalid settings ignored with warnings
- No Exceptions: Public API designed to never throw exceptions
- Resource Safety: RAII ensures proper resource cleanup
- State Consistency: Mutex ensures consistent state even with errors
- Logging: O(1) for level filtering, O(log_message_length) for formatting
- Configuration: O(1) for most operations
- Thread Contention: Minimal with short lock durations