Here's a design I typically use for a logging class that can be multi-provider. It allows for easy swaps between analytics, crash reporting and beta OTA providers and it uses preprocessor directives so that certain services are active in certain environments. This example uses CocoaLumberjack but you could make it work with your logging framework of choice.
@class CLLocation;
@interface TGLogger : NSObject
+ (void)startLogging;
+ (void)stopLogging;
+ (NSString *)getUdidKey;
+ (void)setUserID:(NSString *)userID;
+ (void)setUsername:(NSString *)username;
+ (void)setUserEmail:(NSString *)email;
+ (void)setUserAge:(NSUInteger)age;
+ (void)setUserGender:(NSString *)gender;
+ (void)setUserLocation:(CLLocation *)location;
+ (void)setUserValue:(NSString *)value forKey:(NSString *)key;
+ (void)setIntValue:(int)value forKey:(NSString *)key;
+ (void)setFloatValue:(float)value forKey:(NSString *)key;
+ (void)setBoolValue:(BOOL)value forKey:(NSString *)key;
extern void TGReportMilestone(NSString *milestone, NSDictionary *parameters);
extern void TGReportBeginTimedMilestone(NSString *milestone, NSDictionary *parameters);
extern void TGReportEndTimedMilestone(NSString *milestone, NSDictionary *parameters);
@end
Now the implementation file:
#import "TGLogger.h"
#import "TGAppDelegate.h"
#import <CocoaLumberjack/DDASLLogger.h>
#import <CocoaLumberjack/DDTTYLogger.h>
#import <AFNetworkActivityLogger/AFNetworkActivityLogger.h>
@import CoreLocation;
#ifdef USE_CRASHLYTICS
#import <Crashlytics/Crashlytics.h>
#import <CrashlyticsLumberjack/CrashlyticsLogger.h>
#endif
#ifdef USE_FLURRY
#import <FlurrySDK/Flurry.h>
#endif
#import <Flurry.h>
@implementation TGLogger
+ (void)startLogging
{
[DDLog addLogger:[DDASLLogger sharedInstance]];
[DDLog addLogger:[DDTTYLogger sharedInstance]];
[[DDTTYLogger sharedInstance] setColorsEnabled:YES];
[[DDTTYLogger sharedInstance] setForegroundColor:[UIColor blueColor] backgroundColor:nil forFlag:LOG_FLAG_INFO];
[[DDTTYLogger sharedInstance] setForegroundColor:[UIColor orangeColor] backgroundColor:nil forFlag:LOG_FLAG_WARN];
[[DDTTYLogger sharedInstance] setForegroundColor:[UIColor redColor] backgroundColor:nil forFlag:LOG_FLAG_ERROR];
[[AFNetworkActivityLogger sharedLogger] startLogging];
#ifdef DEBUG
[[AFNetworkActivityLogger sharedLogger] setLevel:AFLoggerLevelInfo];
#else
[[AFNetworkActivityLogger sharedLogger] setLevel:AFLoggerLevelWarn];
#endif
#if defined(USE_CRASHLYTICS) || defined(USE_FLURRY)
NSString *udid = [TGLogger getUdidKey];
TGLogInfo(@"Current UDID is: %@", udid);
#endif
#ifdef USE_CRASHLYTICS
// Start Crashlytics
[Crashlytics startWithAPIKey:TGCrashlyticsKey];
[Crashlytics setUserIdentifier:udid];
[DDLog addLogger:[CrashlyticsLogger sharedInstance]];
TGLogInfo(@"Crashlytics started with API Key: %@", TGCrashlyticsKey);
#endif
#ifdef USE_FLURRY
[Flurry setAppVersion:[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"]];
[Flurry setSecureTransportEnabled:YES];
[Flurry setShowErrorInLogEnabled:YES];
[Flurry setLogLevel:FlurryLogLevelCriticalOnly];
[Flurry startSession:TGFlurryApiKey];
TGLogInfo(@"Flurry started with API Key %@ and for version %@", TGFlurryApiKey, [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"]);
TGLogInfo(@"Flurry Agent Version %@", [Flurry getFlurryAgentVersion]);
#endif
TGLogInfo(@"Logging services started");
}
+ (void)stopLogging
{
TGLogInfo(@"Shutting down logging services");
[DDLog removeAllLoggers];
}
+ (NSString *)getUdidKey
{
return [[UIDevice currentDevice] identifierForVendor].UUIDString;
}
+ (void)setUserID:(NSString *)userID
{
#ifdef USE_CRASHLYTICS
[Crashlytics setUserIdentifier:userID];
#endif
}
+ (void)setUsername:(NSString *)username
{
#ifdef USE_CRASHLYTICS
[Crashlytics setUserName:username];
#endif
#ifdef USE_FLURRY
[Flurry setUserID:username];
#endif
}
+ (void)setUserEmail:(NSString *)email
{
#ifdef USE_CRASHLYTICS
[Crashlytics setUserEmail:email];
#endif
}
+ (void)setUserAge:(NSUInteger)age
{
#ifdef USE_FLURRY
[Flurry setAge:(int)age];
#endif
}
+ (void)setUserGender:(NSString *)gender
{
#ifdef USE_FLURRY
[Flurry setGender:gender];
#endif
}
+ (void)setUserLocation:(CLLocation *)location
{
#ifdef USE_FLURRY
[Flurry setLatitude:location.coordinate.latitude longitude:location.coordinate.longitude horizontalAccuracy:location.horizontalAccuracy verticalAccuracy:location.verticalAccuracy];
#endif
#ifdef USE_CRASHLYTICS
[Crashlytics setObjectValue:location forKey:@"location"];
#endif
}
+ (void)setUserValue:(NSString *)value forKey:(NSString *)key
{
#ifdef USE_CRASHLYTICS
[Crashlytics setObjectValue:value forKey:key];
#endif
}
#pragma mark - Report key/values with crash logs
+ (void)setIntValue:(int)value forKey:(NSString *)key
{
#ifdef USE_CRASHLYTICS
[Crashlytics setIntValue:value forKey:key];
#endif
}
+ (void)setBoolValue:(BOOL)value forKey:(NSString *)key
{
#ifdef USE_CRASHLYTICS
[Crashlytics setBoolValue:value forKey:key];
#endif
}
+ (void)setFloatValue:(float)value forKey:(NSString *)key
{
#ifdef USE_CRASHLYTICS
[Crashlytics setFloatValue:value forKey:key];
#endif
}
void TGReportMilestone(NSString *milestone, NSDictionary *parameters)
{
NSCParameterAssert(milestone);
TGLogCInfo(@"Reporting %@", milestone);
#ifdef USE_FLURRY
[Flurry logEvent:milestone withParameters:parameters];
#endif
}
void TGReportBeginTimedMilestone(NSString *milestone, NSDictionary *parameters)
{
NSCParameterAssert(milestone);
TGLogCInfo(@"Starting timed event %@", milestone);
#ifdef USE_FLURRY
[Flurry logEvent:milestone withParameters:parameters timed:YES];
#endif
}
void TGReportEndTimedMilestone(NSString *milestone, NSDictionary *parameters)
{
NSCParameterAssert(milestone);
TGLogCInfo(@"Ending timed event %@", milestone);
#ifdef USE_FLURRY
[Flurry endTimedEvent:milestone withParameters:parameters];
#endif
}
@end