Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / VisualC++

Logging in C++

3 May 2015CPOL3 min read 125.3K   5.8K  
Logging in C++

Introduction

I am here to discuss the importance of Logging mechanism while developing a software project. To capture the flow of software execution persistently, we need to log the flow/trace of the software execution into the file. Logging mechanism helps us in debugging.

Here, I have developed the logging framework in C++. It's a pure C++ logging framework. This framework is efficient, effective and easily integrates into any project to achieve logging mechanism.

Now a days, many logging frameworks are available on the internet. But the advantage of this logging framework is that it's very simple, efficient, effective and could be easily integrated with the project to achieve the complete logging mechanism.

Advantages of this Logging Framework

  1. It's a very simple and effective logging framework, which could be easily integrated into any of the projects.
  2. Support of multiple log levels.
  3. Support of multiple log types.
  4. Control of log levels and log types.
  5. Logging with Timestamp.
  6. It has C++ interface as well as C interface, so that this framework can be easily integrated into C++ project as well as C project.
  7. Singleton Class and also thread safe in multithreading environment.
  8. Compatible with VC++(On Windows Platform) as well as g++ (On Linux Platform).
  9. Follows the OOP principle i.e. Abstraction, Encapsulation, etc.
  10. Extensible framework. You can easily extend this logging framework into your software module/project.
  11. If you really want to look for the good C++ programming, then you must have a look into the coding of this logging framework.

Usage

This framework has only two files:

  1. Logger.h -- Class and its member functions/variables declarations
  2. Logger.cpp -- Class and its member functions/variables definitions

You can easily add this these files into your software module/project.

There is only one class in this logging framework, i.e., Logger. Logger class and its functions/variables are declared and defined under namespace CPlusPlusLogging. So, you must need to use this namespace into your project to use this logging framework.

Logger class is a singleton class, thread safe and extensible one.

Supporting Log Levels

C++
1. LOG_LEVEL_ERROR
2. LOG_LEVEL_ALARM
3. LOG_LEVEL_INFO
4. LOG_LEVEL_BUFFER
5. LOG_LEVEL_ALWAYS
6. LOG_LEVEL_TRACE
7. LOG_LEVEL_DEBUG

Supporting Log Types

C++
1. CONSOLE
2. FILE_LOG

C Interface for Logging Framework

C++
1. LOG_ERROR(x)
2. LOG_ALARM(x)
3. LOG_ALWAYS(x)
4. LOG_INFO(x)
5. LOG_BUFFER(x)
6. LOG_TRACE(x)
7. LOG_DEBUG(x)

How to use C Interface of Logging Framework

C++
   LOG_ERROR("Message Logged using Direct Interface, Log level: LOG_ERROR");
   LOG_ALARM("Message Logged using Direct Interface, Log level: LOG_ALARM");
   LOG_ALWAYS("Message Logged using Direct Interface, Log level: LOG_ALWAYS");
   LOG_INFO("Message Logged using Direct Interface, Log level: LOG_INFO");
   LOG_BUFFER("Message Logged using Direct Interface, Log level: LOG_BUFFER");
   LOG_TRACE("Message Logged using Direct Interface, Log level: LOG_TRACE");
   LOG_DEBUG("Message Logged using Direct Interface, Log level: LOG_DEBUG");

LOG level automatically added as a prefix in the given log message. 
The reason for adding log level into the above messages is just to validate that, 
whatever log level which is automatically added by the Logging framework must match 
with the whatever log level which I am passing in the message.

C++ Interface for Logging Framework

C++
// C++ Interface for Error Log 
void error(const char* text) throw();
void error(std::string& text) throw();
void error(std::ostringstream& stream) throw();

// C++ Interface for Alarm Log 
void alarm(const char* text) throw();
void alarm(std::string& text) throw();
void alarm(std::ostringstream& stream) throw();

// C++ Interface for Always Log 
void always(const char* text) throw();
void always(std::string& text) throw();
void always(std::ostringstream& stream) throw();

// C++ Interface for Buffer Log 
void buffer(const char* text) throw();
void buffer(std::string& text) throw();
void buffer(std::ostringstream& stream) throw();

// C++ Interface for Info Log 
void info(const char* text) throw();
void info(std::string& text) throw();
void info(std::ostringstream& stream) throw();

// C++ Interface for Trace log 
void trace(const char* text) throw();
void trace(std::string& text) throw();
void trace(std::ostringstream& stream) throw();

// C++ Interface for Debug log 
void debug(const char* text) throw();
void debug(std::string& text) throw();
void debug(std::ostringstream& stream) throw();

How to use C++ Interface of Logging Framework

C++
Usage-1:
// Log message C++ Interface
Logger* pLogger = NULL; // Create the object pointer for Logger Class
pLogger = Logger::getInstance();

