Better iPhone/Mac logging with GTMLogger

14 Mar
2010

I left NSLog a long time ago, using my own written wrappers (that compile out on release), then using wrappers from three20/facebook (not that different, just more log levels)

Now I’ll switch again, this time to a proper logging system. Coming from Java, you know log4j and the concepts there. GTMLogger is the next best thing to it in ObjectiveC-Land. It’s also open source and free, from the google-toolbox-for-mac. (Apache Licence 2)

Check out this guide for a step-by-step integration, complete with user level logging.

Integration with your Project

From the google framework  you need:

Add them to your project (copy the files) and add GTMLogger.h to your precompiled headers. You’re mostly done! To add fance two-way logging (system AND filesystem) add this initializer to your AppDelegate:

#define kDebugLogPath @"logfile.log"
#define kDebugFileMaxSize 200 * 1024 // byte

+ (NSString *)logFilePath {
NSString *documentsDirectory = [NSHomeDirectory() stringByAppendingPathComponent:@"tmp"];
NSString *logFilePath = [NSString stringWithFormat:@"%@/%@",documentsDirectory, kDebugLogPath];
return logFilePath;
}

// configure the google log writer
NSString *logFilePath = [AppDelegate logFilePath];

  // check for file, trunicate it to kDebugFileMaxSize or create if not found
  NSFileHandle *file = [NSFileHandle fileHandleForUpdatingAtPath:logFilePath];
  if (file) {
    unsigned long long maxFileOffset = [file seekToEndOfFile];
    if (maxFileOffset > kDebugFileMaxSize) {
      // read file, trunicate, save, reopen
      [file seekToFileOffset:maxFileOffset - kDebugFileMaxSize];
      NSMutableData *data = [NSMutableData dataWithData:[file readDataToEndOfFile]];
      [file seekToFileOffset:0];
      [file writeData:data];
      [file truncateFileAtOffset:kDebugFileMaxSize];
      [file seekToEndOfFile];
    }
  }else {
    [[NSFileManager defaultManager] createFileAtPath:logFilePath contents:nil attributes:nil];
    file = [NSFileHandle fileHandleForUpdatingAtPath:logFilePath];
  }
NSArray *writers = [NSArray arrayWithObjects:file, [NSFileHandle fileHandleWithStandardOutput], nil];
GTMLogger *logger = [GTMLogger sharedLogger];
[logger setWriter:writers];
[logger setFilter:[GTMLogLevelFilter new]];
GTMLoggerInfo(@"Logging System Initialized");
}

- (void)applicationDidFinishLaunching:(UIApplication*)application {
[self configureLogger];
...
}

This code manages your logfile and trunicates it to kDebugFileMaxSize (byte). It also sets two writers (console, file) and sets up the default LogLevelFilter.

Logging

Just replace your NSLog-calls with GTMLoggerDebug(…), GTMLoggerInfo(…), GTMLoggerError(…)

GTMLogDebug will be compiled out, other calls will be available in your release*. Beware that too much logging can decrease performance.

What you probably want is a setting like “enable logging” that the user can turn on if he’s some strange bug that you can’t reproduce. That’s possible with Log Filters:

* Add GTMVerboseLogging (BOOL) to your settings, call it “Logging” – that’s it! If enabled, Info-Class logs are logged, if disabled, only errors are logged.

Files in the tmp-directory are not backed up and may be deleted at any time. But as it’s just logging data, we don’t really care.

Your application should remove files from this directory when it determines they are no longer needed. (The system may also purge lingering files from this directory when your application is not running.)

If you really need your logs a bit more secure, change “tmp” to “Library\Caches”, files there won’t be backed up, but also won’t be deleted randomly by the system.

For more information, just check out the GTMLogger.h-Header. Google has excellent documentation.

If you use this code, feel free to drop a comment here!

Related posts:

  1. Better logging for iOS and Mac: cocoalumberjack
  2. Logging, again!
  3. Detect if an iPhone is jailbroken
  4. Custom Formatter for the cocoalumberjack logging framework
  5. HowTo: AdHoc distributing an iPhone app

Comment Form

top

Switch to our mobile site