demand

In the development, we often need to debug problems through Log(Log), but after the online do not need to print Log, and the usual development of each module if the Log can be printed according to the level of the problem analysis is very helpful.


Realize the principle of

Log levels are selected by importing a header file to enable or disable Log mode. Print different levels of logs by importing #include

.

Why syslog? Because it can print information not only in the Xcode console, but also in the Mac terminal. The advantage of this is that, for example, if there is a problem with an app in the App Store, we can adjust the log level in the app to the debug mode, and then use the data line to connect the device. This reoccurrence of the problem can print the relevant Log out in real time. It helps a lot to analyze the problem.


The brief analysis of

1. The Log mode

Why to set the log mode is very simple, because the app does not need to print logs after launching, and if you want to cancel all related printing during development, you can also directly use this macro definition to decide.

In this example, if kXDXDebugMode is defined in the code, the print log mode is enabled, otherwise the print log mode is disabled.

2. The Log level

In this example, five functions are used to print different levels of logs, as follows

#define kModuleName "Hello". int i = 1; int j = 2;log4cplus_fatal(kModuleName, "world1 , %d,%d",i,j);
    log4cplus_error(kModuleName, "world2");
    log4cplus_warn(kModuleName, "world3");
    log4cplus_info(kModuleName, "world4");
    log4cplus_debug(kModuleName, "world5");
Copy the code

For example, we may undertake a module independently in the development, and the module will need to be debugged only after it is finished. However, if our Log is clear enough, it can quickly help us find the problem. Here, the Log is divided into five levels

Here are some personal suggestions for printing logs, not necessarily following the following.

  • XDX_IOS_FLAG_FATAL: Severity level

When this kind of error occurs, it indicates that the program has been completely unable to run because of a certain problem. When we use this log, we can attach a description of the current major problems encountered and their causes for debugging.

  • XDX_IOS_FLAG_ERROR: Error level

This type of printing can be used for common errors, such as the return failure of a method call. Because the code is generally expected to be correct, this type of Log is not printed too often. Turning on this level allows us to see clearly where the program is going wrong.

  • XDX_IOS_FLAG_WARN: Warning level

This kind of error is generally lower than the error level, that is, in some possible places where there is no error, for example, when the number of video frames is less than 0, it indicates that there is an error. In order to prevent the error, we can use this kind to add a preventive Log when the number of video frames is less than 5.

  • XDX_IOS_FLAG_INFO: Major information level

This level is usually used to print important points in a module. For example, we can print important information initialized in a class when it is initialized, or do a print before a function is used, which is useful for tracking code.

  • XDX_IOS_FLAG_DEBUG: Debug level

This level indicates that we are currently printing logs temporarily to debug the program, or we are printing logs frequently to observe something, For example, the time stamp is printed in the camera callback, because the camera produces dozens of frames of data every second, so the printing is very frequent. We can use this level as debugging information in development, and it is generally not recommended to enable this level in normal use.

To sum up, the higher the log level is, the fewer the number of logs should be, so that we can reasonably choose which log level to use in development according to the above situation. The log level is inclusive, that is, the lower the log level can contain the higher log level than itself.

3. The module name

The format encapsulated here is as follows, that is, a log is divided into two parts, the module name in front of which is followed by the specific log content. Using this format can help us filter the logs in a certain module, which is very intuitive and clear

#define log4cplus_fatal(category, logFmt, ...) \
if(XDX_IOS_LOG_LEVEL & XDX_IOS_FLAG_FATAL) \
syslog(LOG_CRIT, "%s:" logFmt, category,##__VA_ARGS__); \
Copy the code

Examples are as follows:

#define kModuleName "Hello". - (void)test {
    int i = 0;
    log4cplus_debug(kModuleName, "Hello World - %d",i);
}

Copy the code

4. Pay attention to

The format %@ in OC is not available because of the syslog we are using. But any string in OC can be converted to C through UTF8String, so it doesn’t affect our use.

5. Usage

  • Set the log level before each compilation

If you don’t need to change the log level dynamically through the UI in your project, you can simply drag the header file into the project as follows and import it where you want to use the log. This is a simple and convenient way to change the log level simply by changing the macro definition before each run.

  • Changes through the UI after run

Change the global static variable XDX_IOS_LOG_LEVEL in the header file to an external variable, then cancel the following code, and finally define the value in the class that controls the UI and change it interactively.