pLogger->error("Message Logged using C++ Interface, Log level: LOG_ERROR");
pLogger->alarm("Message Logged using C++ Interface, Log level: LOG_ALARM");
pLogger->always("Message Logged using C++ Interface, Log level: LOG_ALWAYS");
pLogger->buffer("Message Logged using C++ Interface, Log level: LOG_INFO");
pLogger->info("Message Logged using C++ Interface, Log level: LOG_BUFFER");
pLogger->trace("Message Logged using C++ Interface, Log level: LOG_TRACE");
pLogger->debug("Message Logged using C++ Interface, Log level: LOG_DEBUG");

Log Level Automatically Added as a Prefix in the Given Log Message. the Reason for 
Adding Log Level Into the Above Messages Is Just to Validate That, 
Whatever Log Level Which Is Automatically Added by the Logging Framework 
Must Match With the Whatever Log Level Which I Am Passing in the Message.

Usage-2:
// Log Variables
std::string name = "Pankaj Choudhary";
std::string address = "Delhi, India";
int age = 26;

std::ostringstream ss;
ss << endl;
ss << "\t" << "My Contact Details:" << endl;
ss << "\t" << "Name: " << name << endl;
ss << "\t" << "Address: " << address << endl;
ss << "\t" << "Age: " << age << endl << endl;

// Log ostringstream ss to all the log levels
LOG_ALWAYS("Logging ostringstream using Direct Interface");
LOG_ERROR(ss);
LOG_ALARM(ss);
LOG_ALWAYS(ss);
LOG_INFO(ss);
LOG_BUFFER(ss);
LOG_TRACE(ss);
LOG_DEBUG(ss);

Usage-3:

Logger::getInstance()->buffer("Logging ostringstream using C++ Interface");
Logger::getInstance()->error(ss);
Logger::getInstance()->alarm(ss);
Logger::getInstance()->always(ss);
Logger::getInstance()->buffer(ss);
Logger::getInstance()->info(ss);
Logger::getInstance()->trace(ss);
Logger::getInstance()->debug(ss);

Capture of output log file

C++
Tue Apr 21 23:01:39 2015  [ALWAYS]: <=============================== START OF PROGRAM ===============================>
Tue Apr 21 23:01:39 2015  [ERROR]: Message Logged using Direct Interface, Log level: LOG_ERROR
Tue Apr 21 23:01:39 2015  [ALARM]: Message Logged using Direct Interface, Log level: LOG_ALARM
Tue Apr 21 23:01:39 2015  [ALWAYS]: Message Logged using Direct Interface, Log level: LOG_ALWAYS
Tue Apr 21 23:01:39 2015  [INFO]: Message Logged using Direct Interface, Log level: LOG_INFO
Message Logged using Direct Interface, Log level: LOG_BUFFER
Tue Apr 21 23:01:39 2015  [TRACE]: Message Logged using Direct Interface, Log level: LOG_TRACE
Tue Apr 21 23:01:39 2015  [ERROR]: Message Logged using C++ Interface, Log level: LOG_ERROR
Tue Apr 21 23:01:39 2015  [ALARM]: Message Logged using C++ Interface, Log level: LOG_ALARM
Tue Apr 21 23:01:39 2015  [ALWAYS]: Message Logged using C++ Interface, Log level: LOG_ALWAYS
Message Logged using C++ Interface, Log level: LOG_INFO
Tue Apr 21 23:01:39 2015  [INFO]: Message Logged using C++ Interface, Log level: LOG_BUFFER
Tue Apr 21 23:01:39 2015  [TRACE]: Message Logged using C++ Interface, Log level: LOG_TRACE
Tue Apr 21 23:01:39 2015  [ALWAYS]: Logging ostringstream using Direct Interface
Tue Apr 21 23:01:39 2015  [ERROR]: 
    My Contact Details:
    Name: Pankaj Choudhary
    Address: Delhi, India
    Age: 26

Points of Interest

  • Implements complete logging mechanism, supports multiple logging type like as file based logging, console base logging, etc. It also supports different log types.
  • Thread Safe logging mechanism. Compatible with VC++ (Windows platform) as well as G++ (Linux platform).
  • Supported Log Types: ERROR, ALARM, ALWAYS, INFO, BUFFER, TRACE, DEBUG. No control for ERROR, ALRAM and ALWAYS messages. These type of messages should be always captured. BUFFER log type should be used while logging raw buffer or raw messages.
  • Captures log message with current timestamp, so that it would help in debugging your software module.
  • Has C interface as well as C++ Singleton interface. Can use whatever interface want.

Thanks

I would like to thank to my supervisor who has provided me an opportunity to work on log4c++ library. log4c++ library inspired me to develop this type of logging framework in C++.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)