CocoaPods trunk is moving to be read-only. Read more on the blog, there are 19 months to go.
TestsTested | ✗ |
LangLanguage | Obj-CObjective C |
License | Custom |
ReleasedLast Release | Feb 2018 |
Maintained by Georgiy Malyukov.
Simple iOS managed logging library in Objective-C.
Alternatively you can directly add all library's source files to your project.
#import "RSLogger.h"
.Let's imagine you're developing client-server application. You want to log network activity, cache management and app events, for example. We will create necessary loggers, then log some messages and then flush several messages groups to physical file.
// initialize loggers
RSLog *logNetwork = [[RSLog alloc] initWithGroup:@"network"];
RSLog *logCache = [[RSLog alloc] initWithGroup:@"cache"];
// attach them to the singleton logging hub
[[RSLogHub instance] addLog:logNetwork];
[[RSLogHub instance] addLog:logCache];
// ...
// log some messages, for example, after app's start
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
RSLOGFUNC; // log current method
RSLOG(@"app started"); // each NSObject descendant obtains its own logger automatically
[logNetwork log:@"network activity: %d", self.isNetworkActive];
[logCache log:@"cache system activated."];
// ...
}
// then flush your messages into file, for example, when your app is going to background
- (void)applicationDidEnterBackground:(UIApplication *)application {
RSLOGFUNC;
// what if we want to store network/cache and app's logs in different files?
// no problem - use two different recorders:
RSLogRecorder *recNetwork = [[RSLogRecorder alloc] initWithName:@"networkLogs"
recordingGroups:@[@"network", @"cache"]];
// another one for your app delegate
// logger injected by default has group name which equals to containing class name
NSString *groupApp = NSStringFromClass([UIApplication sharedApplication].delegate.class);
RSLogRecorder *recApp = [[RSLogRecorder alloc] initWithName:@"appLogs"
recordingGroups:@[groupApp]];
// then flush to files
[recNetwork flush];
[recApp flush];
}
That's it! Check your device documents directory for the following files:
- networkLogs.log
- appLogs.log
All your classes where RSLogger.h
is imported will automatically obtain their own logger. You can access this logger at any time by calling the property declared as
@property (readonly, nonatomic) RSLog *logger;
You are free to use this RSLog
class instance for logging your messages. Also for your convenience there are RSLOG
and RSLOGT
macroses (described below).
By default this logger will have name equals to class name. You can change this by overriding property in your class like this:
- (NSString *)loggerGroupName {
return @"MyCustomLoggerGroup";
}
All loggers exist only while your application is alive, because they stored just in device's operating memory. If you want to store your logs in physical files, you can use class called RSLogRecorder
.
This class can record specific logging groups and store them into physical file. RSLogRecorder
object can be instantiated whenever you need by using several initializers:
- (instancetype)initWithName:(NSString *)name
recordingGroups:(NSArray<NSString *> *)loggerGroups;
- (instancetype)initWithName:(NSString *)name
recordingGroups:(NSArray<NSString *> *)loggerGroups
filePath:(NSString * _Nullable)path;
- (instancetype)initWithName:(NSString *)name
recordingGroups:(NSArray<NSString *> *)loggerGroups
uploadURL:(NSString * _Nullable)url;
The difference is only in specifying target physical file's path. If you will not specify it then default file path will be used:
/<DOCUMENTS_DIR>/<RSLogRecorder_Instance_Name>.log
After instantiating RSLogRecorder
you can use single method to overwrite target file and store all messages:
- (void)flush;
This method executes in a separated thread so you should not worry about performance issues.
Also you can access RSLogHub
singleton directly for acquiring all logged messages from all objects in your application, or only loggers with specific group names, by using some properties and methods like these:
// contains all logged messages from all loggers inside your app
@property (readonly, nonatomic) NSArray<RSLogMessage *> *allMessages;
// returns only loggers with specified group names
- (NSArray<RSLog *> *)loggersWithGroups:(NSArray<NSString *> *)groups;
Please see well-documented header files and example project for detailed information.
All RSLog
class instances have specific property called configuration
of type RSLogConfiguration
. It contains configuration which uses by this concrete logger on incoming messages. This property is usually set to nil
and uses defaultConfiguration
property declared in RSLogHub
class. Default rules are:
If you want to use another configuration for all loggers at one moment - just reset defaultConfiguration
property in RSLogHub
class instance. Also you can configure any concrete logger by resetting its own configuration
property with new logging settings.
Please note that if you reset configuration
property for a concrete RSLog
class instance then it will not be affected by RSLogHub
global configuration even if you disable logging in it. If you want to remove configuration from concrete logger to use defaultConfiguration
instead then just set configuration
property for this logger to nil
.
You can upload your logs as text/plain
value inside HTTP request body by setting up uploadURL
property and calling upload
method. Your server must support plain text receiving inside HTTP body in this case.
Centralized manager of all loggers registered in your application. Very convenient access point to receive partial or full information about all logged messages from loggers in all objects within your application. You can acquire all messages or all loggers used by your app at the moment, also you can access loggers or messages with specific groups only to filter your output results. See RSLogHub
header file to get detailed information.
RSLogger library contains main class that encapsulates all logging methods called RSLog
. It is completely documented with Apple HeaderDoc notation and is very easy to use.
At first please note that there is an RSLog
category for base NSObject
class (imports automatically with RSLogger.h
header file). After importing RSLogger library all your classes receive readonly public property declared as
@property (readonly, nonatomic) RSLog *logger;
This property will be instantiated after its first call. RSLog
class instance will have a group name equals to your own class name where this logger is injected.
Also this category contains two macroses for convenient logging text-only messages without formatting arguments:
RSLOGT(target, message, ...) // logs your message into target's logger
RSLOGF(message, ...) // logs your message into self logger with arguments
RSLOG(message) // calls RSLOGF macro with nil arguments
RSLOGFUNC // logs current function
Of course, you are free to create and instantiate your own RSLog
class instances in addition to internal objects' loggers.
The RSLog class has two initializers declared as follows:
- (instancetype)init; // empty group name
- (instancetype)initWithGroup:(NSString * _Nullable)group;
All loggers can have they own logical group. For example, if you want to have a distinct loggers for your network, storage, database management classes and so on, then you can instantiate separate loggers for each of these modules with human-readable group names.
Default logging method can receive variable format arguments lists:
- (void)log:(NSString *)format, ...; // logs a message into logger
Usage example:
RSLOGT(myObject, @"Object updated.", nil); // equals to [myObject.logger log:@"Object updated."]
RSLOG(@"Models processed."); // equals to [self.logger log:@"Models processed."]
NSString *host = "127.0.0.1";
RSLog *netLogger = [[RSLog alloc] initWithGroup:@"network"];
[netLogger log:@"Connected to host: %@", host];
Output results will look like this:
[MyObjectClass] Object updated.
[MyRootClass] Models processed.
[network] Connected to host: 127.0.0.1
Please note that these methods will not do anything if logger's configuration isLoggingEnabled
flag set to NO
.
All logged messages can be accessed through the two public properties inside RSLog
declared as
@property (readonly, nonatomic) NSArray<RXLogMessage *> *messages;
@property (readonly, nonatomic) NSString *messagesString;
Note that the messagesString
property will return all messages joined by the new line character \n
.
Let's imagine you want to join these loggers into a new one after some event happened. You can do it by calling this method:
+ (RSLog *)loggerByJoining:(NSArray<RSLog *> *)loggers group:(NSString * _Nullable)group;
This one will instantiate a new RSLog
class instance with optional group
value, and all messages from loggers taken with the first argument will be joined in a new one. Example (using the code above):
RSLog *commonLogger = [RSLog loggerByJoining:@[myObject.logger, self.logger, netLogger] group:@"common"];
[commonLogger log:@"New message 1"];
[commonLogger log:@"New message 2"];
All messages of incoming loggers are automatically sorted by date in ascending order. Output logs from commonLogger
will look like this:
[MyObjectClass] Object updated.
[MyRootClass] Models processed.
[network] Connected to host: 127.0.0.1
[common] New message 1
[common] New message 2
Also you can inject any other list of logged messages right inside your logger by calling this method:
- (void)injectMessages:(NSArray<RSLogMessage *> *)messages;
These messages also will be automatically joined with your logger's messages and sorted by their dates in ascending order.
This class represents a single logging message information, such as messageUID
with unique message ID, date
of this message creation, message text
and optional group
name for more deep logical grouping (for example, each of your loggers can have "error", "warning" and "notification" messages at the same time).
Each message can be displayed in a system console or sent to any other output stream by calling its NSObject's description
property. Date of a message will be displayed automatically, including milliseconds and timezone.
This class represents logging configuration that can be assigned to any concrete logger or the "global" RSLogHub
defaultConfiguration
property. Configuration class instance is immutable. You can configure properties with initializers. The properties are:
isLoggingEnabled
. Indicates whether this configuration allows to log any messages. If set to NO
then no incoming messages will be saved while this configuration is in use.printMode
. Determines how standard NSLog()
should be called. Each logged message can be displayed in system console asynchronously (by default) and synchronously, also you can disable printing at all.In most cases you may not use your own configurations, but if it's necessary please remember about several moments:
RSLogHub
class instance contains defaultConfiguration
property. You can reset it with your own configuration. This configuration uses by default by the all loggers in your application, if they have no their own configurations setup.RSLog
class instance can be configured with its own configuration
property. By default it's set to nil
and uses global defaultConfiguration
instead. You can setup it with custom RSLogConfiguration
class instance or set to nil
again to reset settings to defaults.defaultConfiguration
will NOT affect loggers that have been already configured with their own configurations.Apache. See LICENSE
for details.