diff options
author | stuconnolly <stuart02@gmail.com> | 2010-04-24 22:20:04 +0000 |
---|---|---|
committer | stuconnolly <stuart02@gmail.com> | 2010-04-24 22:20:04 +0000 |
commit | d04a1612e5c26e2752d6c30c5aaf5289d01e90a9 (patch) | |
tree | 4b71bfb5f0045282982f280bea0cd1b2684b0cf0 /Source/SPLogger.m | |
parent | 452e5fb8e8fd1f22be98b26ece0010af09fb3d7d (diff) | |
download | sequelpro-d04a1612e5c26e2752d6c30c5aaf5289d01e90a9.tar.gz sequelpro-d04a1612e5c26e2752d6c30c5aaf5289d01e90a9.tar.bz2 sequelpro-d04a1612e5c26e2752d6c30c5aaf5289d01e90a9.zip |
Enhance SPLogger by adding the ability to run leaks() against the application upon termination with the result being written to /tmp.
To enable call setDumpLeaksOnTermination on SPLogger.
Note, that SPLogger has been restructed to accommodate calling this method without writing the additional log file to the user's desktop. Could probably be enhanced a bit by someone with better C skills than me.
Diffstat (limited to 'Source/SPLogger.m')
-rw-r--r-- | Source/SPLogger.m | 154 |
1 files changed, 116 insertions, 38 deletions
diff --git a/Source/SPLogger.m b/Source/SPLogger.m index d492fe32..5b0e4a05 100644 --- a/Source/SPLogger.m +++ b/Source/SPLogger.m @@ -25,8 +25,20 @@ #import "SPLogger.h" +#include <stdio.h> +#include <dirent.h> +#include <sys/dir.h> +#include <sys/types.h> + static SPLogger *logger = nil; +@interface SPLogger (PrivateAPI) + +- (void)_initLogFile; +- (void)_outputTimeString; + +@end + /** * This is a small class intended to aid in user issue debugging; by including * the header file, and using [[SPLogger logger] log:@"String with format", ...] @@ -77,41 +89,8 @@ static SPLogger *logger = nil; - (id)init { if ((self = [super init])) { - NSArray *paths = NSSearchPathForDirectoriesInDomains (NSDesktopDirectory, NSUserDomainMask, YES); - NSString *logFilePath = [NSString stringWithFormat:@"%@/Sequel Pro Debug Log.txt", [paths objectAtIndex:0]]; - + dumpLeaksOnTermination = NO; initializedSuccessfully = YES; - - // Check if the debug file exists, and is writable - if ( [[NSFileManager defaultManager] fileExistsAtPath:logFilePath] ) { - if ( ![[NSFileManager defaultManager] isWritableFileAtPath:logFilePath] ) { - initializedSuccessfully = NO; - NSRunAlertPanel(@"Logging error", @"Log file exists but is not writeable; no debug log will be generated!", @"OK", nil, nil); - } - - // Otherwise try creating one - } else { - if ( ![[NSFileManager defaultManager] createFileAtPath:logFilePath contents:[NSData data] attributes:nil] ) { - initializedSuccessfully = NO; - NSRunAlertPanel(@"Logging error", @"Could not create log file for writing; no debug log will be generated!", @"OK", nil, nil); - } - } - - // Get a file handle to the file if possible - if (initializedSuccessfully) { - logFileHandle = [NSFileHandle fileHandleForWritingAtPath:logFilePath]; - if (!logFileHandle) { - initializedSuccessfully = NO; - NSRunAlertPanel(@"Logging error", @"Could not open log file for writing; no debug log will be generated!", @"OK", nil, nil); - } else { - [logFileHandle retain]; - [logFileHandle seekToEndOfFile]; - NSString *bundleName = [[NSFileManager defaultManager] displayNameAtPath:[[NSBundle mainBundle] bundlePath]]; - NSMutableString *logStart = [NSMutableString stringWithString:@"\n\n\n==========================================================================\n\n"]; - [logStart appendString:[NSString stringWithFormat:@"%@ (r%ld)\n", bundleName, (long)[[[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"] integerValue]]]; - [logFileHandle writeData:[logStart dataUsingEncoding:NSUTF8StringEncoding]]; - } - } } return self; @@ -120,9 +99,11 @@ static SPLogger *logger = nil; #pragma mark - #pragma mark Logging functions -- (void) log:(NSString *)theString, ... +- (void)log:(NSString *)theString, ... { if (!initializedSuccessfully) return; + + if (!logFileHandle) [self _initLogFile]; // Extract any supplied arguments and build the formatted log string va_list arguments; @@ -131,16 +112,113 @@ static SPLogger *logger = nil; va_end(arguments); // Write the log line, forcing an immediate write to disk to ensure logging - [logFileHandle writeData:[[NSString stringWithFormat:@"%@ %@\n", [[NSDate date] descriptionWithCalendarFormat:@"%H:%M:%S" timeZone:nil locale:[[NSUserDefaults standardUserDefaults] dictionaryRepresentation]], logString] dataUsingEncoding:NSUTF8StringEncoding]]; + [logFileHandle writeData:[[NSString stringWithFormat:@"%@ %@\n", [[NSDate date] descriptionWithCalendarFormat:@"%H:%M:%S" timeZone:nil locale:[[NSUserDefaults standardUserDefaults] dictionaryRepresentation]], logString] dataUsingEncoding:NSUTF8StringEncoding]]; [logFileHandle synchronizeFile]; [logString release]; } -- (void) outputTimeString +- (void)setDumpLeaksOnTermination { - if (!initializedSuccessfully) return; + dumpLeaksOnTermination = YES; +} + +- (void)dumpLeaks +{ + if (dumpLeaksOnTermination) { + + // Remove old leaks logs + int count, i; + int isSPLeaksLog(); + struct direct **files; + + count = scandir("/tmp", &files, isSPLeaksLog, NULL); + + char fpath[32]; + + for (i = 0; i < count; i++) + { + snprintf(fpath, sizeof(fpath), "/tmp/%s", files[i]->d_name); + + if (remove(fpath) != 0) { + printf("Unable to remove Sequel Pro leaks log '%s'", files[i]->d_name); + } + } + + FILE *fp; + FILE *fp2; + size_t len; + + char cmd[32], file[32], buf[512]; + + snprintf(cmd, sizeof(cmd), "/usr/bin/leaks %d", getpid()); + snprintf(file, sizeof(file), "/tmp/sp.leaks.%d.tmp", getpid()); + + // Write new leaks log + if ((fp = popen(cmd, "r")) && (fp2 = fopen(file, "w"))) { + + while(len = fread(buf, 1, sizeof(buf), fp)) + { + fwrite(buf, 1, len, fp2); + } + + pclose(fp); + } + } +} + +int isSPLeaksLog(struct direct *entry) +{ + return (strstr(entry->d_name, "sp.leaks") != NULL); +} + +- (void)_initLogFile +{ + NSArray *paths = NSSearchPathForDirectoriesInDomains (NSDesktopDirectory, NSUserDomainMask, YES); + NSString *logFilePath = [NSString stringWithFormat:@"%@/Sequel Pro Debug Log.log", [paths objectAtIndex:0]]; + + NSFileManager *fileManager = [NSFileManager defaultManager]; + + // Check if the debug file exists, and is writable + if ([fileManager fileExistsAtPath:logFilePath]) { + if (![fileManager isWritableFileAtPath:logFilePath]) { + initializedSuccessfully = NO; + NSRunAlertPanel(@"Logging error", @"Log file exists but is not writeable; no debug log will be generated!", @"OK", nil, nil); + } + // Otherwise try creating one + } + else { + if (![fileManager createFileAtPath:logFilePath contents:[NSData data] attributes:nil]) { + initializedSuccessfully = NO; + NSRunAlertPanel(@"Logging error", @"Could not create log file for writing; no debug log will be generated!", @"OK", nil, nil); + } + } + + // Get a file handle to the file if possible + if (initializedSuccessfully) { + logFileHandle = [NSFileHandle fileHandleForWritingAtPath:logFilePath]; + + if (!logFileHandle) { + initializedSuccessfully = NO; + NSRunAlertPanel(@"Logging error", @"Could not open log file for writing; no debug log will be generated!", @"OK", nil, nil); + } + else { + [logFileHandle retain]; + [logFileHandle seekToEndOfFile]; + + NSString *bundleName = [fileManager displayNameAtPath:[[NSBundle mainBundle] bundlePath]]; + NSMutableString *logStart = [NSMutableString stringWithString:@"\n\n\n==========================================================================\n\n"]; + + [logStart appendString:[NSString stringWithFormat:@"%@ (r%ld)\n", bundleName, (long)[[[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"] integerValue]]]; + [logFileHandle writeData:[logStart dataUsingEncoding:NSUTF8StringEncoding]]; + } + } +} +- (void)_outputTimeString +{ + if (!initializedSuccessfully) return; + [logFileHandle writeData:[[NSString stringWithFormat:@"Launched at %@\n\n", [[NSDate date] description]] dataUsingEncoding:NSUTF8StringEncoding]]; } |