drdobbs.com Open in urlscan Pro
172.67.66.43  Public Scan

Submitted URL: http://drdobbs.com/cpp/201804215
Effective URL: https://drdobbs.com/cpp/logging-in-c/201804215
Submission: On December 28 via manual from NZ — Scanned from NZ

Form analysis 1 forms found in the DOM

GET /sitesearch

<form method="get" action="/sitesearch">
  <input type="hidden" name="sort" value="publishDate desc">
  <ul>
    <li><input type="text" value="" size="40" id="queryText" name="queryText" maxlength="100" class="text"></li>
    <li><input type="submit" value=" " class="search"></li>
  </ul> Search: <input type="radio" name="type" value="site" checked=""> Site <input type="radio" name="type" value="sourcecode"> Source Code
</form>

Text Content

This site uses cookies to provide you with the best user experience possible. By
using Dr. Dobb's, you accept our use of cookies.
×
Informa

Dr. Dobb's is part of the Informa Tech Division of Informa PLC

 * Informa PLC
 * About us
 * Investor relations
 * Talent

This site is operated by a business or businesses owned by Informa PLC and all
copyright resides with them. Informa PLC's registered office is 5 Howick Place,
London SW1P 1WG. Registered in England and Wales. Number 8860726.





Welcome Guest | Log In | Register | Benefits
 * Subscribe
 * Newsletters
 * Digital Library
 * RSS

 * 
 * 

Search: Site Source Code


 * Home
 * Articles
 * News
 * Blogs
 * Source Code
 * Webinars & Events


 * 
 * 

Sections ▼
 * Home
 * Articles
 * News
 * Blogs
 * Source Code
 * Webinars & Events


 * Cloud
 * Mobile
 * Parallel
 * .NET
 * JVM Languages
 * C/C++
 * Tools
 * Design
 * Testing
 * Web Dev
 * Jolt Awards

Channels ▼
 * Cloud
 * Mobile
 * Parallel
 * .NET
 * JVM Languages
 * C/C++
 * Tools
 * Design
 * Testing
 * Web Dev
 * Jolt Awards




C/C++

Share

Reddit Permalink




LOGGING IN C++

By Petru Marginean, September 05, 2007

11 Comments

Logging is a critical technique for troubleshooting and maintaining software
systems. Petru presents a C++ logging framework that is typesafe, thread-safe,
and portable.


Logging is a critical technique for troubleshooting and maintaining software
systems. It's simple, provides information without requiring knowledge of
programming language, and does not require specialized tools. Logging is a
useful means to figure out if an application is actually doing what it is
supposed to do. Good logging mechanisms can save long debugging sessions and
dramatically increase the maintainability of applications.



In this article, I present a simple—but highly useful—logging framework that is
typesafe, threadsafe (at line-level), efficient, portable, fine-grained,
compact, and flexible. The complete source code, which works with Visual C++
7.1, g++ 3.3.5, and CC 5.3 on Sun and other platforms, is available in the DDJ
October 2007 zip file at www.ddj.com/code/.



In Part 2 of this article, I enhance this technique by providing more
granularity.




THE FIRST STEP



Let's take a first stab at a Log class. Listing One uses an std::ostringstream
member variable called "os" to accumulate logged data. The Get() member function
gives access to that variable. After all data is formatted, Log's destructor
persists the output to the standard error. You use Log class like this:

Log().Get(logINFO) << "Hello " << username;


Executing this code creates a Log object with the logINFOx logging level,
fetches its std::stringstream object, formats and accumulates the user-supplied
data, and finally, persists the resulting string into the log file using exactly
one call to fprintf().



Why flush during destruction? The last two steps are important because they
confer threadsafety to the logging mechanism. The fprintf() function is
threadsafe, so even if this log is used from different threads, the output lines
won't be scrambled. According to
gnu.org/software/libc/manual/html_node/Streams-and-Threads.html:



LISTING ONE

// Log, version 0.1: a simple logging class
enum TLogLevel {logERROR, logWARNING, logINFO, logDEBUG, logDEBUG1,
logDEBUG2, logDEBUG3, logDEBUG4};
class Log
{
public:
   Log();
   virtual ~Log();
   std::ostringstream& Get(TLogLevel level = logINFO);
public:
   static TLogLevel& ReportingLevel();
protected:
   std::ostringstream os;
private:
   Log(const Log&);
   Log& operator =(const Log&);
private:
   TLogLevel messageLevel;
};
std::ostringstream& Log::Get(TLogLevel level)
{
   os << "- " << NowTime();
   os << " " << ToString(level) << ": ";
   os << std::string(level > logDEBUG ? 0 : level - logDEBUG, '\t');
   messageLevel = level;
   return os;
}
Log::~Log()
{
   if (messageLevel >= Log::ReportingLevel())
   {
      os << std::endl;
      fprintf(stderr, "%s", os.str().c_str());
      fflush(stderr);
   }
}




