Use native C ++ to develop log classes in Windows Mobile

Source: Internet
Author: User
Background

I have been developing itoday in my spare time. Add log management to itoday. For more information about itoday, seeArticle.

Open source (1)

Open-source things (2)-itoday open-source project plan

Open-source things (III)-overall itoday Design

Open-source things (4)-How to Use codeplex for project management

 

Introduction

Log Management isProgramAn important component that cannot be missing is especially important for long-running background programs. Despite a large number of tests, there is no error in the program in the actual running environment. Sometimes it is caused by a third party, such as downloading the quality of the telecom network and dropping packets. Under some seemingly inexplicable problems, log files often become a life-saving rope. Bug free is our goal, but I can never guarantee bug free. Every time I say this in an interview, people who are born from sales will turn their eyes to the white, people who are skilled will smile. What I can ensure is how to quickly troubleshooting and Improve the Quality. log files are one of the most important means in this process. The following article describes how to use native C ++ to encapsulate Windows Embedded ce and Windows Mobile log files.

 

Code

First, go to the code and analyze it below. You can download all itoday code to codeplex.

Class definition file

 Typedef Enum Taglog_level
{
Log_trace,
Log_info,
Log_warning,
Log_error,
Log_fatal,
Log_none = 10,
} Log_level;

Class Logger
{
Public :
Static Logger & instance ();

Static void Setlogfilepath ( Const STD: string & strfilepath );
Static void Setloglevel ( Const Log_level enloglevel );
Static void Initialise ();
Static void Dispose ();

// Void log (log_trace const tchar * format ,...);
// Void loginfo (const tchar * format ,...);
// Void logwarning (const tchar * format ,...);
// Void logerror (const tchar * format ,...);
// Void logfatal (const tchar * format ,...);

Void Log (log_level loglevel, Const Tchar * format ,...);

Private :
/* More (non-static) functions here */
Logger (); // Ctor hidden
Logger (Logger Const &); // Copy ctor hidhidden
Logger & Operator = (Logger Const &); // Assign op. Hidden
~ Logger (); // Dtor hidden

Static File * m_hlogfile;
Static STD: String m_strfilepath;
Static Log_level m_enloglevel;
};

Class implementation file

File * logger: m_hlogfile = NULL;
Log_level logger: m_enloglevel = log_trace;
STD: String logger: m_strfilepath = "\ Storage card \ debuginfo. log" ;

Tchar * loglevelstr [] =
{
Text ( "Trace" ),
Text ( "Info" ),
Text ( "Warn" ),
Text ( "Error" ),
Text ( "Fatal" ),
};

Logger & logger: instance ()
{
Static Logger ologger;
Return Ologger;
}

Void Logger: setlogfilepath ( Const STD: string & strfilepath)
{
M_strfilepath = strfilepath;
Dispose ();
Initialise ();
}

Void Logger: setloglevel ( Const Log_level enloglevel)
{
M_enloglevel = enloglevel;
}


Logger: logger ()
{
Initialise ();
}

// Never use
Logger ::~ Logger ()
{
Dispose ();
}

Void Logger: initialise ()
{
If (M_strfilepath.length ()> 0)
{
M_hlogfile = fopen (m_strfilepath.c_str (), "A +" );
}
}

Void Logger: dispose ()
{
If (Null! = M_hlogfile)
{
Fflush (m_hlogfile );
Fclose (m_hlogfile );
M_hlogfile = NULL;
}
}

Void Logger: log (log_level enloglevel, Const Tchar * format ,...)
{
If (M_enloglevel> enloglevel)
{
Return ;
}
# Ifndef Debug
If (Null = m_hlogfile)
{
Return ;
}
# Endif

Tchar szbuffer [1024];

Va_list ARGs;
Va_start (ARGs, format );
Vswprintf (szbuffer, format, argS );
Va_end (ARGs );

# Ifdef Debug
Wprintf (_ T ("% s thr: % 8.8x % s \ t % s \ n"), getcurrenttime (), getcurrentthread (), loglevelstr [enloglevel], szbuffer );
# Else
// Combine time stamp, thread number and log level together.
If (0> fwprintf (m_hlogfile, _ T ( "% S thr: % 8.8x % s \ t % s \ n" ), Getcurrenttime (), getcurrentthreadid (), loglevelstr [enloglevel], szbuffer ))
{
Dispose ();
}
Else
{
Fflush (m_hlogfile );
}
# Endif

}

 

Singleton Mode

This logger class is implemented using the singleton mode. I don't know when the design mode will no longer be popular in the blog Park. On the one hand, it indicates that the design mode is no longer spring and white, and has already penetrated into the world. On the other hand, the anti-pattern craze has emerged. In the anti-pattern wave, Singleton is the most criticized pattern. Singleton is a bit like a global variable in disguise. It destroys encapsulation and disconnects dependencies of various classes.

I am still saying that there is no error in the pattern itself. Check whether the user uses the pattern in a specific scenario. I will still use singleton. If a resource class has only one copy, I will use Singleton. There is no need to generate multiple objects, and synchronization may occur when multiple objects access exclusive resources. In the logger class, I still use Singleton because I only write one file.

