IOS a flexible and extensible open source log Library

Time:2019-12-2

At present, most IOS small development teams don’t pay much attention to log, which makes it difficult to troubleshoot many online or user feedback bugs. For app, a good log system can help us troubleshoot some difficult bugs at the lowest cost. The only thing we need to do is to print logs in the right place and record the health of app. This not only allows us to view the app running log when debugging, but also allows the app to send back the log file in some ways for developers to analyze the problem.

About NSLog

Apple’sNSLogIs a common logging tool for most developers, butNSLogIt still can’t meet our other requirements for log, such as log classification, log persistence, etc. And we knowNSLogIt’s notprintfThe package of ASL is the advanced package of ASL, which Apple also explained in the documentNSLogDesigned forLogs an error messageSo if we use a lot ofNSLog, the performance of app will be very bad. For the performance problems of nslog, please refer to this sunnyxx article [causes of low efficiency of nslog and try to print log with lldb breakpoint]

demand

  • Independent switch. For example, we want to open the console log and file log in the debug version, and only open the file log function in the release version.
  • Scalability and flexibility. We know that after IOS 10, apple suggests usingos.logTo replaceNSLog, we hope to have a log library with strong scalability, so that we can easily replace the underlying implementation of log withos.logWithout changing the original log code.
  • Custom format. You can customize the standard format of log output, and you don’t want a lot of changes to the original log calling interface.
  • Log viewing tool. We knowNSLogAvailable on MACConsole.appSuch a debugging tool enables us to view the app logs at any time even when we are not in the debug mode of Xcode. Even if we want to use Windows PC, we can view the log in non debug mode.
  • Grading and filtering. Log should be divided into different levels. At the same time, we can set different levels of filters under debug and release, and low-level logs can be filtered out. For example: if there are four levels of logs: info, default, warning, and error, we may want to output all levels of logs under debug, but only warning and error under release.

wheel

Get on the wheel, GitHub

Coolog was designed to address these requirements. Coolog has high scalability and flexibility, and provides a browser debugging tool. At present, there are many things that need to be improved in coolog, including that the browser debugging tool is only a demo at present. Welcome to be the contributor of coolog.

Framework

In order to ensure the scalability and flexibility, coolog includes the generator (collager), format protocol and formatter (colformatable and collagformatter), driver (collagger driver), engine (collengine) and manager (collagmanager). The relationship between them is shown in the following figure:
IOS a flexible and extensible open source log Library

Let’s explain their respective functions one by one.

Generator collagger

As the name implies, the generator is responsible for the generation of the final log,COLLoggerIt’s an agreement. Coolog provides three kinds of generators, namelyCOLNSLoggerCOLConsoleLoggerCOLFileLogger, all three classes implementCOLLoggerAgreement- (void)log:(NSString *)logString;This method. In this method, we finally define the last generation method of this type of log. The log engine will call this method to output the log through the driver.
In addition to these three generators, you can also implement your ownCOLLoggerThe protocol comes from defining a generator.

Format protocol

This protocol has only one method, which defines the output format of log.

- (NSString *)completeLogWithType:(COLLogType)type
                              tag:(NSString *)tag
                          message:(NSString *)message
                             date:(NSDate *)date;

Formatter collagformatter

The formatter is implementedCOLFormatableBy default, we provide three formatters corresponding to the above three types of generatorsNSLogFormatterConsoleFormatterFileFormatter, they correspond to native nslog, console and browser tool log and file log respectively. For these three classes, we use class family to provide factory methods to complete initialization, and we do not need to inherit when customizing formatterCOLLogFormatter, it needs to be realizedCOLFormatableThe agreement is enough.

Drive collaggerdriver

The driver is a container. The generator and formatter will be injected into the driver as dependencies. At the same time, the driver is responsible for the configuration of the log level and realizes the hierarchical filtering of the log. The log type is divided into 5 types:Error>Warning>Info>Default>Debug, the filtering level is divided into 7 levels:LevelOff>LevelError>LevelWarning>LevelInfo>LevelDefault>LevelDebug>LevelAllFor example, if the current filtering level isLevelInfo, then onlyErrorWarningInfo These three types of logs will be output. The final drive will be managed by the log engine.