#ifdef XDXLogLevelFatal
static const int XDX_IOS_LOG_LEVEL = XDX_IOS_FLAG_FATAL;
#elif defined(XDXLogLevelError)
static const int XDX_IOS_LOG_LEVEL = (XDX_IOS_FLAG_FATAL | XDX_IOS_FLAG_ERROR);
#elif defined(XDXLogLevelWarn)
static const int XDX_IOS_LOG_LEVEL = (XDX_IOS_FLAG_FATAL | XDX_IOS_FLAG_ERROR | XDX_IOS_FLAG_WARN);
#elif defined(XDXLogLevelInfo)
static const int XDX_IOS_LOG_LEVEL = (XDX_IOS_FLAG_FATAL | XDX_IOS_FLAG_ERROR | XDX_IOS_FLAG_WARN | XDX_IOS_FLAG_INFO);
#elif defined(XDXLogLevelDebug)
static const int XDX_IOS_LOG_LEVEL = (XDX_IOS_FLAG_FATAL | XDX_IOS_FLAG_ERROR | XDX_IOS_FLAG_WARN | XDX_IOS_FLAG_INFO | XDX_IOS_FLAG_DEBUG);
#endif

Copy the code

The specific implementation


#include <syslog.h>
#ifndef XDX_IOS
#define XDX_IOS
#endif

#pragma - Please select your log mode and log level

// Note: Only debug mode will print log. You could also set mode for log level.
#define kXDXDebugMode
// XDXLogLevelFatal , XDXLogLevelError , XDXLogLevelWarn , XDXLogLevelInfo , XDXLogLevelDebug
#define XDXLogLevelDebug

#pragma ----------------------------------

#ifdef kXDXDebugMode

static const int XDX_IOS_FLAG_FATAL = 0x10;
static const int XDX_IOS_FLAG_ERROR = 0x08;
static const int XDX_IOS_FLAG_WARN  = 0x04;
static const int XDX_IOS_FLAG_INFO  = 0x02;
static const int XDX_IOS_FLAG_DEBUG = 0x01;

#ifdef XDXLogLevelFatal
static const int XDX_IOS_LOG_LEVEL = XDX_IOS_FLAG_FATAL;
#elif defined(XDXLogLevelError)
static const int XDX_IOS_LOG_LEVEL = (XDX_IOS_FLAG_FATAL | XDX_IOS_FLAG_ERROR);
#elif defined(XDXLogLevelWarn)
static const int XDX_IOS_LOG_LEVEL = (XDX_IOS_FLAG_FATAL | XDX_IOS_FLAG_ERROR | XDX_IOS_FLAG_WARN);
#elif defined(XDXLogLevelInfo)
static const int XDX_IOS_LOG_LEVEL = (XDX_IOS_FLAG_FATAL | XDX_IOS_FLAG_ERROR | XDX_IOS_FLAG_WARN | XDX_IOS_FLAG_INFO);
#elif defined(XDXLogLevelDebug)
static const int XDX_IOS_LOG_LEVEL = (XDX_IOS_FLAG_FATAL | XDX_IOS_FLAG_ERROR | XDX_IOS_FLAG_WARN | XDX_IOS_FLAG_INFO | XDX_IOS_FLAG_DEBUG);
#endif



#define log4cplus_fatal(category, logFmt, ...) \
if(XDX_IOS_LOG_LEVEL & XDX_IOS_FLAG_FATAL) \
syslog(LOG_CRIT, "%s:" logFmt, category,##__VA_ARGS__); \

#define log4cplus_error(category, logFmt, ...) \
if(XDX_IOS_LOG_LEVEL & XDX_IOS_FLAG_ERROR) \
syslog(LOG_ERR, "%s:" logFmt, category,##__VA_ARGS__); \

#define log4cplus_warn(category, logFmt, ...) \
if(XDX_IOS_LOG_LEVEL & XDX_IOS_FLAG_WARN) \
syslog(LOG_WARNING, "%s:" logFmt, category,##__VA_ARGS__); \

#define log4cplus_info(category, logFmt, ...) \
if(XDX_IOS_LOG_LEVEL & XDX_IOS_FLAG_INFO) \
syslog(LOG_WARNING, "%s:" logFmt, category,##__VA_ARGS__); \

#define log4cplus_debug(category, logFmt, ...) \
if(XDX_IOS_LOG_LEVEL & XDX_IOS_FLAG_DEBUG) \
syslog(LOG_WARNING, "%s:" logFmt, category,##__VA_ARGS__); \


#else

#define log4cplus_fatal(category, logFmt, ...) ; \

#define log4cplus_error(category, logFmt, ...) ; \

#define log4cplus_warn(category, logFmt, ...) ; \

#define log4cplus_info(category, logFmt, ...) ; \

#define log4cplus_debug(category, logFmt, ...) ; \

#endif


Copy the code