Painted levels: being fostered fostered fostered

Tags: “iOS” “Log” “CocoaLumberjack” author: Dac_1033 Review: QiShare team


It is essential to print logs during the development process. Log processing is divided into the following types:

  • Process logs in Debug/Release mode.
  • The logs are recorded in a local file and uploaded to the server.
  • The service App controls whether to enable logging.
1. Process logs in Debug/Release mode

The first point is most commonly used when developing business apps, and is done in one line:

#ifdef DEBUG #define DLog(fmt, ...) {NSLog((@"%s [Line %d]\n " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__); } #else #define DLog(...) #endifCopy the code

If the diagram is convenient, you can write the above code to the prefix-.pch file and call DLog(…) where you want to output the log. When the Debug/Release mode is switched, the log printing function is automatically enabled or disabled.

2. Record logs in a local file

Logging to a local file is handled by the CocoaLumberjack library. This library allows you to export logs to the console or write them to a local file. You can also set the level of logging output. For details about how to use CocoaLumberjack, see the iOS logging framework CocoaLumberjack configuration and usage

3. Supports CocoaLumberjack and enables or disables logs

This scenario often appears in the framework development process, we develop a framework, which needs to output logs to local files, in addition to host App tuning, often need to actively control the log on and off. We define a LogManager class, logManager.h code is as follows:

@import Foundation; //#define LUMBERJACK @"LUMBERJACK" #ifdef LUMBERJACK #define LOG_LEVEL_DEF ddLogLevelf #import <CocoaLumberjack/CocoaLumberjack.h> #else /* LUMBERJACK */ typedef NS_OPTIONS(NSUInteger, DDLogFlag){ // 0... 00001 DDLogFlagError DDLogFlagError = (1 << 0), // 0... 00010 DDLogFlagWarning DDLogFlagWarning = (1 << 1), // 0... 00100 DDLogFlagInfo DDLogFlagInfo = (1 << 2), // 0... 01000 DDLogFlagDebug DDLogFlagDebug = (1 << 3), // 0... 10000 DDLogFlagVerbose DDLogFlagVerbose = (1 << 4) }; typedef NS_ENUM(NSUInteger, DDLogLevel){ DDLogLevelOff = 0, // Error logs only DDLogLevelError = (DDLogFlagError), // Error and warning logs DDLogLevelWarning = (DDLogLevelError | DDLogFlagWarning), // Error, warning and info logs DDLogLevelInfo = (DDLogLevelWarning | DDLogFlagInfo), // Error, warning, info and debug logs DDLogLevelDebug = (DDLogLevelInfo | DDLogFlagDebug), // Error, warning, info, debug and verbose logs DDLogLevelVerbose = (DDLogLevelDebug | DDLogFlagVerbose), // All logs (1... 11111) DDLogLevelAll = NSUIntegerMax }; #define CustomLog(format,...) [MQTTLog customLogWithFormatString:[NSString stringWithFormat:format, ##__VA_ARGS__]] #define DDLogVerbose if (ddLogLevel & DDLogFlagVerbose) CustomLog #define DDLogDebug if (ddLogLevel & DDLogFlagDebug) CustomLog #define DDLogWarn if (ddLogLevel & DDLogFlagWarning) CustomLog #define DDLogInfo if (ddLogLevel & DDLogFlagInfo) CustomLog #define DDLogError if (ddLogLevel & DDLogFlagError) CustomLog #endif /* LUMBERJACK */ extern DDLogLevel ddLogLevel; extern BOOL logEnable; /** MQTTLog lets you define the log level for MQTTClient * independently of using CocoaLumberjack */ @interface MQTTLog:  NSObject // default one is DDLogLevelVerbose + (void)setLogLevel:(DDLogLevel)logLevel; + (void)setLogEnable:(BOOL)logEnable; + (void)customLogWithFormatString:(NSString *)formatString; @endCopy the code

The logmanager.m code is as follows:

#import "mqttlog. h" #ifdef LUMBERJACK @interface DDLogFileFormatter: NSObject <DDLogFormatter> { NSDateFormatter *dateFormatter; } - (id)init; - (instancetype)initWithDateFormatter:(NSDateFormatter *)dateFormatter; @end @implementation DDLogFileFormatter - (id)init { return [self initWithDateFormatter:nil]; } - (instancetype)initWithDateFormatter:(NSDateFormatter *)aDateFormatter { if ((self = [super init])) { if (aDateFormatter) { dateFormatter = aDateFormatter; } else { dateFormatter = [[NSDateFormatter alloc] init]; [dateFormatter setFormatterBehavior:NSDateFormatterBehavior10_4]; // 10.4+ style [dateFormatter setDateFormat:@" YYYYMMDD-HHmms.sss "]; } } return self; } - (NSString *)formatLogMessage:(DDLogMessage *)logMessage { NSString *dateAndTime = [dateFormatter stringFromDate:(logMessage.timestamp)]; NSString* level; switch(logMessage.flag) { case DDLogFlagError: level=@"E"; break; case DDLogFlagWarning: level=@"W"; break; case DDLogFlagInfo: level=@"I"; break; case DDLogFlagDebug: level=@"D"; break; case DDLogFlagVerbose: level=@"V"; break; default: level=@"U"; break; } NSString *formatStr = [NSString stringWithFormat:@"%@ %@ %d.%@[%@:%ld:%@] %@", level, dateAndTime, getpid(),logMessage.threadID, logMessage.fileName, (unsigned long)logMessage.line, logMessage.function, logMessage.message]; return formatStr; } @end #endif BOOL mqttLogEnable = NO; @implementation MQTTLog DDLogLevel ddLogLevel = DDLogLevelVerbose; + (void)setLogLevel:(DDLogLevel)logLevel { ddLogLevel = logLevel; } + (void)setLogEnable:(BOOL)logEnable { mqttLogEnable = logEnable; if (logEnable) { [MQTTLog startDDLogger]; } } + (void)startDDLogger { #ifdef LUMBERJACK #ifdef DEBUG //[DDLog addLogger:[DDTTYLogger sharedInstance]]; // TTY = Xcode console [[DDTTYLogger sharedInstance] setColorsEnabled:YES]; [DDLog addLogger:[DDOSLogger sharedInstance]]; // ASL = Apple System Logs #endif NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; [dateFormatter setFormatterBehavior:NSDateFormatterBehavior10_4]; // 10.4+ style [dateFormatter setDateFormat:@" YYYYMMDD-HHmms.sss "]; NSArray *path = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES); NSString *folderPath = [NSString stringWithFormat:@"%@/QiTestSDK/QiTestSDKLogs", path[0]]; if (! [[NSFileManager defaultManager] fileExistsAtPath:folderPath]) { [[NSFileManager defaultManager] createDirectoryAtPath:folderPath withIntermediateDirectories:YES attributes:nil error:nil]; } DDLogFileManagerDefault *fileManager = [[DDLogFileManagerDefault alloc] initWithLogsDirectory:folderPath]; DDFileLogger *fileLogger = [[DDFileLogger alloc] initWithLogFileManager:fileManager]; fileLogger.rollingFrequency = 60 * 60 * 24 * 3; // 3 days rolling fileLogger.logFileManager.maximumNumberOfLogFiles = 5; fileLogger.logFileManager.logFilesDiskQuota = 50 * 1024 * 1024; // 50M fileLogger.maximumFileSize = 10 * 1024 * 1024; fileLogger.logFormatter = [[DDLogFileFormatter alloc] init]; [DDLog addLogger:fileLogger]; # endif} + (void) customLogWithFormatString: (nsstrings *) formatString {if (mqttLogEnable) {/ / opens the Log NSLog (@ "% @". formatString); } } @endCopy the code

In this way, the macro definition can be compatible with CocoaLumberjack and log switch. If you want to implement the “mount” of CocoaLumberjack in a more elegant way, please refer to the two ways to implement the dismantling of a Framework in iOS App.


Recommended articles:

IOS App can be disassembled in a framework of two ways to customize WKWebView display content (a) Swift 5.1 (6) – function Swift 5.1 (5) – Control flow Xcode11 new project SceneDelegate iOS IOS App startup optimization (a) — understand the App startup process iOS WKWebView basic use Swift 5.1 (4) – collection type Strange dance weekly