The POSIX Standard requires that by default the stream operations are
atomic...issuing two stream operations for the same stream in two threads at the
same time will cause the operations to be executed as if they were issued
sequentially. The buffer operations performed while reading or writing are
protected from other uses of the same stream. To do this, each stream has an
internal lock object that has to be (implicitly) acquired before any work can be
done.



Before moving on to a more efficient implementation, let's write code to insert
tabs in proportion to the logging level, and append an std::endl to each chunk
of text. This makes the log line oriented and easy to read by both humans and
machines. Here's the relevant code:



Log::ReportingLevel() = logDEBUG2;
const int count = 3;
Log().Get(logDEBUG) << "A loop with "    << count << " iterations";
for (int i = 0; i != count; ++i)
{
   Log().Get(logDEBUG1)        << "the counter i = " << i;
}





which outputs:



- 22:25:23.643 DEBUG: 	A loop with 3 iterations
- 22:25:23.644 DEBUG1: 	the counter i = 0
- 22:25:23.645 DEBUG1: 	the counter i = 1
- 22:25:23.645 DEBUG1: 	the counter i = 2


Indentation makes the logging more readable. More leading tabs imply a more
detailed level of logging.



1 2 3 4 Next


RELATED READING

 * News
 * Commentary


NEWS

 * JetBrains Upsource 1.0 Final Release
 * Mirantis Releases Free Developer Edition
 * Jelastic Docker Integration For Orchestrated Delivery
 * Mac OS Installer Platform From installCore
   More News»


COMMENTARY

 * Things That Go Boom
 * JetBrains Upsource 1.0 Final Release
 * Mirantis Releases Free Developer Edition
 * Parasoft DevTest Shifts To Continuous
   More Commentary»

 * Slideshow
 * Video


SLIDESHOW

 * Jolt Awards 2014: The Best Utilities
 * The Most Underused Compiler Switches in Visual C++
 * Developer Reading List
 * Jolt Awards: Coding Tools
   More Slideshows»


VIDEO

 * Jimmy'll See You Around
 * IBM Mobile Developer Challenge
 * IBM Five in Five Predictions
 * Teen Computer Scientist Wins Big at ISEF
   More Videos»

 * Most Popular


MOST POPULAR

 * RESTful Web Services: A Tutorial
 * Lambda Expressions in Java 8
 * Developer Reading List: The Must-Have Books for JavaScript
 * Why Build Your Java Projects with Gradle Rather than Ant or Maven?
   More Popular»

--------------------------------------------------------------------------------


MORE INSIGHTS


WHITE PAPERS

 * Modernize your Security Operations with Human-Machine Intelligence
 * The Rise of Extended Detection & Response

More >>


REPORTS

 * Zero Trust and the Power of Isolation for Threat Prevention
 * Forrester Total Economic Impact Study: Team Cymru Pure Signal Recon

More >>


WEBCASTS

 * Cybersecurity Tech: Where It's Going and How To Get There
 * Developing an Effective Threat Intelligence Program for Your Enterprise

More >>

--------------------------------------------------------------------------------

INFO-LINK
 * 
 * 
 * 
 * 









CURRENTLY WE ALLOW THE FOLLOWING HTML TAGS IN COMMENTS:


SINGLE TAGS

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line


MATCHING TAGS

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text



Dr. Dobb's encourages readers to engage in spirited, healthy debate, including
taking us to task. However, Dr. Dobb's moderates all comments posted to our
site, and reserves the right to modify or remove any content that it determines
to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist
or obvious marketing or spam. Dr. Dobb's further reserves the right to disable
the profile of any commenter participating in said activities.

  To upload an avatar photo, first complete your Disqus profile. | View the list
of supported HTML tags you can use to style comments. | Please read our
commenting policy.  

Login or Register to Comment
arsemik

I do not understand why we log at destructor.

ThorstenR136

This still is the best startup / tutorial for a logger in C++. Simple,
extendable and well documented. I used this as a base framework and integrated
logging from a calling Python interpreter to merge C++ and Python log. I learned
a lot about simplicity in logging. Too much log4xyz monsters flying around,
where you need a training before writing a single line to the log.

CCsernica

Late reply is late, but I only ran across this just now while looking to save
myself from work writing a logging facility for a new app.

If you were to dynamically create an instance of the Log class and use that for
all your logging throughout your application, what you say here would be
correct. However, using the macro as presented, the object automatically created
goes out of scope as soon as you exit the if-else statement where it exists. The
destructor is therefore called immediately.

Dollar_cz

EasyLogging++ is the way to go that is fast light weight an high performing with
extra features!

mstokes357

I like this log facility. I made one change that adds some value for me. I added
a logNONE enum at the first position (index=0) with the idea that it would not
be used to log to. If used when setting the ReportingLevel() none of the log
entries will be printed.

daffodil

nice ..........

ildar

