Sensei Posted November 8, 2023 Posted November 8, 2023 (edited) When programming, logging is an essential operation to find out what happened and why it happened. Especially in an application written on Linux and running on a server, without a GUI, whose output goes to a terminal / shell. I have created some basic C++ classes that can be useful in an application (C++, but they can be easily adapted to other OOP languages). Logs.Base is a virtual class without implemented methods. Logs.QuietLogs is implemented as a no-op. Simply put, nothing, quiet. Logs.Logs is implemented to write only about serious errors (Logs.Error() method implemented). Logs.VerboseLogs is implemented to write about errors and warnings (Logs.Warning() method implemented). Logs.VeryVerboseLogs is implemented to write about errors, warnings and notifications (Logs.Notice() method implemented). By passing a generic logging class object to functions, methods, classes, constructors, etc., they can write what they want to the logging object, but what appears to the user depends on user willingness to listen using -q (--quiet), -s (--silent), -v (--verbose), -vv (--very-verbose) etc. on the command line.. Writing to a separate log file can be as simple as creating another Logs.Base subclass with the appropriate methods overridden, or even over the network. // Logs v1.0 (c) 2023 Sensei (aka 'Q') (8.XI.2023) #include <iostream> namespace Logs { class Base { public: virtual void Notice( const std::string &message ) = 0; virtual void Warning( const std::string &message ) = 0; virtual void Error( const std::string &message ) = 0; }; class QuietLogs : public Base { public: virtual void Notice( const std::string &message ) {} virtual void Warning( const std::string &message ) {} virtual void Error( const std::string &message ) {} }; class Logs : public QuietLogs { public: virtual void Error( const std::string &message ) { std::cerr << message << std::endl; } }; class VerboseLogs : public Logs { public: virtual void Warning( const std::string &message ) { std::cerr << message << std::endl; } }; class VeryVerboseLogs : public VerboseLogs { public: virtual void Notice( const std::string &message ) { std::cout << message << std::endl; } }; }; class Program { public: Program( const std::string &title, Logs::Base &logs ) { std::cout << "Testing " << title << std::endl; logs.Error( "Error!" ); logs.Warning( "Warning!" ); logs.Notice( "Notice!" ); std::cout << std::endl; } }; int main( int argc, const char *argv[] ) { Logs::VeryVerboseLogs l3; Program p1( "Very Verbose Logs Test", l3 ); Logs::VerboseLogs l2; Program p2( "Verbose Logs Test", l2 ); Logs::Logs l1; Program p3( "Logs Test", l1 ); Logs::QuietLogs l0; Program p4( "Quiet Test", l0 ); return( 0 ); } Example output: ./logs Testing Very Verbose Logs Test Error! Warning! Notice! Testing Verbose Logs Test Error! Warning! Testing Logs Test Error! Testing Quiet Test I think passing arguments --verbose, --very-verbose, --quiet, --silent, etc. is quite sloppy in code.. better instead to create such a C++ class.. logs.cpp Edited November 8, 2023 by Sensei
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now