The specific implementation of Singleton is generally concerned with three issues: 1. There is only one object instantiated. 2. multi-thread control. In fact, the second problem is also to ensure the first problem. 3. instantiate on demand.

 
Private:
/* More (non-static) functions here */
Logger ();// Ctor hidden
Logger (LoggerConst&);// Copy ctor hidhidden
Logger &Operator= (LoggerConst&);// Assign op. Hidden
~ Logger ();// Dtor hidden

The code above is used to ensure that only one object is instantiated. Many developers who do C # will ignore the code above, because C # does not have the concept of deep copy and does not have the concept of operator overloading.

 

 
Logger & logger: instance ()
{
StaticLogger ologger;
ReturnOlogger;
}

The above Code ensures thread security and instantiation on demand. I think this implementation mode is good and meets three wishes at the same time.

 

Log Classification Management

When printing logs, hierarchical management is very important. Different Levels of logs need to be displayed in different periods. During development periods, trace-level logs may be required, at runtime, only logs of the error level or above are required. Log hierarchical management can balance the reasonable utilization of time and space.

Through level management, you can print logs with a level higher than the desired level.

 
If(M_enloglevel> enloglevel)
{
Return;
}

 

During the printing process, the display level is from advanced to low-level when I look for a problem.

 
If(0> fwprintf (m_hlogfile, _ T ("% S thr: % 8.8x % s \ t % s \ n"), Getcurrenttime (), getcurrentthreadid (), loglevelstr [enloglevel], szbuffer ))
{
Dispose ();
}

Since this is implemented on Windows Embedded ce and Windows Mobile Platforms, Unicode APIs are available. Below is the printed log, including the level.

2010-02-24t09: 17: 38 thr: de428d7e trace file = [. \ itoday. cpp], line = [44]
2010-02-24t09: 17: 39 thr: de428d7e info file = [. \ itoday. cpp], line = [47]
2010-02-24t09: 17: 39 thr: de428d7e warn file = [. \ itoday. cpp], line = [50]
2010-02-24t09: 17: 40 thr: de428d7e error file = [. \ itoday. cpp], line = [53]
2010-02-24t09: 17: 40 thr: de428d7e fatal file = [. \ itoday. cpp], line = [56]
2010-02-24t09: 17: 41 thr: de428d7e warn file = [. \ itoday. cpp], line = [67]
2010-02-24t09: 17: 42 thr: de428d7e error file = [. \ itoday. cpp], line = [70]
2010-02-24t09: 17: 42 thr: de428d7e fatal file = [. \ itoday. cpp], line = [73]

Time and thread number

In a multi-threaded environment, printing time and threads are very important, so as to check thread synchronization problems. The time and thread number are shown in the preceding log.

 

Use Logger
 Void Loggertest ()
{
Logger: instance (). Log (log_trace, _ T ("File = [% s], line = [% d]" ), _ File __, _ line __);
Sleep (500 );

Logger: instance (). Log (log_info, _ T ( "File = [% s], line = [% d]" ), _ File __, _ line __);
Sleep (500 );

Logger: instance (). Log (log_warning, _ T ( "File = [% s], line = [% d]" ), _ File __, _ line __);
Sleep (500 );

Logger: instance (). Log (log_error, _ T ( "File = [% s], line = [% d]" ), _ File __, _ line __);
Sleep (500 );

Logger: instance (). Log (log_fatal, _ T ( "File = [% s], line = [% d]" ), _ File __, _ line __);
Sleep (500 );

Logger: setloglevel (log_warning );

Logger: instance (). Log (log_trace, _ T ( "File = [% s], line = [% d]" ), _ File __, _ line __);
Sleep (500 );

Logger: instance (). Log (log_info, _ T ( "File = [% s], line = [% d]" ), _ File __, _ line __);
Sleep (500 );

Logger: instance (). Log (log_warning, _ T ( "File = [% s], line = [% d]" ), _ File __, _ line __);
Sleep (500 );

Logger: instance (). Log (log_error, _ T ( "File = [% s], line = [% d]" ), _ File __, _ line __);
Sleep (500 );

Logger: instance (). Log (log_fatal, _ T ( "File = [% s], line = [% d]" ), _ File __, _ line __);
Sleep (500 );

Logger: setloglevel (log_info );
Logger: setlogfilepath ( "\ Storage card \ debuginfo2.log" );

Logger: instance (). Log (log_trace, _ T ( "File = [% s], line = [% d]" ), _ File __, _ line __);
Sleep (500 );

Logger: instance (). Log (log_info, _ T ( "File = [% s], line = [% d]" ), _ File __, _ line __);
Sleep (500 );

Logger: instance (). Log (log_warning, _ T ( "File = [% s], line = [% d]" ), _ File __, _ line __);
Sleep (500 );

Logger: instance (). Log (log_error, _ T ( "File = [% s], line = [% d]" ), _ File __, _ line __);
Sleep (500 );

Logger: instance (). Log (log_fatal, _ T ("File = [% s], line = [% d]" ), _ File __, _ line __);
Sleep (500 );

}

Using the logger class is simple. You can call the log () function directly. You can refer to the printf mode, that is, the string. Format () mode of C.

 

This is my encapsulated logger class. You are welcome to make the Board so that I can continuously improve the implementation of this class.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.