Engine

The engine is responsible for managing all the drives, and it is responsible for starting the log. The engine can remove or add a single log drive at any time to realize independent switching of different logs.

Use

Initialization

[[COLLogManager sharedInstance] setup];
    
[[collagmanager shareinstance] enablefilelog]; // open the file log
[[collagmanager shareinstance] enablecononsolelog]; // open the console log
//[[collagmanager shareinstance] enablenslog]; // generally, console log and nslog are not opened at the same time
    
//Open all levels of logs under debug, and open logs above info level under release
#ifdef DEBUG
    [COLLogManager sharedInstance].level = COLLogLevelAll;
#else
    [COLLogManager sharedInstance].level = COLLogLevelInfo;
#endif

Log

CLogError(@"tag", @"%@", @"log content");
CLogE(@"%@", @"log content");

CLogWarning(@"tag", @"%@", @"log content");
CLogW(@"%@", @"log content");
    
CLogInfo(@"tag", @"%@", @"log content");
CLogI(@"%@", @"log content");
    
CLogDefault(@"tag", @"%@", @"log content");
CLog(@"%@", @"log content");
    
CLogDebug(@"tag", @"%@", @"log content");
CLogD(@"%@", @"log content");

Browser debugging

First, open the browser debugging function.

[[COLLogManager sharedInstance] enableRemoteConsole];

Connect the computer and mobile phone to the same WiFi, open the browser and access [(http://coolog.oss-cn-hangzhou…: / / [yourphoneipaddr]: 9001 / coolog] (http://coolog.oss-cn-hangzhou…: / / [yourphoneipaddr]: 9001 / coolog). Note that the parameter [yourphoneipaddr] after the address is replaced by the IP address of the mobile phone.

The current effect is as follows.
IOS a flexible and extensible open source log Library

Add custom log method

  • Step 1: implement a generator
#import "COLLogger.h"
@interface MyLogger : NSObject <COLLogger>

@end
#import "MyLogger.h"
#import <os/log.h>

@implementation MyLogger
@synthesize formatterClass = _formatterClass;

+ (instancetype)logger {
    return [[MyLogger alloc] init];
}

// This is your own log method. It will be called by log engine. 
- (void)log:(NSString *)logString {
    //For example, here below uses os_log as its implementation.
    os_log(OS_LOG_DEFAULT, "%{public}s", [logString UTF8String]);
}
@end
  • Step 2: implement a formatter
#import "COLLogFormatter.h"

@interface MyLogFormatter : NSObject <COLFormatable>

@end
#import "MyLogFormatter.h"

@implementation MyLogFormatter
// The log's format depends on this method.
- (NSString *)completeLogWithType:(COLLogType)type tag:(NSString *)tag message:(NSString *)message date:(NSDate *)date {
    return [NSString stringWithFormat:@"tag=[%@], type=[%zd], message=[%@], date=[%@]", tag, type, message, date];
}
@end
  • Step 3: instantiate the drive and add it to the log engine
COLLoggerDriver *myDriver = [[COLLoggerDriver alloc] initWithLogger:[MyLogger logger]
                                                              formatter:[[MyLogFormatter alloc] init]
                                                                  level:COLLogLevelInfo];
[[COLLogManager sharedInstance].logEngine addDriver:myDriver];

Epilogue

Log is a step that is easy to be ignored in our development process, but it is also a very important work. We should learn how to record the right log in the right place, which is really helpful for us to reproduce and troubleshoot problems.

At present, there are still many imperfections in coolog, including that the browser debugging tool is also a primary demo state. The follow-up work will be placed in the performance optimization of log, the search and filtering functions of debugging tools, and the UI of debugging tools will be further optimized.