plog

repository·master·Indexed 25 days ago

https://github.com/sergiusthebest/plog

A portable, simple, and extensible header-only C++ logging library. Plog is lightweight (approx. 1000 LOC) and provides features such as CSV formatting, wide string support, and various appenders (RollingFile, Console, Android, Windows Event Log) without external dependencies. It supports multiple independent loggers, runtime severity changes, and integration via CMake, vcpkg, Conan, and NuGet.

Tokens
5.7K
Snippets
21
Records
35
Agent score
33%

What's inside plog

  1. Share log instances across binary modules

    master

    When working with multiple binaries (EXE, DLL, SO, DYLIB), you can choose between local instances (one per module) or shared instances (all modules use the same instance).

    Windows

    • Shared: Use PLOG_EXPORT in the providing module and PLOG_IMPORT in the consuming modules.
    • Local: Default behavior.

    Linux/Unix

    • Shared: Use PLOG_GLOBAL.
    • Local: Use PLOG_LOCAL.
    • Note: If no macro is specified, behavior depends on compiler visibility settings (e.g., -fvisibility).
  2. Chain loggers between modules

    master

    A Logger can act as an Appender for another Logger. This pattern is useful for streaming logs from a shared library into the main application's logger.

    // --- In Shared Library ---
    extern "C" void EXPORT initialize(plog::Severity severity, plog::IAppender* appender) {
        plog::init(severity, appender);
    }
    
    extern "C" void EXPORT foo() {
        PLOGI << "Hello from shared lib!";
    }
    
    // --- In Main App ---
    extern "C" void initialize(plog::Severity severity, plog::IAppender* appender);
    extern "C" void foo();
    
    int main() {
        plog::init(plog::debug, "ChainedApp.txt"); // Main logger
        
        // Pass the main logger as an appender to the shared library
        initialize(plog::debug, plog::get()); 
        foo(); 
        return 0;
    }
  3. Use different Appenders to output log data

    master

    An Appender is responsible for outputting log data to a destination (file, console, etc.). All appenders implement the IAppender interface. Plog provides several built-in appenders:

    • RollingFileAppender<Formatter, Converter>: Outputs to a file with rolling behavior.
      • fileName: Log file name.
      • maxFileSize: Max size in bytes (minimum 1000 bytes). If 0, rolling is disabled.
      • maxFiles: Number of files to keep. If 0, rolling is disabled.
    • ConsoleAppender<Formatter>: Outputs to stdout or stderr.
    • ColorConsoleAppender<Formatter>: Outputs to stdout or stderr with colors based on severity.
    • AndroidAppender<Formatter>: Uses the Android logging system (viewable via logcat). Requires a tag.
    • EventLogAppender<Formatter>: Outputs to the Windows Event Log. Requires a unique sourceName and must be registered in the Windows registry using EventLogAppenderRegistry (requires administrator rights).
    • DebugOutputAppender<Formatter>: Sends data to the debugger (Windows only).
    • ArduinoAppender<Formatter>: Outputs to an Arduino Stream object (e.g., Serial).
    • DynamicAppender: A thread-safe wrapper that allows adding or removing appenders at runtime using addAppender and removeAppender.
    class IAppender
    {
    public:
        virtual ~IAppender();
        virtual void write(const Record& record) = 0;
    };
  4. How Plog's core components work together

    master

    Plog is composed of five functional parts that work in a pipeline to process log data:

    1. PLOG macro: The entry point that initiates a log event.
    2. Record: An object that captures all log data (time, severity, thread ID, source file, line, function, message, etc.).
    3. Logger: A singleton center object that manages configuration and dispatches records to appenders.
    4. Appender: Represents the destination for log data (e.g., file, console, Android appender).
    5. Formatter: Responsible for turning a Record into a string representation (e.g., TxtFormatter, CsvFormatter).
    6. Converter: Converts the formatted string into a raw buffer (e.g., UTF8Converter, NativeEOLConverter) before the Appender writes it.

    Data Flow: PLOG macro $\rightarrow$ Record $\rightarrow$ Logger $\rightarrow$ Appender $\rightarrow$ Formatter $\rightarrow$ Converter $\rightarrow$ Appender $\rightarrow$ Finish

  5. Understand the Record object and data capture

    master

    The Record object stores all metadata associated with a log event, including time, severity, thread ID, source line, file name, function name, and the message itself.

    Data Capture Configuration:

    • Source file name: Not captured by default. Enable it by defining PLOG_CAPTURE_FILE.
    • Function name: Captured by default. Disable it by defining PLOG_NO_CAPTURE_FUNCTION_NAME.

    Record supports overloaded stream output operators (operator<<) to construct messages using various types.

  6. Quickstart: Hello log!

    master

    To use Plog, follow these three steps:

    1. Include headers: Add #include <plog/Log.h> to your files.
    2. Initialize: Call plog::init() with a severity level and a destination (e.g., a filename).
    3. Log messages: Use one of the provided macros to write logs.

    Available macro styles include:

    • Short macros: PLOGD << "msg"; (Debug), PLOGI << "msg"; (Info), etc.
    • Long macros: PLOG_DEBUG << "msg";
    • Function-style macros: PLOG(plog::debug) << "msg";

    Note: LOG_XXX macros are also available but may clash with other libraries.

    #include <plog/Log.h>
    #include "plog/Initializers/RollingFileInitializer.h"
    
    int main()
    {
        plog::init(plog::debug, "Hello.txt"); // Step2: initialize the logger
    
        // Step3: write log messages
        PLOGD << "Hello log!"; // short macro
        PLOG_DEBUG << "Hello log!"; // long macro
        PLOG(plog::debug) << "Hello log!"; // function-style macro
    
        return 0;
    }
  7. Manual logger initialization with IAppender

    master

    For custom setups, include #include <plog/Init.h> and call plog::init with a manually constructed appender.

    Important: The appender must be managed by the user and its lifetime should be static to ensure it remains valid for the duration of the program.

    #include <plog/Log.h>
    #include <plog/Init.h>
    
    static plog::ConsoleAppender<plog::TxtFormatter> appender;
    plog::init(plog::info, &appender); // logs info and above to the specified appender
  8. Integrate Plog with CMake using `FetchContent`

    master

    Use CMake's FetchContent module to automatically download Plog at configure time. This is useful for ensuring a specific version is used without manual management.

    include(FetchContent)
    
    FetchContent_Declare(
        plog
        GIT_REPOSITORY https://github.com/SergiusTheBest/plog
        GIT_TAG        1.1.10
        GIT_SHALLOW    true
    )
    FetchContent_MakeAvailable(plog) # Downloads and adds plog to your CMake project
    
    add_executable(myproj main.cpp)
    target_link_libraries(myproj plog::plog) # Links and sets include path
  9. Integrate Plog with CMake using `add_subdirectory`

    master

    If Plog is already present in your source tree, use add_subdirectory to include it in your CMake build. Link against the plog::plog target to automatically set up include paths.

    add_subdirectory(3rd-party/plog) # Adds plog to your CMake project
    
    add_executable(myproj main.cpp)
    target_link_libraries(myproj plog::plog) # Links and sets include path
  10. Explore plog samples

    master

    Plog provides a wide variety of samples to demonstrate specific features and integration patterns. Key samples include:

    • Appenders: AndroidAppender, ArduinoAppender, ColorConsoleAppender, DebugOutputAppender, EventLogAppender.
    • Data Formatting: AscDump (ASCII), HexDump (Hex), CustomFormatter, CustomConverter (e.g., encryption).
    • Advanced Usage: Chained (routing messages between libraries), DynamicAppender (adding/removing appenders at runtime), MultiAppender (multiple appenders for one logger), MultiInstance (independent logger configurations).
    • C++ Features: CXX11/CXX17 (modern feature support), CustomType (printing custom types), Path (std::filesystem::path support).
    • System/Platform: ObjectiveC, DisableLogging (stripping logs from binary), Shared/NotShared (controlling logger visibility across binary modules).