One of the most helpful components of an actionable bug report is a complete set of logs. Aardvark makes it simple to add logs with the logging utilities in the CoreAardvark framework.
The easiest way to get started logging with Aardvark is by replacing calls to print
with log
in Swift and calls to NSLog
with ARKLog
in Objective-C.
log("Hello world")
ARKLog(@"Hello world");
By default, this will log messages to the Aardvark log store instead of the console. If you would like the messages to be logged to the console as well, toggle the default log store's printsLogsToConsole
property:
ARKLogDistributor.default().defaultLogStore.printsLogsToConsole = true
A recommended pattern for logging is to keep your log messages simple and attach details of the log in the parameters
field. You can attach key/value pairs of strings to your log messages to provide further debugging data, while keeping your logs easy to scan through in a list of messages.
log("Said hello to user", parameters: ["user_name": user.name])
ARKLogWithParameters(@{ @"user_name": [user name] }, @"Said hello to user");
If you prefer to use dependency injection rather than global functions, you can inject an ARKLogDistributor
to your logging call sites.
func sayHelloToPerson(named name: String, on logDistributor: ARKLogDistributor) {
logDistributor.log("Hello \(name)")
}
- (void)sayHelloToPersonNamed:(NSString *)name onLogDistributor:(ARKLogDistributor *)logDistributor;
{
[logDistributor logWithFormat:@"Hello %@", name];
}
By default, all logs are sent to the same log file. If you would prefer to send some logs into separate log files, you can add multiple log stores to the distributor and set each store's logFilterBlock
to filter incoming logs.
To facilitate filtering, log messages contain a userInfo
dictionary. Unlike the parameters
dictionary, the userInfo
is not persisted with the log message.
log("Loaded data", userInfo: ["category": "Core Data"])
For example, we can set up a second log store for all of the logs related to Core Data and filter these logs out of the main log store. This could be helpful if our Core Data implementation consistently runs tasks in the background and creates noise in the main log store.
// Create the new log store.
let coreDataLogStore = ARKLogStore(persistedLogFileName: "CoreDataLogs.data")
// Set the new log store to only include logs related to Core Data.
coreDataLogStore.logFilterBlock = { message in
return message.userInfo?["category"] == "Core Data"
}
// Add the new log store to the default distributor.
ARKLogDistributor.default().add(coreDataLogStore)
// Set the default log store to exclude log related to Core Data.
ARKLogDistributor.default().defaultLogStore.logFilterBlock = { message in
return !coreDataLogStore.logFilterBlock(message)
}
See SampleViewController’s tapGestureLogStore
for an example of how this works.
One log can be easily distributed to multiple services by adding objects conforming to ARKLogObserver to the default ARKLogDistributor via addLogObserver:
. SampleCrashlyticsLogObserver is an example of an ARKLogObserver that sends event logs to Crashlytics.
When logs are shown in the in-app log viewer or attached to a bug report email, they are formatted into plain text. You can change how these messages look by creating a formatter that conforms to ARKLogFormatter and setting it as the formatter where desired (e.g. as the logFormatter
on an ARKEmailBugReporter).