I am not going to say that this is not the (one) way of doing it.
However, there is one issue here. It seems that all logs has been appended to
the string, and at the end of the life of application that string is written to
the file. Is that 'buffering" taken to extreme?
Does some one really wants to allow the log to be accumulated in the application
memory indefinitly?

twerd

Great little header file. Im using it as a simple logger for some research Im
doing. One small problem I had was that static boost::mutex mtx inside the
Output2File class refused to compile and gave me a linker error. I moved it out
of the class as a global static variable and that fixed it.

grunt

I can't open logcpp.zip which is no suprise since the file's size is only 44
Bytes.

And the "0710.zip" download link doesn't seem to work for me.

UK

Click the "0710.zip" instead, it contains the logcpp.zip, too.

voodooRod

Having trouble unzipping this file.





C/C++ RECENT ARTICLES

 * Dr. Dobb's Archive
 * Jolt Awards 2015: Coding Tools
 * Building Node.js Projects in Visual Studio
 * Building Portable Games in C++
 * C# and .NET's Sudden Ubiquity


MOST POPULAR

Stories Blogs
 * The C++14 Standard: What You Need to Know
 * A Simple and Efficient FFT Implementation in C++:
   Part I
 * State Machine Design in C++
 * Lambdas in C++11
 * A Lightweight Logger for C++
 * 
 * 

 * C++11: unique_ptr
 * C++11's async Template
 * Abstractions For Binary Search, Part 10: Putting It All Together
 * It's Hard To Compare Floating-Point Numbers
 * Auto Types and Range-Based For Statements in C++11
 * 
 * 




THIS MONTH'S DR. DOBB'S JOURNAL

This month, Dr. Dobb's Journal is devoted to mobile programming. We introduce
you to Apple's new Swift programming language, discuss the perils of being the
third-most-popular mobile platform, revisit SQLite on Android , and much more!

Download the latest issue today. >>




UPCOMING EVENTS

Live Events WebCasts
 * [FREE VIRTUAL EVENT] 9/29 - Enterprise Network Evolution & Modernization -
 * [FREE Virtual Event] The Identity Crisis -

Understanding Cyber Attacks on Remote Workers Making Deception a Part of Your
Enterprise Defense Strategy A Black Hat Webinar: Inside the Cyber Safety Review
Board: A Fireside Chat with Jeff Moss, Chair Rob Silvers and Deputy Chair
Heather Adkins Streamlining Your Patch Management Processes Developing an
Effective Threat Intelligence Program for Your Enterprise


More Webcasts>>


FEATURED REPORTS

 
 
What's this?
 * Incident Readiness and Building Response Playbook
 * Privileged Access Management Checklist
 * Proven Success Factors for Endpoint Security
 * Intel 471 Breach Report
 * SANS 2021 Cloud Security Survey

More >>




FEATURED WHITEPAPERS

 
 
What's this?
 * Quantifying the Gap Between Perceived Security and Comprehensive MITRE ATT&CK
   Coverage
 * Defending Corporate Executives and VIPs from Cyberattacks
 * The Cyber Threat Impact of COVID-19 to Global Business
 * Identity Access Management 101
 * The Impact of XDR in the Modern SOC

More >>




MOST RECENT PREMIUM CONTENT

Digital Issues
   2014
   
   
   Dr. Dobb's Journal
 * November - Mobile Development
 * August - Web Development
 * May - Testing
 * February - Languages
   
   
   Dr. Dobb's Tech Digest
   
   
 * DevOps
 * Open Source
 * Windows and .NET programming
 * The Design of Messaging Middleware and 10 Tips from Tech Writers
 * Parallel Array Operations in Java 8 and Android on x86: Java Native Interface
   and the Android Native Development Kit
   
   
   2013
 * January - Mobile Development
 * February - Parallel Programming
 * March - Windows Programming
 * April - Programming Languages
 * May - Web Development
 * June - Database Development
 * July - Testing
 * August - Debugging and Defect Management
 * September - Version Control
 * October - DevOps
 * November- Really Big Data
 * December - Design
   
   
   2012
 * January - C & C++
 * February - Parallel Programming
 * March - Microsoft Technologies
 * April - Mobile Development
 * May - Database Programming
 * June - Web Development
 * July - Security
 * August - ALM & Development Tools
 * September - Cloud & Web Development
 * October - JVM Languages
 * November - Testing
 * December - DevOps
   
   

Discover more from Informa Tech
 * InformationWeek
 * Interop
 * Dark Reading
 * Data Center Knowledge
 * Network Computing
 * IT Pro Today

Working With Us
 * Contact Us
 * About Us
 * Advertise
 * Reprints

Follow Dr. Dobb's on Social
 * 
 * 
 * 
 *  

 * Home
 * Cookie Policy
 * CCPA: Do not sell my personal info
 * Privacy
 * Terms

Copyright © 2022 Informa PLC. Informa PLC is registered in England and Wales
with company number 8860726 whose registered and head office is 5 Howick Place,
London, SW1P 1WG.



Techweb