美文网首页
控制日志的开关

控制日志的开关

作者: 大成小栈 | 来源:发表于2019-10-30 19:24 被阅读0次

    在开发过程中打印日志功能是必不可少的,日志的处理主要分为以下几种:

    • Debug/Release模式下日志的处理;
    • 将日志记录在本地文件,并上传服务器;
    • 由业务App控制是否开启日志。
    1. Debug/Release模式下日志的处理

    第一点在开发业务App时最常使用,一行语句就搞定:

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

    如果图方便,可以将以上代码写到prefix.pch文件中,在需要输出log的地方调用DLog(...),即可在Debug/Release模式切换时,自动开启/关闭打印log。

    2. 将日志记录在本地文件

    将日志记录在本地文件常用三方库CocoaLumberjack来处理,我们通过这个库可以将日志输出至控制台,也可以写在本地文件中,我们还可以设置输出日志等级。具体CocoaLumberjack的使用方式可以参考iOS开发之日志框架CocoaLumberjack的配置与使用详解

    3. 兼容CocoaLumberjack的同时,控制日志的开关

    这个场景经常出现在framework开发过程中,我们开发一个framework,其中需要自己输出日志到本地文件,另外宿主App联调时,也常常需要主动控制log的开和关。我们定义了一个LogManager类,LogManager.h代码如下:

    @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;
    
    @end
    

    LogManager.m代码如下:

    #import "MQTTLog.h"
    
    #ifdef LUMBERJACK
    
    // 自定义日志文件里  log的格式
    @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-HHmmss.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-HHmmss.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:(NSString *)formatString {
        
        if (mqttLogEnable) {// 开启了Log
            NSLog(@"%@", formatString);
        }
    }
    
    @end
    

    注:该段代码中没有使用CocoaLumberjack控制台打印,控制台打印直接使用了NSLog()

    这样通过宏定义,既能兼容CocoaLumberjack,也能实现log的开关。如果想美观一点实现CocoaLumberjack的“挂载”,请参考iOS App中实现可拆卸一个framework的两种方式

    相关文章

      网友评论

          本文标题:控制日志的开关

          本文链接:https://www.haomeiwen.com/subject/kmuevctx.html