Skip to content
Dimo Markov edited this page Jul 11, 2024 · 12 revisions

Main Functions

Logging happens mainly through the following variadic functions, each with its distinct style:

Logger::Section

Logger::Section(...);

Output:

image

Logger::Fatal

Logger::Fatal(...);
Logger::FatalTab(...) -> Logger::ScopedTab;

Output:

image

Logger::Error

Logger::Error(...);
Logger::ErrorTab(...) -> Logger::ScopedTab;

Output:

image

Logger::Warning

Logger::Warning(...);
Logger::WarningTab(...) -> Logger::ScopedTab;

Output:

image

Logger::Verbose

Logger::Verbose(...);
Logger::VerboseTab(...) -> Logger::ScopedTab;

Output:

image

Logger::Info

Logger::Info(...);
Logger::InfoTab(...) -> Logger::ScopedTab;

Output:

image

Logger::Message

Logger::Message(...);
Logger::MessageTab(...) -> Logger::ScopedTab;

Output:

image

Logger::Special

Logger::Special(...);
Logger::SpecialTab(...) -> Logger::ScopedTab;

Output:

image

Logger::Flow

Logger::Flow(...);
Logger::FlowTab(...) -> Logger::ScopedTab;

Output:

image

Logger::Input

Logger::Input(...);
Logger::InputTab(...) -> Logger::ScopedTab;

Output:

image

Logger::Network

Logger::Network(...);
Logger::NetworkTab(...) -> Logger::ScopedTab;

Output:

image

Logger::OS

Logger::OS(...);
Logger::OSTab(...) -> Logger::ScopedTab;

Output:

image

Logger::Prompt

Logger::Prompt(...);
Logger::PromptTab(...) -> Logger::ScopedTab;

Output:

image

Secondary Functions

Additionally, there are a couple of context-dependent calls, that don't modify styling:

Logger::Line

Logger::Line(...)

Logger::Append

Logger::Append(...)

Text arguments

All of the mentioned functions accept all string/character types, as well as types that are convertible to strings (either provided by you, or by {fmt} library). You can provide any number of arguments in two possible ways:

// Provided as variadic function arguments (recommended)
Logger::Special("The answer is ", 42, '!', " It's ", true, ", I tell ya!");
// Provided using std::cout style operator <<
Logger::Special() << "The answer is " << 42 << '!' << " It's " << true << ", I tell ya!";

Output:

image

Command arguments

Logger accepts some special arguments, that change the logging state, such as tabulation, color and style.

Colors

Here's a list of the available colors. These colors are encoded using ANSI/VT100 escape sequences when written in terminals, or HTML tags when logged in html files:

Logger::NoForeground // Sets foreground color to the default
Logger::NoBackground // Sets background color to the default

// Foreground colors:
Logger::Black
Logger::DarkRed
Logger::DarkGreen
Logger::DarkYellow
Logger::DarkBlue
Logger::DarkPurple
Logger::DarkCyan
Logger::Gray
Logger::DarkGray
Logger::Red
Logger::Green
Logger::Yellow
Logger::Blue
Logger::Purple
Logger::Cyan
Logger::White

// Background colors
Logger::BlackBgr
Logger::DarkRedBgr
Logger::DarkGreenBgr
Logger::DarkYellowBgr
Logger::DarkBlueBgr
Logger::DarkPurpleBgr
Logger::DarkCyanBgr
Logger::GrayBgr
Logger::DarkGrayBgr
Logger::RedBgr
Logger::GreenBgr
Logger::YellowBgr
Logger::BlueBgr
Logger::PurpleBgr
Logger::CyanBgr
Logger::WhiteBgr

You can set colors, by providing the appropriate value as an argument:

{
   auto scope = Logger::Section("Now testing foreground colors: ");
   Logger::Line(Logger::Black, "Black, ", Logger::Blue, "Blue, ", Logger::Cyan, "Cyan, ", Logger::DarkBlue, "Dark blue, ");
   Logger::Line(Logger::DarkCyan, "Dark cyan, ", Logger::DarkGray, "Dark gray, ", Logger::DarkGreen, "Dark green, ", Logger::DarkPurple, "Dark purple, ");
   Logger::Line(Logger::DarkRed, "Dark red, ", Logger::DarkYellow, "Dark yellow, ", Logger::Gray, "Gray, ", Logger::Green, "Green, ");
   Logger::Line(Logger::Purple, "Purple, ", Logger::Red, "Red, ", Logger::White, "White, ", Logger::Yellow, "Yellow, ");
}
{
   auto scope = Logger::Section("Now testing background colors: ");
   Logger::Line(Logger::BlackBgr, "Black, ", Logger::BlueBgr, "Blue, ", Logger::CyanBgr, "Cyan, ", Logger::DarkBlueBgr, "Dark blue, ");
   Logger::Line(Logger::DarkCyanBgr, "Dark cyan, ", Logger::DarkGrayBgr, "Dark gray, ", Logger::DarkGreenBgr, "Dark green, ", Logger::DarkPurpleBgr, "Dark purple, ");
   Logger::Line(Logger::DarkRedBgr, "Dark red, ", Logger::DarkYellowBgr, "Dark yellow, ", Logger::GrayBgr, "Gray, ", Logger::GreenBgr, "Green, ");
   Logger::Line(Logger::PurpleBgr, "Purple, ", Logger::RedBgr, "Red, ", Logger::WhiteBgr, "White, ", Logger::YellowBgr, "Yellow, ");
}

Output:

image

Emphasis

Much like colors, you can apply some emphasis styles. Unfortunately, most of these aren't available on Windows terminals.

Logger::Bold       // Not working on windows                 
Logger::Faint      // Not working on windows                 
Logger::Italic     // Not working on windows                 
Logger::Underline  // Used in Logger::Section, for example
Logger::Blink      // Not working on windows                 
Logger::Reverse
Logger::Conceal    // Not working on windows                 
Logger::Strike     // Not working on windows                 

Commands

Much like colors and emphasis, you can also provide some commands to change the logger state:

Logger::Clear      // Clear the console/log file                                  
Logger::NewLine    // Write a new line, with a timestamp and tabulation - style will be continued from the last pushed one
Logger::Pop        // Pop the style                                      
Logger::Push       // Push the style                                     
Logger::Invert     // Inverts background and foreground colors           
Logger::Reset      // Reset the style, popping all pushed styles                                   
Logger::Stylize    // Apply the last style                               
Logger::Tab        // Tab once on a new line after this command          
Logger::Untab      // Untab once, again on a new line after this command 
Logger::Time       // Write a short timestamp                            
Logger::ExactTime  // Write an exhaustive timestamp                      

Tabulation

You can also use Logger::Tabs{N} as an argument to specify how many tabulations will be applied on next logged message. ⚠️ Logger::Tabs{N} should be used as the last argument, and will make the logging function return a ScopedTab that you should keep in a variable, that will automatically untab when out of scope. If you forget to keep that return value, you'll likely see no tabulation at all.

auto scopedTabs = Logger::Network("This is a network message", Logger::Tabs{3});
Logger::Line("This should be a continued network on a new line, without any prefix");
Logger::Append(", and this should be appended");
// Will automatically untab, when scopedTabs goes out of scope

Output:

image

Attachments

The logger interface allows for attachments via the following functions:

// Duplicator attachments repeat any logged message through each attachment
Logger::AttachDuplicator(Logger::A::Interface*);
Logger::DettachDuplicator(Logger::A::Interface*);

// Redirector attachments relay any logged messages through all redirectors and then consumes the message, so that it never reaches the terminal or any duplicators. This is especially useful when you use terminals for interfaces, and logging shouldn't interfere.
Logger::AttachRedirector(Logger::A::Interface*);
Logger::DettachRedirector(Logger::A::Interface*);

HTML logging works through an attachment:

#include <Logger/Logger.hpp>

int main(int argc, char* argv[]) {
   // Duplicate any logging messages to an external HTML file           
   Logger::ToHTML logFile {"logfile.htm"};
   Logger::AttachDuplicator(&logFile);

   // The message will appear both in the console, and in logfile.htm
   Logger::Message("Howdy!");
   return 0;
}

⚠️ Attachment objects aren't managed by the logger - you are responsible for creating and destroying them. Make sure you don't destroy an attachment before detaching it.

The logger library comes with two stock attachments:

  • Logger::MessageSink - with a global instance Logger::MessageSinkInstance. It consumes any message it receives. Useful if you want to disable logging, when attached via Logger::AttachRedirector.
  • Logger::ToHTML - you'll have to instantiate it yourself as shown in the example above - useful to redirect/duplicate any logging in an HTML file.

You can create your own attachments, by inheriting the Logger::A::Interface.