aboutsummaryrefslogtreecommitdiffstats
path: root/Source/SPLogger.m
diff options
context:
space:
mode:
authorrowanbeentje <rowan@beent.je>2009-08-21 00:03:16 +0000
committerrowanbeentje <rowan@beent.je>2009-08-21 00:03:16 +0000
commit68bbc4aae63e38eae25236c80dbc08896537755e (patch)
tree3b39943f9dbc6a54a862339d53c1463ce8261164 /Source/SPLogger.m
parentb3c737fa485e28a81cc3de8b076fa40aa083fb37 (diff)
downloadsequelpro-68bbc4aae63e38eae25236c80dbc08896537755e.tar.gz
sequelpro-68bbc4aae63e38eae25236c80dbc08896537755e.tar.bz2
sequelpro-68bbc4aae63e38eae25236c80dbc08896537755e.zip
- Add a "SPLogger" class to allow easy debug builds when attempting to pinpoint the cause of specific user issues; see SPLogger.m for very brief usage notes
Diffstat (limited to 'Source/SPLogger.m')
-rw-r--r--Source/SPLogger.m143
1 files changed, 143 insertions, 0 deletions
diff --git a/Source/SPLogger.m b/Source/SPLogger.m
new file mode 100644
index 00000000..8c65f245
--- /dev/null
+++ b/Source/SPLogger.m
@@ -0,0 +1,143 @@
+//
+// $Id$
+//
+// SPLogger.m
+// sequel-pro
+//
+// Created by Rowan Beentje on 17/06/2009.
+// Copyright 2009 Rowan Beentje. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// More info at <http://code.google.com/p/sequel-pro/>
+
+#import "SPLogger.h"
+
+static SPLogger *logger = nil;
+
+/**
+ * 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", ...]
+ * a file will be created on the user's desktop including timestamps and
+ * the log message.
+ * This allows use of fine-grained and detailed logging, without asking the user
+ * to copy text from a console log via NSLog.
+ * As each log line must by synched to disk as soon as it is received, for safety,
+ * this class can add a performance hit when lots of logging is used.
+ */
+
+@implementation SPLogger
+
+/*
+ * Returns the shared logger object.
+ */
++ (SPLogger *)logger
+{
+ @synchronized(self) {
+ if (logger == nil) {
+ [[self alloc] init];
+ }
+ }
+
+ return logger;
+}
+
+#pragma mark -
+#pragma mark Initialisation and teardown
+
++ (id)allocWithZone:(NSZone *)zone
+{
+ @synchronized(self) {
+ if (logger == nil) {
+ logger = [super allocWithZone:zone];
+
+ return logger;
+ }
+ }
+
+ return 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]];
+
+ 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%i)\n", bundleName, [[[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"] intValue]]];
+ [logFileHandle writeData:[logStart dataUsingEncoding:NSUTF8StringEncoding]];
+ }
+ }
+ }
+
+ return self;
+}
+
+#pragma mark -
+#pragma mark Logging functions
+
+- (void) log:(NSString *)theString, ...
+{
+ if (!initializedSuccessfully) return;
+
+ // Extract any supplied arguments and build the formatted log string
+ va_list arguments;
+ va_start(arguments, theString);
+ NSString *logString = [[NSString alloc] initWithFormat:theString arguments:arguments];
+ 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 synchronizeFile];
+
+ [logString release];
+}
+
+- (void) outputTimeString
+{
+ if (!initializedSuccessfully) return;
+
+ [logFileHandle writeData:[[NSString stringWithFormat:@"Launched at %@\n\n", [[NSDate date] description]] dataUsingEncoding:NSUTF8StringEncoding]];
+}
+
+@end