]> err.no Git - sope/commitdiff
stabilized NGLogging - adapted enhancements in parts of NGObjWeb
authorznek <znek@e4a50df8-12e2-0310-a44c-efbce7f8a7e3>
Fri, 19 Nov 2004 04:37:51 +0000 (04:37 +0000)
committerznek <znek@e4a50df8-12e2-0310-a44c-efbce7f8a7e3>
Fri, 19 Nov 2004 04:37:51 +0000 (04:37 +0000)
git-svn-id: http://svn.opengroupware.org/SOPE/trunk@401 e4a50df8-12e2-0310-a44c-efbce7f8a7e3

33 files changed:
sope-appserver/NGObjWeb/ChangeLog
sope-appserver/NGObjWeb/Defaults.plist
sope-appserver/NGObjWeb/DynamicElements/_WOTemporaryHyperlink.m
sope-appserver/NGObjWeb/NGHttp/NGHttp.xcode/project.pbxproj
sope-appserver/NGObjWeb/NGObjWeb.xcode/project.pbxproj
sope-appserver/NGObjWeb/SoObjects/SoObjects.xcode/project.pbxproj
sope-appserver/NGObjWeb/Version
sope-appserver/NGObjWeb/WOHttpAdaptor/WOHttpTransaction.m
sope-appserver/NGObjWeb/WebDAV/WebDAV.xcode/project.pbxproj
sope-core/NGExtensions/ChangeLog
sope-core/NGExtensions/GNUmakefile
sope-core/NGExtensions/NGExtensions.xcode/project.pbxproj
sope-core/NGExtensions/NGExtensions/NGLogAppender.h
sope-core/NGExtensions/NGExtensions/NGLogEvent.h
sope-core/NGExtensions/NGExtensions/NGLogEventFormatter.h [new file with mode: 0644]
sope-core/NGExtensions/NGExtensions/NGLogFileHandleAppender.h [new file with mode: 0644]
sope-core/NGExtensions/NGExtensions/NGLogger.h
sope-core/NGExtensions/NGExtensions/NGLoggerManager.h
sope-core/NGExtensions/NGExtensions/NGLogging.h
sope-core/NGExtensions/NGLogging.subproj/ChangeLog
sope-core/NGExtensions/NGLogging.subproj/GNUmakefile
sope-core/NGExtensions/NGLogging.subproj/NGLogAppender.m
sope-core/NGExtensions/NGLogging.subproj/NGLogConsoleAppender.m [deleted file]
sope-core/NGExtensions/NGLogging.subproj/NGLogEvent.m
sope-core/NGExtensions/NGLogging.subproj/NGLogEventDetailedFormatter.m [new file with mode: 0644]
sope-core/NGExtensions/NGLogging.subproj/NGLogEventFormatter.m [new file with mode: 0644]
sope-core/NGExtensions/NGLogging.subproj/NGLogFileHandleAppender.m [new file with mode: 0644]
sope-core/NGExtensions/NGLogging.subproj/NGLogStderrAppender.m [new file with mode: 0644]
sope-core/NGExtensions/NGLogging.subproj/NGLogStdoutAppender.m [moved from sope-core/NGExtensions/NGExtensions/NGLogConsoleAppender.h with 60% similarity]
sope-core/NGExtensions/NGLogging.subproj/NGLogSyslogAppender.m
sope-core/NGExtensions/NGLogging.subproj/NGLogger.m
sope-core/NGExtensions/NGLogging.subproj/NGLoggerManager.m
sope-core/NGExtensions/Version

index 2b5fad2f27fef17971db196e80e58215b9313427..97c6b243a6dca3a92e45e5507a050eab0ad22068 100644 (file)
@@ -1,3 +1,19 @@
+2004-11-19  Marcus Mueller  <znek@mulle-kybernetik.com>
+
+       * v4.5.95
+
+       * Defaults.plist: new defaults for NGLogging
+
+       * WOHttpAdaptor/WOHttpAdaptor.m: rewrote transaction logging to use
+         NGLogging. Configuration for transActionLogger is stored in
+         Defaults.plist.
+         NOTE: no profiling has been done, yet - thus the profiling
+         information needs to be updated (a TODO has been placed at the
+         appropriate place).
+
+       * DynamicElements/_WOTemporaryHyperlink.m: added correct cast to
+         circumvent gcc bug (false warning).
+
 2004-11-19  Helge Hess  <helge.hess@opengroupware.org>
 
        * v4.5.94
index 14892079172b7263e8ca3126163f40a0e9e7e32f..e1ca29a243ce965cfc1e7f6e737f6c8f3ca114b4 100644 (file)
@@ -1,8 +1,11 @@
 {
-  NGObjWeb_doc_   = "NSUserDefaults for NGObjWeb";
+  NGObjWeb_doc_                         = "NSUserDefaults for NGObjWeb";
 
+  NGLogDefaultAppenderClass             = "NGLogStdoutAppender";
+  NGLogDefaultLogLevel                  = "INFO";
+  NGLogDefaultLogEventFormatterClass    = "NGLogEventDetailedFormatter";
   WOAdaptor                             = "WOHttpAdaptor";
-  WOAdaptorLogPath                     = "";
+  WOAdaptorLogPath                      = "";
   WOAdditionalAdaptors                  = ( );
   WOApplicationBaseURL                  = "/WebObjects";
   WOApplicationSuffix                   = ".woa";
   WOCoreOnApplicationException          = NO;
   WOCoreOnAwakeComponentInCtxDealloc    = NO;
   WOCoreOnHTTPAdaptorException          = NO;
-  WOCoreOnRecursiveSubcomponents       = NO;
+  WOCoreOnRecursiveSubcomponents        = NO;
   WOCoreOnXmlRpcFault                   = NO;
   WODebugActions                        = NO;
-  WODebugComponentAwake                        = NO;
+  WODebugComponentAwake                 = NO;
   WODebugComponentDefinition            = NO;
-  WODebugComponentLookup               = NO;
+  WODebugComponentLookup                = NO;
   WODebugCursor                         = NO;
   WODebugHttpTransaction                = NO;
   WODebugKeyPathAssociation             = NO;
   WOHttpAdaptor_LogStream               = NO;
   WOHttpAllowHost                       = "localhost";
   WOHttpTransactionUseSimpleParser      = NO;
+  WOHttpTransactionLoggerConfig         = {
+    "LogLevel"  = "INFO";
+    "Appenders" = (
+        {
+            "Class"     = "NGLogStdoutAppender";
+            "Formatter" = {
+               "Class" = "NGLogEventFormatter";
+            };
+        },
+    );
+  };
   WOIncludeCommentsInResponse           = YES;
   WOIsRedirectionEnabled                = NO;
   WOKeyPathAssociationsCacheSize        = 200;
   WOSimpleHTTPParserMaxUploadSizeInKB   = 262144;
   WOStatsStylesheetName                 = "WOStats.xsl";
   WOUseRelativeURLs                     = YES;
-  WOUseGlobalCookiePath                        = YES;
+  WOUseGlobalCookiePath                 = YES;
   WOValueAssociationsCacheSize          = 200;
   WOWorkerThreadCount                   = 0;
   WOxFileExtensions                     = ( wox, xtmpl, xhtml );
   WOxElemBuilder_LogAssociationMapping  = NO;
   WOxElemBuilder_LogAssociationCreation = NO;
-  WOxComponentElemBuilderDebugEnabled  = NO;
+  WOxComponentElemBuilderDebugEnabled   = NO;
   WOxLogBuilderQueue                    = NO;
   WOxBuilderClasses = ( 
     WOxControlElemBuilder,
index deeb0153aa9805f9f0aebe6bb2cdde3e9146be9c..42c5537b7c0b4abb613caab0f67318b9d6df1f17 100644 (file)
@@ -63,7 +63,8 @@ static Class _WODirectActionHyperlinkClass       = Nil;
   WOHyperlinkInfo *info;
   Class linkClass = Nil;
   
-  if ((info = [[WOHyperlinkInfo alloc] initWithConfig:(id)_config]) == nil) {
+  if ((info = [(WOHyperlinkInfo *)[WOHyperlinkInfo alloc]
+                initWithConfig:(id)_config]) == nil) {
     return nil;
   }
   
index 9e6541d19b37f8052a7c21b8a676955d7eb3523d..ad4484883c69a70827daf9368e958480016f0aa7 100644 (file)
                        );
                        buildSettings = {
                                DYLIB_COMPATIBILITY_VERSION = 1;
-                               DYLIB_CURRENT_VERSION = 4.5.91;
+                               DYLIB_CURRENT_VERSION = 4.5.95;
                                FRAMEWORK_SEARCH_PATHS = "$(LOCAL_LIBRARY_DIR)/Frameworks";
                                FRAMEWORK_VERSION = A;
                                GCC_PRECOMPILE_PREFIX_HEADER = YES;
index 0e89de1bcbd698b50c286b589a487f91bdd7f78b..4de323b5917c3f11755cf5f3bf4eb4f0f1535162 100644 (file)
                        );
                        buildSettings = {
                                DYLIB_COMPATIBILITY_VERSION = 1;
-                               DYLIB_CURRENT_VERSION = 4.5.91;
+                               DYLIB_CURRENT_VERSION = 4.5.95;
                                FRAMEWORK_SEARCH_PATHS = "$(LOCAL_LIBRARY_DIR)/Frameworks";
                                FRAMEWORK_VERSION = A;
                                GCC_PRECOMPILE_PREFIX_HEADER = YES;
index 35cf81120300bfec4e6d6056e83b6275a0e9af26..be98e782e208d258a48367d1014112b6153a6f63 100644 (file)
                        );
                        buildSettings = {
                                DYLIB_COMPATIBILITY_VERSION = 1;
-                               DYLIB_CURRENT_VERSION = 4.5.91;
+                               DYLIB_CURRENT_VERSION = 4.5.95;
                                FRAMEWORK_SEARCH_PATHS = "$(LOCAL_LIBRARY_DIR)/Frameworks";
                                FRAMEWORK_VERSION = A;
                                GCC_PRECOMPILE_PREFIX_HEADER = NO;
index 625a956761eb727aad540b8cb67c2c123128bae4..cfdbb47650a046513e49ddbe6ab3830b59df15db 100644 (file)
@@ -1,6 +1,6 @@
 # version file
 
-SUBMINOR_VERSION:=94
+SUBMINOR_VERSION:=95
 
 # v4.5.91  requires libNGExtensions v4.5.134
 # v4.5.84  requires libNGExtensions v4.5.127
index d4c35dbac487726e634b81fdee0c30d849e2cc6d..2a2d62b6721de8a61285f5edc4985a3570755df5 100644 (file)
@@ -58,9 +58,10 @@ NSString *WOAsyncResponse = @"WOAsyncResponse";
 static NSMutableDictionary *pendingTransactions = nil; // THREAD
 static BOOL useSimpleParser = YES;
 static int  doCore  = -1;
-static NSString *adLogPath   = nil;
-static NGLogger *debugLogger = nil;
-static NGLogger *perfLogger  = nil;
+static NSString *adLogPath         = nil;
+static NGLogger *debugLogger       = nil;
+static NGLogger *perfLogger        = nil;
+static NGLogger *transActionLogger = nil;
 
 + (int)version {
   return 2;
@@ -73,9 +74,10 @@ static NGLogger *perfLogger  = nil;
   if (didInit) return;
   didInit = YES;
 
-  lm          = [NGLoggerManager defaultLoggerManager];
-  perfLogger  = [lm loggerForDefaultKey:@"WOProfileHttpAdaptor"];
-  debugLogger = [lm loggerForDefaultKey:@"WODebugHttpTransaction"];
+  lm                = [NGLoggerManager defaultLoggerManager];
+  perfLogger        = [lm loggerForDefaultKey:@"WOProfileHttpAdaptor"];
+  debugLogger       = [lm loggerForDefaultKey:@"WODebugHttpTransaction"];
+  transActionLogger = [lm loggerForClass:self];
 
   ud = [NSUserDefaults standardUserDefaults];
   useSimpleParser = [ud boolForKey:@"WOHttpTransactionUseSimpleParser"];
@@ -869,15 +871,18 @@ static __inline__ const unsigned char *monthAbbr(int m) {
   connection:(id<NGActiveSocket>)_connection
 {
   /* 
+    NOTE: *obsoleted profiling information*
+    TODO: update profiling info! (left the old one for comparison)
     Profiling: this method takes 0.95% of -run if the output is piped to
     /dev/null on OSX, morphing caldate to string is 0.79% of that.
   */
-  NSString       *remoteHost = @"-";
-  NSNumber       *zippedLen;
-  NSCalendarDate *now;
-  NSDate         *lstartDate;
-  NSDictionary   *startStats;
-  
+  NSString        *remoteHost;
+  NSNumber        *zippedLen;
+  NSCalendarDate  *now;
+  NSDate          *lstartDate;
+  NSDictionary    *startStats;
+  NSMutableString *buf;
+
   lstartDate = [_request startDate];
   startStats = [_request startStatistics];
   zippedLen  = [[_response userInfo] objectForKey:@"WOResponseZippedLength"];
@@ -902,27 +907,34 @@ static __inline__ const unsigned char *monthAbbr(int m) {
   
   // this is supposed to be in GMT ! TODO: explicitly set GMT
   now = [NSCalendarDate calendarDate];
-  
-  /* print standard info */
-  printf("%s - - [%02i/%s/%04i:%02i:%02i:%02i GMT] \"%s %s %s\" %i %i",
-         remoteHost ? [remoteHost cString] : "-",
-         [now dayOfMonth],
-         monthAbbr([now monthOfYear]),
-         [now yearOfCommonEra],
-         [now hourOfDay], [now minuteOfHour], [now secondOfMinute],
-         [[_request method] cString],
-         [[_request uri] cString],
-         [[_request httpVersion] cString],
-         [_response status],
-         [[_response content] length]);
-  
-  /* print duration */
+
+  buf = [[NSMutableString alloc] initWithCapacity:160]; /* 2 terminal lines */
+
+  /* append standard info */
+  [buf appendString:remoteHost];
+  [buf appendString:@" - - ["];
+  [buf appendFormat:@"%02i/%s/%04i:%02i:%02i:%02i",
+        [now dayOfMonth],
+        monthAbbr([now monthOfYear]),
+        [now yearOfCommonEra],
+        [now hourOfDay], [now minuteOfHour], [now secondOfMinute]];
+  [buf appendString:@" GMT] \""];
+  [buf appendString:[_request method]];
+  [buf appendString:@" "];
+  [buf appendString:[_request uri]];
+  [buf appendString:@" "];
+  [buf appendString:[_request httpVersion]];
+  [buf appendString:@"\" "];
+  [buf appendFormat:@"%i",  [_response status]];
+  [buf appendFormat:@" %i", [[_response content] length]];
+
+  /* append duration */
   if (lstartDate)
-    printf(" %.3f", [now timeIntervalSinceDate:lstartDate]);
+    [buf appendFormat:@" %.3f", [now timeIntervalSinceDate:lstartDate]];
   else
-    printf(" -");
+    [buf appendString:@" -"];
   
-  /* print zip level */
+  /* append zip level */
   if (zippedLen) {
     double p;
     double unzippedLen;
@@ -930,25 +942,24 @@ static __inline__ const unsigned char *monthAbbr(int m) {
     unzippedLen = 
       [[[_response userInfo] objectForKey:@"WOResponseUnzippedLength"] 
                   unsignedIntValue];
-    
-    printf(" %d", (unsigned int)unzippedLen);
+    [buf appendFormat:@" %d", (unsigned int)unzippedLen];
 
     if ([zippedLen unsignedIntValue] == unzippedLen) {
-      printf(" -");
+      [buf appendString:@" -"];
     }
     else {
       p = unzippedLen / 100.0; // one percent
       p = [zippedLen doubleValue] / p;
       p = 100.0 - p;
-      printf(" %-2d%%", (unsigned int)p);
+      [buf appendFormat:@" %-2d%%", (unsigned int)p];
     }
   }
   else {
     /* content was not zipped */
-    printf(" - -");
+    [buf appendString:@" - -"];
   }
   
-  /* print statistics */
+  /* append statistics */
   
   if (startStats) {
     static NSProcessInfo *pi = nil;
@@ -965,21 +976,20 @@ static __inline__ const unsigned char *monthAbbr(int m) {
       
       diff *= 4; /* in KB */
       if (diff == 0)
-       printf(" 0");
+        [buf appendString:@" 0"];
       else if (diff > 999)
-       printf(" %iM", diff / 1024);
+        [buf appendFormat:@" %iM", diff / 1024];
       else
-       printf(" %iK", diff);
+        [buf appendFormat:@" %iK", diff];
     }
     else
-      printf(" ?");
+      [buf appendString:@" ?"];
   }
   else
-    printf(" -");
-  
-  /* flush log */
-  puts("");
-  fflush(stdout);
+    [buf appendString:@" -"];
+
+  [transActionLogger logLevel:NGLogLevelInfo message:buf];
+  [buf release];
 }
 
 /* NGHttpMessageParserDelegate */
index ef1813808b5b034b05ba9930acfb65b7db13d3cd..8d0b2bd423bf7380fc75ee8fa56ca1b5d80a141a 100644 (file)
                        );
                        buildSettings = {
                                DYLIB_COMPATIBILITY_VERSION = 1;
-                               DYLIB_CURRENT_VERSION = 4.5.91;
+                               DYLIB_CURRENT_VERSION = 4.5.95;
                                FRAMEWORK_SEARCH_PATHS = "$(LOCAL_LIBRARY_DIR)/Frameworks";
                                FRAMEWORK_VERSION = A;
                                GCC_PRECOMPILE_PREFIX_HEADER = NO;
index 79692e2a874a3749b04d71f1820c9194b7721368..bc47f01fcb613bd3991c5c31537eb576a92124d5 100644 (file)
@@ -1,3 +1,8 @@
+2004-11-19  Marcus Mueller  <znek@mulle-kybernetik.com>
+
+       * NGLogging: updated - API considered stable now.
+         NOTE: "make distclean" is required this time. (v4.5.136)
+
 2004-11-19  Helge Hess  <helge.hess@opengroupware.org>
 
        * v4.5.135
index 18d41da528d2686021bf85ef2207a2d91e6a3090..19f1e3d85bdeaf0ff49e1593ed84c4df0e6a5445 100644 (file)
@@ -126,8 +126,9 @@ NGLogging_HEADER_FILES = \
        NGLogger.h                      \
        NGLoggerManager.h               \
        NGLogEvent.h                    \
+       NGLogEventFormatter.h           \
        NGLogAppender.h                 \
-       NGLogConsoleAppender.h          \
+       NGLogFileHandleAppender.h       \
        NGLogSyslogAppender.h           \
 
 
index 9f873304d5f0fd48413cf9e75c4b2a6a56abaad7..2686235172fcb8fb7844cb6399b5c7d3926c9306 100644 (file)
                                COMPILER_FLAGS = "-I..";
                        };
                };
+               AD8B5D95074CF58C001AF5D3 = {
+                       fileEncoding = 5;
+                       indentWidth = 2;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.objc;
+                       path = NGLogFileHandleAppender.m;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               AD8B5D97074CF58C001AF5D3 = {
+                       fileRef = AD8B5D95074CF58C001AF5D3;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               AD8B5D98074CF614001AF5D3 = {
+                       fileEncoding = 5;
+                       indentWidth = 2;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.objc;
+                       path = NGLogStdoutAppender.m;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               AD8B5D99074CF614001AF5D3 = {
+                       fileRef = AD8B5D98074CF614001AF5D3;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               AD8B5DDC074CF7C8001AF5D3 = {
+                       fileEncoding = 5;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.h;
+                       path = NGLogFileHandleAppender.h;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               AD8B5DDD074CF7C8001AF5D3 = {
+                       fileRef = AD8B5DDC074CF7C8001AF5D3;
+                       isa = PBXBuildFile;
+                       settings = {
+                               ATTRIBUTES = (
+                                       Public,
+                               );
+                       };
+               };
+               AD8B5F6C074D46D0001AF5D3 = {
+                       fileEncoding = 4;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.objc;
+                       path = NGLogEventFormatter.m;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               AD8B5F6D074D46D0001AF5D3 = {
+                       fileRef = AD8B5F6C074D46D0001AF5D3;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               AD8B5FBE074D4D18001AF5D3 = {
+                       fileEncoding = 4;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.h;
+                       path = NGLogEventFormatter.h;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               AD8B5FBF074D4D18001AF5D3 = {
+                       fileRef = AD8B5FBE074D4D18001AF5D3;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               AD8B5FFB074D57B2001AF5D3 = {
+                       fileEncoding = 4;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.objc;
+                       path = NGLogEventDetailedFormatter.m;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               AD8B5FFC074D57B2001AF5D3 = {
+                       fileRef = AD8B5FFB074D57B2001AF5D3;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               AD8B6017074D59B4001AF5D3 = {
+                       fileEncoding = 4;
+                       isa = PBXFileReference;
+                       lastKnownFileType = sourcecode.c.objc;
+                       path = NGLogStderrAppender.m;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               AD8B6018074D59B4001AF5D3 = {
+                       fileRef = AD8B6017074D59B4001AF5D3;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
                ADCD51360743BBBC0071C1A1 = {
                        children = (
                                AD595AB00745170400B2C064,
                        refType = 4;
                        sourceTree = "<group>";
                };
-               ADCD513B0743BBE10071C1A1 = {
-                       fileEncoding = 5;
-                       indentWidth = 2;
-                       isa = PBXFileReference;
-                       lastKnownFileType = sourcecode.c.h;
-                       path = NGLogConsoleAppender.h;
-                       refType = 4;
-                       sourceTree = "<group>";
-               };
-               ADCD513C0743BBE10071C1A1 = {
-                       fileEncoding = 5;
-                       indentWidth = 2;
-                       isa = PBXFileReference;
-                       lastKnownFileType = sourcecode.c.objc;
-                       path = NGLogConsoleAppender.m;
-                       refType = 4;
-                       sourceTree = "<group>";
-               };
                ADCD513D0743BBE10071C1A1 = {
                        fileEncoding = 5;
                        indentWidth = 2;
                        settings = {
                        };
                };
-               ADCD514A0743BBE10071C1A1 = {
-                       fileRef = ADCD513B0743BBE10071C1A1;
-                       isa = PBXBuildFile;
-                       settings = {
-                               ATTRIBUTES = (
-                                       Public,
-                               );
-                       };
-               };
-               ADCD514B0743BBE10071C1A1 = {
-                       fileRef = ADCD513C0743BBE10071C1A1;
-                       isa = PBXBuildFile;
-                       settings = {
-                       };
-               };
                ADCD514C0743BBE10071C1A1 = {
                        fileRef = ADCD513D0743BBE10071C1A1;
                        isa = PBXBuildFile;
                                ADCD513F0743BBE10071C1A1,
                                ADCD52020743D8CA0071C1A1,
                                ADCD513D0743BBE10071C1A1,
+                               AD8B5FBE074D4D18001AF5D3,
                                ADCD51390743BBE10071C1A1,
-                               ADCD513B0743BBE10071C1A1,
+                               AD8B5DDC074CF7C8001AF5D3,
                                ADCD51420743BBE10071C1A1,
                        );
                        fileEncoding = 5;
                                ADCD51400743BBE10071C1A1,
                                ADCD52030743D8CA0071C1A1,
                                ADCD513E0743BBE10071C1A1,
+                               AD8B5F6C074D46D0001AF5D3,
+                               AD8B5FFB074D57B2001AF5D3,
                                ADCD513A0743BBE10071C1A1,
-                               ADCD513C0743BBE10071C1A1,
                                ADCD51430743BBE10071C1A1,
+                               AD8B5D95074CF58C001AF5D3,
+                               AD8B5D98074CF614001AF5D3,
+                               AD8B6017074D59B4001AF5D3,
                        );
+                       fileEncoding = 5;
+                       indentWidth = 2;
                        isa = PBXGroup;
                        name = Classes;
                        refType = 4;
                                ADD45B6006FEF017004BBD65,
                                AD4BF6D60703147A006FB665,
                                ADCD51480743BBE10071C1A1,
-                               ADCD514A0743BBE10071C1A1,
                                ADCD514C0743BBE10071C1A1,
                                ADCD514E0743BBE10071C1A1,
                                ADCD51500743BBE10071C1A1,
                                ADCD51510743BBE10071C1A1,
                                ADCD51530743BBE10071C1A1,
                                ADCD52040743D8CA0071C1A1,
+                               AD8B5DDD074CF7C8001AF5D3,
+                               AD8B5FBF074D4D18001AF5D3,
                        );
                        isa = PBXHeadersBuildPhase;
                        runOnlyForDeploymentPostprocessing = 0;
                                AD4BF6EC070314EE006FB665,
                                AD665E3A071F00AF00EC5911,
                                ADCD51490743BBE10071C1A1,
-                               ADCD514B0743BBE10071C1A1,
                                ADCD514D0743BBE10071C1A1,
                                ADCD514F0743BBE10071C1A1,
                                ADCD51520743BBE10071C1A1,
                                ADCD52050743D8CA0071C1A1,
+                               AD8B5D97074CF58C001AF5D3,
+                               AD8B5D99074CF614001AF5D3,
+                               AD8B5F6D074D46D0001AF5D3,
+                               AD8B5FFC074D57B2001AF5D3,
+                               AD8B6018074D59B4001AF5D3,
                        );
                        isa = PBXSourcesBuildPhase;
                        runOnlyForDeploymentPostprocessing = 0;
                        );
                        buildSettings = {
                                DYLIB_COMPATIBILITY_VERSION = 1;
-                               DYLIB_CURRENT_VERSION = 4.5.134;
+                               DYLIB_CURRENT_VERSION = 4.5.136;
                                FRAMEWORK_SEARCH_PATHS = "$(LOCAL_LIBRARY_DIR)/Frameworks";
                                FRAMEWORK_VERSION = A;
                                GCC_PRECOMPILE_PREFIX_HEADER = YES;
                                ADD65D8E06DA3830007161CA,
                                ADD65D8F06DA3830007161CA,
                        );
+                       fileEncoding = 5;
+                       indentWidth = 2;
                        isa = PBXGroup;
                        name = Headers;
                        path = NGExtensions;
index 6117a3fcbec4f96d02ea2c290b674fd5257346d7..f8b805fe34b50ab341fced3368ad89b177c8585f 100644 (file)
   NGLogAppender
 
   Abstract superclass for all log appenders.
+
+  NGLogAppender honours the following user default keys:
+  User Default key              Function
+  ----------------------------------------------------------------------------
+  NGLogDefaultAppenderClass     The appender class to use if no class
+                                information was provided by the configuration.
+                                The fallback is "NGLogStdoutAppender".
+  The following keys in the configuration dictionary will be recognized:
+  Key                           Function
+  ----------------------------------------------------------------------------
+  "Class"                       The class to use for instance creation. If no
+                                class name is provided, the fallback path
+                                described above will be taken.
+
+  "Formatter"                   Dictionary suitable as configuration
+                                provided to NGLogEventFormatters's factory
+                                method. Please see NGLogEventFormatteer.h for
+                                further explanation.
 */
 
 #import <Foundation/NSObject.h>
 #include <NGExtensions/NGLogLevel.h>
 
-@class NGLogEvent;
+@class NSDictionary, NGLogEvent, NGLogEventFormatter;
 
 @interface NGLogAppender : NSObject
 {
+  NGLogEventFormatter *formatter;
 }
 
+/* factory method */
++ (id)logAppenderFromConfig:(NSDictionary *)_config;
+
+/* designated initializer */
+- (id)initWithConfig:(NSDictionary *)_config;
+
 /* subclass responsibility */
 - (void)appendLogEvent:(NGLogEvent *)_event;
 - (NSString *)formattedEvent:(NGLogEvent *)_event;
 
-- (NSString *)localizedNameOfLogLevel:(NGLogLevel)_level;
-
 @end
 
 #endif /* __NGExtensions_NGLogAppender_H_ */
index 4277eff0df8c18fa3b3d658300a6f01ed2264fc5..f46d5ec7bf1a478ba686bc72da894f1126ebee6f 100644 (file)
@@ -34,7 +34,7 @@
 #import <Foundation/NSDate.h>
 #include <NGExtensions/NGLogLevel.h>
 
-@class NSString;
+@class NSString, NSCalendarDate;
 
 @interface NGLogEvent : NSObject
 {
@@ -49,7 +49,7 @@
 
 - (NGLogLevel)level;
 - (NSString *)message;
-- (NSDate *)date;
+- (NSCalendarDate *)date;
 
 @end
 
diff --git a/sope-core/NGExtensions/NGExtensions/NGLogEventFormatter.h b/sope-core/NGExtensions/NGExtensions/NGLogEventFormatter.h
new file mode 100644 (file)
index 0000000..c8fab92
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ Copyright (C) 2004 SKYRIX Software AG
+ This file is part of OpenGroupware.org.
+ OGo is free software; you can redistribute it and/or modify it under
+ the terms of the GNU Lesser General Public License as published by the
+ Free Software Foundation; either version 2, or (at your option) any
+ later version.
+ OGo 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 Lesser General Public
+ License for more details.
+ You should have received a copy of the GNU Lesser General Public
+ License along with OGo; see the file COPYING.  If not, write to the
+ Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA.
+ */
+
+#ifndef        __NGExtensions_NGLogEventFormatter_H_
+#define        __NGExtensions_NGLogEventFormatter_H_
+
+/*
+  NGLogEventFormatter
+  Suits as factory and base class for all custom log event formatters.
+  Its purpose is to offer a lightweight interface to transform NGLogEvent
+  objects into string representations.
+
+  NGLogEventFormatter honours the following user default keys:
+  User Default key                       Function
+  ----------------------------------------------------------------------------
+  NGLogDefaultLogEventFormatterClass     The formatter class to use if no class
+                                         information was provided by the
+                                         configuration.
+                                         The fallback is "NGLogEventFormatter".
+  The following keys in the configuration dictionary will be recognized:
+  Key                           Function
+  ----------------------------------------------------------------------------
+  "Class"                       The class to use for instance creation. If no
+                                class name is provided, the fallback path
+                                described above will be taken.
+*/
+
+#import <Foundation/NSObject.h>
+#include <NGExtensions/NGLogLevel.h>
+
+@class NSDictionary, NGLogEvent;
+
+@interface NGLogEventFormatter : NSObject
+{
+}
+
++ (id)logEventFormatterFromConfig:(NSDictionary *)_config;
+
+- (id)initWithConfig:(NSDictionary *)_config;
+
+/* formatting */
+- (NSString *)formattedEvent:(NGLogEvent *)_event;
+
+@end
+
+#endif /* __NGExtensions_NGLogEventFormatter_H_ */
diff --git a/sope-core/NGExtensions/NGExtensions/NGLogFileHandleAppender.h b/sope-core/NGExtensions/NGExtensions/NGLogFileHandleAppender.h
new file mode 100644 (file)
index 0000000..0505ead
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+  Copyright (C) 2004 SKYRIX Software AG
+
+  This file is part of OpenGroupware.org.
+
+  OGo is free software; you can redistribute it and/or modify it under
+  the terms of the GNU Lesser General Public License as published by the
+  Free Software Foundation; either version 2, or (at your option) any
+  later version.
+
+  OGo 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 Lesser General Public
+  License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with OGo; see the file COPYING.  If not, write to the
+  Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+  02111-1307, USA.
+*/
+
+#ifndef        __NGExtensions_NGLogFileHandleAppender_H_
+#define        __NGExtensions_NGLogFileHandleAppender_H_
+
+/*
+ NGLogFileHandleAppender
+ Suits as an abstract base class for all NSFileHandle based appenders.
+ */
+
+#include <NGExtensions/NGLogAppender.h>
+#import <Foundation/NSString.h> /* for NSStringEncoding */
+
+@class NSFileHandle, NSDictionary;
+
+@interface NGLogFileHandleAppender : NGLogAppender
+{
+  NSFileHandle     *fh;
+  NSStringEncoding encoding;
+  BOOL             flushImmediately;
+}
+
+- (BOOL)isFileHandleOpen;
+- (void)openFileHandleWithConfig:(NSDictionary *)_config;
+- (void)closeFileHandle;
+  
+@end
+
+#endif /* __NGExtensions_NGLogFileHandleAppender_H_ */
index 9ddb2de6acbf3cfb55076ee1b849905dfad5498e..cf18eec095df12622c325ce514fdd7fe46d76b95 100644 (file)
   only if this minimum log level is satisfied - otherwise it silently drops
   these messages.
 
-  Note: Except in rare circumstances, do not allocate loggers yourself. Always
-        try to use the appropriate API of NGLoggerManager if possible.
+  NGLogger also offers a factory to instantiate loggers from configs stored
+  in NSUserDefaults.
+
+  NOTE: Except in rare circumstances, do not allocate loggers yourself!
+        Always try to use the appropriate API of NGLoggerManager if possible.
+
+
+  NGLogger honours the following user default keys:
+
+  User Default key              Function
+  ----------------------------------------------------------------------------
+  NGLogDefaultLogLevel          The log level to use as a fallback, if no
+                                log level is provided during initialization.
+                                The default is "INFO".
+
+  The following keys in the configuration dictionary will be recognized:
+  Key                           Function
+  ----------------------------------------------------------------------------
+  "LogLevel"                    The log level to use for this logger. If no
+                                log level is provided, sets log level according
+                                to fallback described above.
+
+  "Appenders"                   Array of dictionaries suitable as configuration
+                                provided to NGLogAppender's factory method.
+                                Please see NGLogAppender.h for further
+                                explanation.
+
+  LoggerConfig example:
+  WOHttpTransactionLoggerConfig = {
+    "LogLevel"  = "INFO";
+    "Appenders" = (
+      {
+        "Class"     = "NGLogStdoutAppender";
+        "Formatter" = {
+          "Class" = "NGLogEventFormatter";
+        };
+      },
+    );
+  };
  
-  Note: Currently the NGLogger implementation lacks an API for configuring
-        appenders. Until this has been done appropriately, use the
-        "NGLogDefaultAppenderClass" user default to select an appropriate
-        default appender. If this default isn't set, "NGLogConsoleAppender"
-        is used.
 */
 
 #import <Foundation/NSObject.h>
 #include <NGExtensions/NGLogLevel.h>
 
+@class NSMutableArray, NSString, NSDictionary, NGLogAppender;
+
 @interface NGLogger : NSObject
 {
-  NGLogLevel logLevel;
-  id         _appender; // going away as soon as we have a config
+  NSMutableArray *appenders;
+  @public
+  NGLogLevel     logLevel;
 }
 
-+ (id)defaultLogger;
++ (id)loggerWithConfigFromUserDefaults:(NSString *)_defaultName;
+
+- (id)initWithConfig:(NSDictionary *)_config;
 - (id)initWithLogLevel:(NGLogLevel)_level;
 
 /* accessors */
 - (void)setLogLevel:(NGLogLevel)_level;
 - (NGLogLevel)logLevel;
 
+- (void)addAppender:(NGLogAppender *)_appender;
+- (void)removeAppender:(NGLogAppender *)_appender;
 
-  
 /* logging */
 
+- (void)logLevel:(NGLogLevel)_level message:(NSString *)_msg;
 
 /* conditions */
 
index 34e65f883c113e13ca8972fdad39aab90b42ec30..b78b6de201fc31b7a422c5d96435a6f389a18206 100644 (file)
   same name/key. Also, NGLoggerManager offers conditional creation of loggers
   based on user default keys (and special values associated with these keys).
 
-  It's planned that NGLoggerManager will be provided with a configuration of
-  some sort at a later stage, so configuration of log levels and appenders for
-  loggers can reach a similar dynamism as is currently achieved in Log4J.
+  NGLoggerManager honours the following user default keys:
+
+  User Default key              Function
+  ----------------------------------------------------------------------------
+  <Name>LoggerConfig            contains the configuration of the logger
+                                named <Name>. Depending on what method you used
+                                to retrieve the logger, <Name> is either
+                                the user default key, class name or another
+                                arbitrary name. The config found for that key
+                                is used to initialize the logger instance.
+
+  NGLogDebugAllEnabled          if set to "YES" will always return a logger
+                                when -loggerForDefaultKey: is called.
+
 */
 
 #import <Foundation/NSObject.h>
index 0cd278b3b3e11bd03ed05aa26efcd5615c8e4b64..fd47ce77b7c2c4dade8cbaa58cc6a1fa91a64a95 100644 (file)
@@ -33,8 +33,9 @@
 #include <NGExtensions/NGLogger.h>
 #include <NGExtensions/NGLoggerManager.h>
 #include <NGExtensions/NGLogEvent.h>
+#include <NGExtensions/NGLogEventFormatter.h>
 #include <NGExtensions/NGLogAppender.h>
-#include <NGExtensions/NGLogConsoleAppender.h>
+#include <NGExtensions/NGLogFileHandleAppender.h>
 #include <NGExtensions/NGLogSyslogAppender.h>
 
 #endif /* __NGExtensions_NGLogging_H_ */
index 5a13bd6552466b3d25d488c2401a86159993a042..de3b0e801d89b94b71d77e6064fc7e396b2386eb 100644 (file)
@@ -1,3 +1,33 @@
+2004-11-19  Marcus Mueller  <znek@mulle-kybernetik.com>
+
+       * *.h: added detailed documentation
+
+       * *.m: added -description where appropriate
+
+       * NGLogger.m: removed +defaultLogger from the API, it's used
+         internally though.
+
+       * NGLoggerManager.m: reinstated caching of loggers. Added optimization
+         to reuse a "default" logger when no config is available.
+
+       * NGLogEvent.[hm]: changed -date to return NSCalendarDate instead of
+         NSDate.
+
+       * NGLogEventFormatter.[hm]: new base class for implementing formatters.
+         Also offers a factory for creating log event formatter instances
+         from configurations.
+
+       * NGLogEventDetailedFormatter.m: offers rich logging, similar to what
+         NSLog() in libFoundation has to offer.
+
+       * NGLogConsoleAppender.m: removed, obsoleted by NGLogStdoutAppender.
+
+       * NGLogFileHandleAppender.[hm]: new base class for implementing file
+         handle based appenders.
+
+       * NGLogStdoutAppender.m, NGLogStderrAppender.m: appenders for logging
+         to stdout/stderr.
+
 2004-11-19  Helge Hess  <helge.hess@opengroupware.org>
 
        * NGLoggerManager.m: use default logger if none is registered
index d90f37a2cbe85fbc99952f8b0b41e852952525bb..817dfece4ae38c9dcfcc5b622e27650cd5877bee 100644 (file)
@@ -9,8 +9,12 @@ NGLogging_OBJC_FILES += \
        NGLogger.m                      \
        NGLoggerManager.m               \
        NGLogEvent.m                    \
+       NGLogEventFormatter.m           \
+       NGLogEventDetailedFormatter.m   \
        NGLogAppender.m                 \
-       NGLogConsoleAppender.m          \
+       NGLogFileHandleAppender.m       \
+       NGLogStdoutAppender.m           \
+       NGLogStderrAppender.m           \
 
 # TODO: disable on Windows
 NGLogging_OBJC_FILES += \
index 324315ea1d44c36ec517a9b74a84a1b1e06776d8..d1dd831980c8188b279c205eb27a8870dff192dd 100644 (file)
 #include "NGLogAppender.h"
 #include "NGLogLevel.h"
 #include "NGLogEvent.h"
+#include "NGLogEventFormatter.h"
 #include "common.h"
 
 @implementation NGLogAppender
 
+static NSString *defaultAppenderClassName = nil;
+
++ (void)initialize {
+  static BOOL    didInit = NO;
+  NSUserDefaults *ud;
+
+  if (didInit) return;
+  
+  didInit = YES;
+  ud      = [NSUserDefaults standardUserDefaults];
+  defaultAppenderClassName =
+    [[ud stringForKey:@"NGLogDefaultAppenderClass"] retain];
+  if (defaultAppenderClassName == nil)
+    defaultAppenderClassName = @"NGLogStdoutAppender";
+}
+
++ (id)logAppenderFromConfig:(NSDictionary *)_config {
+  NSString *className;
+  Class    clazz;
+  id       appender;
+
+  className   = [_config objectForKey:@"Class"];
+  if (!className)
+    className = defaultAppenderClassName;
+  clazz = NSClassFromString(className);
+  if (clazz == Nil) {
+    NSLog(@"ERROR: can't instantiate appender class named '%@'",
+          className);
+    return nil;
+  }
+  appender = [[[clazz alloc] initWithConfig:_config] autorelease];
+  return appender;
+}
+
+- (id)initWithConfig:(NSDictionary *)_config {
+  self = [super init];
+  if (self) {
+    NSDictionary *formatterConfig;
+    
+    formatterConfig = [_config objectForKey:@"Formatter"];
+    self->formatter =
+      [[NGLogEventFormatter logEventFormatterFromConfig:formatterConfig]
+                            retain];
+  }
+  return self;
+}
+
 - (void)appendLogEvent:(NGLogEvent *)_event {
 #if LIB_FOUNDATION_LIBRARY
   [self subclassResponsibility:_cmd];
 #endif
 }
 
-- (NSString *)formattedEvent:(NGLogEvent *)_event {
-  NSMutableString *fe;
-  NSString        *lvl;
-  
-  lvl = [self localizedNameOfLogLevel:[_event level]];
-  fe = [NSMutableString stringWithCapacity:128];
-  if (lvl != nil) {
-    [fe appendString:@"["];
-    [fe appendString:lvl];
-    [fe appendString:@"] "];
-  }
-  [fe appendString:[_event message]];
-  return fe;
-}
+/* formatting */
 
-- (NSString *)localizedNameOfLogLevel:(NGLogLevel)_level {
-  NSString *name;
-  
-  switch (_level) {
-    case NGLogLevelWarn:
-      name = @"WARN";
-      break;
-    case NGLogLevelError:
-      name = @"ERROR";
-      break;
-    case NGLogLevelFatal:
-      name = @"FATAL";
-      break;
-    default:
-      name = nil;
-      break;
-  }
-  return name;
+- (NSString *)formattedEvent:(NGLogEvent *)_event {
+  return [self->formatter formattedEvent:_event];
 }
 
 @end /* NGLogAppender */
diff --git a/sope-core/NGExtensions/NGLogging.subproj/NGLogConsoleAppender.m b/sope-core/NGExtensions/NGLogging.subproj/NGLogConsoleAppender.m
deleted file mode 100644 (file)
index 645dea4..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
-  Copyright (C) 2004 SKYRIX Software AG
-  This file is part of OpenGroupware.org.
-  
-  OGo is free software; you can redistribute it and/or modify it under
-  the terms of the GNU Lesser General Public License as published by the
-  Free Software Foundation; either version 2, or (at your option) any
-  later version.
-  
-  OGo 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 Lesser General Public
-  License for more details.
-  
-  You should have received a copy of the GNU Lesser General Public
-  License along with OGo; see the file COPYING.  If not, write to the
-  Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-  02111-1307, USA.
-*/
-
-#include "NGLogConsoleAppender.h"
-#include "NGLogEvent.h"
-#include "common.h"
-#include <sys/types.h>
-#include <unistd.h>
-
-@implementation NGLogConsoleAppender
-
-static Class NSCalendarDateClass = Nil;
-static Class NSProcessInfoClass  = Nil;
-static unsigned char *processName = NULL;
-
-static char *monthNames[14] = {
-  "Dec", 
-  "Jan", "Feb", "Mar", "Apr", "May", "Jun",
-  "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
-  "Jan"
-};
-
-+ (void)initialize {
-  if (NSCalendarDateClass == Nil)
-    NSCalendarDateClass = [NSCalendarDate class];
-  if (NSProcessInfoClass == Nil)
-    NSProcessInfoClass = [NSProcessInfo class];
-
-  if (processName == NULL) {
-    /* process name can't change, right? */
-    unsigned len;
-    NSString *pn;
-    
-    pn  = [[NSProcessInfoClass processInfo] processName];
-    len = [pn cStringLength];
-    
-    processName = malloc(len + 4);
-    [pn getCString:processName];
-  }
-}
-
-static __inline__ unsigned char * levelPrefixForEvent(NGLogEvent *_event) {
-  switch ([_event level]) {
-  case NGLogLevelWarn:  return "[WARN]";
-  case NGLogLevelError: return "[ERROR]";
-  case NGLogLevelFatal: return "[FATAL]";
-  default:              return "";
-  }
-}
-
-- (void)appendLogEvent:(NGLogEvent *)_event {
-  /* Note: pid can change after a fork() */
-  NSCalendarDate *date;
-  
-  // TODO: get time using libc function, cheaper
-  // TODO: set to GMT?
-  date = [[NSCalendarDateClass alloc] init];
-  
-  // TODO: cString for message is expensive
-  fprintf(stderr,
-         "%s %02i %02i:%02i:%02i %s [%d]: %s\n",
-         monthNames[[date monthOfYear]],
-         [date dayOfMonth],
-         [date hourOfDay], [date minuteOfHour], [date secondOfMinute],
-         processName,
-         getpid(),
-         [[_event message] cString]);
-  
-  [date release];
-}
-
-@end /* NGLogConsoleAppender */
index 3de406bdac4e943b97cb9828b413c51757d734fa..b1d366ff57661cc06ed9fdae621c5a2da1109f2e 100644 (file)
 
 @implementation NGLogEvent
 
-static Class NSDateClass = Nil;
+static Class DateClass = Nil;
 
 + (void)initialize {
-  NSDateClass = [NSDate class];
+  static BOOL didInit = NO;
+
+  if (didInit) return;
+  didInit = YES;
+
+  DateClass = [NSCalendarDate class];
 }
 
 - (id)initWithLevel:(NGLogLevel)_level message:(NSString *)_msg {
   self = [super init];
-  if(self) {
-    self->date    = [NSDateClass timeIntervalSinceReferenceDate];
-    self->level   = _level;
-    self->msg     = [_msg copy];
+  if (self) {
+    // TODO: get time using libc function, cheaper
+    self->date  = [DateClass timeIntervalSinceReferenceDate];
+    self->level = _level;
+    self->msg   = [_msg copy];
   }
   return self;
 }
 
 - (void)dealloc {
-  [self->msg     release];
+  [self->msg release];
   [super dealloc];
 }
 
@@ -55,8 +61,28 @@ static Class NSDateClass = Nil;
   return self->msg;
 }
 
-- (NSDate *)date {
-  return [NSDateClass dateWithTimeIntervalSinceReferenceDate:self->date];
+- (NSCalendarDate *)date {
+  // TODO: set to GMT?
+  return [DateClass dateWithTimeIntervalSinceReferenceDate:self->date];
+}
+
+/* description */
+
+- (NSString *)description {
+  NSString *lvl;
+  
+  switch (self->level) {
+    case NGLogLevelOff:   lvl = @"OFF";   break;
+    case NGLogLevelDebug: lvl = @"DEBUG"; break;
+    case NGLogLevelInfo:  lvl = @"INFO";  break;
+    case NGLogLevelWarn:  lvl = @"WARN";  break;
+    case NGLogLevelError: lvl = @"ERROR"; break;
+    case NGLogLevelFatal: lvl = @"FATAL"; break;
+    default:              lvl = @"ALL";   break;
+  }
+  return [NSString stringWithFormat:@"<%@[0x%08X] date=%@ level=%@ msg:%@>",
+                      NSStringFromClass([self class]), self,
+                      [self date], lvl, self->msg];
 }
 
 @end /* NGLogEvent */
diff --git a/sope-core/NGExtensions/NGLogging.subproj/NGLogEventDetailedFormatter.m b/sope-core/NGExtensions/NGLogging.subproj/NGLogEventDetailedFormatter.m
new file mode 100644 (file)
index 0000000..e5531a8
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+  Copyright (C) 2000-2004 SKYRIX Software AG
+
+  This file is part of OGo
+
+  OGo is free software; you can redistribute it and/or modify it under
+  the terms of the GNU Lesser General Public License as published by the
+  Free Software Foundation; either version 2, or (at your option) any
+  later version.
+
+  OGo 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 Lesser General Public
+  License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with OGo; see the file COPYING.  If not, write to the
+  Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+  02111-1307, USA.
+*/
+// $Id$
+
+
+#include "NGLogEventFormatter.h"
+#include "NGLogLevel.h"
+
+@class NSString;
+
+@interface NGLogEventDetailedFormatter : NGLogEventFormatter
+{
+}
+
+@end
+
+#include "NGLogEvent.h"
+#include "common.h"
+#include "NSProcessInfo+misc.h"
+
+@implementation NGLogEventDetailedFormatter
+
+static unsigned char *processName = NULL;
+static NSProcessInfo *processInfo = nil;
+
+static char *monthNames[14] = {
+  "Dec", 
+  "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+  "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
+  "Jan"
+};
+
++ (void)initialize {
+  static BOOL didInit = NO;
+  unsigned    len;
+  NSString    *pn;
+
+  if (didInit) return;
+
+  didInit     = YES;
+  processInfo = [[NSProcessInfo processInfo] retain];
+  pn          = [processInfo processName];
+  len         = [pn cStringLength];
+  processName = malloc(len + 4);
+  [pn getCString:processName];
+}
+
+static __inline__ unsigned char * levelPrefixForEvent(NGLogEvent *_event) {
+  switch ([_event level]) {
+    case NGLogLevelWarn:  return "[WARN] ";
+    case NGLogLevelError: return "[ERROR] ";
+    case NGLogLevelFatal: return "[FATAL] ";
+    default:              return "";
+  }
+}
+
+- (NSString *)formattedEvent:(NGLogEvent *)_event {
+  NSMutableString *fe;
+  NSCalendarDate  *date;
+
+  fe = [NSMutableString stringWithCapacity:160];
+  /* timestamp, process name, process id, level prefix */
+  date = [_event date];
+  [fe appendFormat:@"%s %02i %02i:%02i:%02i %s [%d]: %s",
+    monthNames[[date monthOfYear]],
+    [date dayOfMonth],
+    [date hourOfDay], [date minuteOfHour], [date secondOfMinute],
+    processName,
+    /* Note: pid can change after a fork() */
+#if NeXT_Foundation_LIBRARY || COCOA_Foundation_LIBRARY
+    [processInfo processIdentifier],
+#else
+    [[processInfo processId] intValue],
+#endif
+    levelPrefixForEvent(_event)];
+    
+  /* message */
+  [fe appendString:[_event message]];
+  return fe;
+}
+
+@end /* NGLogEventDetailedFormatter */
diff --git a/sope-core/NGExtensions/NGLogging.subproj/NGLogEventFormatter.m b/sope-core/NGExtensions/NGLogging.subproj/NGLogEventFormatter.m
new file mode 100644 (file)
index 0000000..bf071b9
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+  Copyright (C) 2000-2004 SKYRIX Software AG
+
+  This file is part of OGo
+
+  OGo is free software; you can redistribute it and/or modify it under
+  the terms of the GNU Lesser General Public License as published by the
+  Free Software Foundation; either version 2, or (at your option) any
+  later version.
+
+  OGo 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 Lesser General Public
+  License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with OGo; see the file COPYING.  If not, write to the
+  Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+  02111-1307, USA.
+*/
+
+#include "NGLogEventFormatter.h"
+#include "NGLogEvent.h"
+#include "common.h"
+
+@implementation NGLogEventFormatter
+
+static NSString *defaultFormatterClassName = nil;
+
++ (void)initialize {
+  static BOOL    didInit = NO;
+  NSUserDefaults *ud;
+  
+  if (didInit) return;
+  
+  didInit = YES;
+  ud      = [NSUserDefaults standardUserDefaults];
+  defaultFormatterClassName =
+    [[ud stringForKey:@"NGLogDefaultLogEventFormatterClass"] retain];
+  if (defaultFormatterClassName == nil)
+    defaultFormatterClassName = @"NGLogEventFormatter";
+}
+
++ (id)logEventFormatterFromConfig:(NSDictionary *)_config {
+  NSString *className;
+  Class    clazz;
+  id       formatter;
+  
+  className   = [_config objectForKey:@"Class"];
+  if (!className)
+    className = defaultFormatterClassName;
+  clazz = NSClassFromString(className);
+  if (clazz == Nil) {
+    NSLog(@"ERROR: can't instantiate log event formatter class named '%@'",
+          className);
+    return nil;
+  }
+  formatter = [[[clazz alloc] initWithConfig:_config] autorelease];
+  return formatter;
+}
+
+- (id)initWithConfig:(NSDictionary *)_config {
+  self = [super init];
+  if (self) {
+  }
+  return self;
+}
+
+/* formatting */
+
+- (NSString *)formattedEvent:(NGLogEvent *)_event {
+  return [_event message];
+}
+
+@end /* NGLogEventFormatter */
diff --git a/sope-core/NGExtensions/NGLogging.subproj/NGLogFileHandleAppender.m b/sope-core/NGExtensions/NGLogging.subproj/NGLogFileHandleAppender.m
new file mode 100644 (file)
index 0000000..62dee3c
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+  Copyright (C) 2004 SKYRIX Software AG
+
+  This file is part of OpenGroupware.org.
+
+  OGo is free software; you can redistribute it and/or modify it under
+  the terms of the GNU Lesser General Public License as published by the
+  Free Software Foundation; either version 2, or (at your option) any
+  later version.
+
+  OGo 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 Lesser General Public
+  License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with OGo; see the file COPYING.  If not, write to the
+  Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+  02111-1307, USA.
+*/
+
+#include "NGLogFileHandleAppender.h"
+#include "NGLogEvent.h"
+#include "common.h"
+
+@implementation NGLogFileHandleAppender
+
+static NSData *nextLineData = nil;
+
++ (void)initialize {
+  static BOOL didInit = NO;
+  
+  if (didInit) return;
+
+  didInit = YES;
+  nextLineData = [[@"\n" dataUsingEncoding:NSASCIIStringEncoding] retain];
+}
+
+- (id)initWithConfig:(NSDictionary *)_config {
+  self = [super initWithConfig:_config];
+  if (self) {
+    self->flushImmediately = NO;
+    self->encoding         = [NSString defaultCStringEncoding];
+    [self openFileHandleWithConfig:_config];
+  }
+  return self;
+}
+
+- (void)dealloc {
+  if ([self isFileHandleOpen])
+    [self closeFileHandle];
+  [self->fh release];
+  [super dealloc];
+}
+
+- (BOOL)isFileHandleOpen {
+  return self->fh ? YES : NO;
+}
+
+- (void)openFileHandleWithConfig:(NSDictionary *)_config {
+}
+
+- (void)closeFileHandle {
+  [self->fh closeFile];
+}
+
+- (void)appendLogEvent:(NGLogEvent *)_event {
+  NSString *formatted;
+  NSData   *bin;
+
+  formatted = [self formattedEvent:_event];
+  bin       = [formatted dataUsingEncoding:self->encoding];
+  [self->fh writeData:bin];
+  [self->fh writeData:nextLineData];
+  if (self->flushImmediately)
+    [self->fh synchronizeFile];
+}
+
+@end /* NGLogFileHandleAppender */
diff --git a/sope-core/NGExtensions/NGLogging.subproj/NGLogStderrAppender.m b/sope-core/NGExtensions/NGLogging.subproj/NGLogStderrAppender.m
new file mode 100644 (file)
index 0000000..f074228
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ Copyright (C) 2004 SKYRIX Software AG
+ This file is part of OpenGroupware.org.
+ OGo is free software; you can redistribute it and/or modify it under
+ the terms of the GNU Lesser General Public License as published by the
+ Free Software Foundation; either version 2, or (at your option) any
+ later version.
+ OGo 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 Lesser General Public
+ License for more details.
+ You should have received a copy of the GNU Lesser General Public
+ License along with OGo; see the file COPYING.  If not, write to the
+ Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA.
+ */
+
+#include "NGLogFileHandleAppender.h"
+
+@interface NGLogStderrAppender : NGLogFileHandleAppender
+{
+}
+
+@end
+
+#include "common.h"
+
+@implementation NGLogStderrAppender
+
+- (void)openFileHandleWithConfig:(NSDictionary *)_config {
+  self->fh = [[NSFileHandle fileHandleWithStandardError] retain];
+}
+
+@end /* NGLogStderrAppender */
similarity index 60%
rename from sope-core/NGExtensions/NGExtensions/NGLogConsoleAppender.h
rename to sope-core/NGExtensions/NGLogging.subproj/NGLogStdoutAppender.m
index 2fca9c9cc1d6b3ac1db3f7c084e4054dca56e5dc..906e713fc51bd68ed6abaa6cbbdf4e07802e7176 100644 (file)
   02111-1307, USA.
 */
 
-#ifndef        __NGExtensions_NGLogConsoleAppender_H_
-#define        __NGExtensions_NGLogConsoleAppender_H_
+#include "NGLogFileHandleAppender.h"
 
-/*
-  NGLogConsoleAppender
-  A very simple console appender. The current implementation logs the
-  formatted event via NSLog(). Please note that doing so discards the timestamp
-  saved in the event, so the logged time isn't really exact, but will probably
-  only differ marginally.
-*/
-
-#include <NGExtensions/NGLogAppender.h>
-
-@interface NGLogConsoleAppender : NGLogAppender
+@interface NGLogStdoutAppender : NGLogFileHandleAppender
 {
 }
 
 @end
 
-#endif /* __NGExtensions_NGLogConsoleAppender_H_ */
+#include "common.h"
+
+@implementation NGLogStdoutAppender
+
+- (void)openFileHandleWithConfig:(NSDictionary *)_config {
+  self->fh = [[NSFileHandle fileHandleWithStandardOutput] retain];
+}
+
+@end /* NGLogStdoutAppender */
index 1bb3be11c657d0965d46a776bb880565ac33c681..ba0884d7e1af492711f1da7238dba06e132b2e79 100644 (file)
@@ -55,8 +55,13 @@ static NSString *defaultSyslogIdentifier = nil;
   return sharedAppender;
 }
 
-- (id)init {
-  return [self initWithIdentifier:defaultSyslogIdentifier];
+- (id)initWithConfig:(NSDictionary *)_config {
+  NSString *identifier;
+  
+  identifier = [_config objectForKey:@"SyslogIdentifier"];
+  if(!identifier)
+    identifier = defaultSyslogIdentifier;
+  return [self initWithIdentifier:identifier];
 }
 
 - (id)initWithIdentifier:(NSString *)_ident {
index fd74640682f2e4d8b08988a9e0204ad8bc972ef9..09b814fdbcdcd4ef0da1ee9478bad3497f9114c7 100644 (file)
 */
 
 #include "NGLogger.h"
-#include "common.h"
 #include "NGLogEvent.h"
 #include "NGLogAppender.h"
+#include "NSNull+misc.h"
+#include "common.h"
 
 @interface NGLogger (PrivateAPI)
-- (void)logLevel:(NGLogLevel)_level message:(NSString *)_msg;
-- (void)logLevel:(NGLogLevel)_level withFormat:(NSString *)_fmt, ...;
++ (NGLogLevel)_logLevelForString:(NSString *)_level;
 @end
 
 @implementation NGLogger
 
-static Class NSStringClass = Nil;
+static Class      NSStringClass   = Nil;
+static NGLogger   *defaultLogger  = nil;
+static NGLogLevel defaultLogLevel = NGLogLevelInfo;
 
 + (void)initialize {
-  static BOOL didInit = NO;
-  if (didInit)
-    return;
-  didInit       = YES;
-  NSStringClass = [NSString class];
+  static BOOL    didInit = NO;
+  NSUserDefaults *ud;
+  NSString       *level;
+
+  if (didInit) return;
+
+  didInit         = YES;
+  NSStringClass   = [NSString class];
+  ud              = [NSUserDefaults standardUserDefaults];
+  level           = [ud stringForKey:@"NGLogDefaultLogLevel"];
+  defaultLogLevel = [self _logLevelForString:level];
+  defaultLogger   = [[self alloc] init];
 }
 
-+ (id)defaultLogger {
-  static NGLogger *logger = nil; // THREAD
-  
-  if (logger == nil)
-    logger = [[self alloc] init];
++ (id)loggerWithConfigFromUserDefaults:(NSString *)_defaultName {
+  NSUserDefaults *ud;
+  NSDictionary   *config;
+  id             logger;
+
+  ud     = [NSUserDefaults standardUserDefaults];
+  config = [ud dictionaryForKey:_defaultName];
+  if(!config)
+    return defaultLogger;
+  logger = [[[NGLogger alloc] initWithConfig:config] autorelease];
   return logger;
 }
 
 - (id)init {
-  return [self initWithLogLevel:NGLogLevelAll];
+  return [self initWithConfig:nil];
 }
 
-- (id)initWithLogLevel:(NGLogLevel)_level appender:(id)_appenderParam {
-  if ((self = [super init]) != nil) {
-    [self setLogLevel:_level];
-    self->_appender = [_appenderParam retain]; // TODO: fix ivar name
+- (id)initWithConfig:(NSDictionary *)_config {
+  self = [super init];
+  if (self) {
+    NSArray       *appenderConfigs;
+    NGLogAppender *appender;
+    NSString      *levelString;
+    NGLogLevel    level;
+    unsigned      count;
+
+    self->appenders = [[NSMutableArray alloc] initWithCapacity:1];
+
+    levelString = [_config objectForKey:@"LogLevel"];
+    level       = [NGLogger _logLevelForString:levelString];
+    [self setLogLevel:level];
+
+    appenderConfigs = [_config objectForKey:@"Appenders"];
+    count           = [appenderConfigs count];
+    if(!count) {
+      /* create a default appender */
+      appender = [NGLogAppender logAppenderFromConfig:nil];
+      [self addAppender:appender];
+    }
+    else {
+      unsigned i;
+
+      for(i = 0; i < count; i++) {
+        NSDictionary  *appenderConfig;
+
+        appenderConfig = [appenderConfigs objectAtIndex:i];
+        appender       = [NGLogAppender logAppenderFromConfig:appenderConfig];
+        if(appender)
+          [self addAppender:appender];
+      }
+    }
   }
   return self;
 }
 
 - (id)initWithLogLevel:(NGLogLevel)_level {
-  NSUserDefaults *ud;
-  NSString       *appenderClassName;
-  id appender;
-  
-  // TODO: remove this as soon as we have a config
-  ud                = [NSUserDefaults standardUserDefaults];
-  appenderClassName = [ud stringForKey:@"NGLogDefaultAppenderClass"];
-  if (appenderClassName == nil)
-    appenderClassName = @"NGLogConsoleAppender";
-  
-  appender = [[NSClassFromString(appenderClassName) alloc] init];
-  
-  self = [self initWithLogLevel:_level appender:appender];
-  [appender release];
+  self = [self initWithConfig:nil];
+  if (self) {
+    [self setLogLevel:_level];
+  }
   return self;
 }
 
 - (void)dealloc {
-  [self->_appender release];
+  [self->appenders release];
   [super dealloc];
 }
 
@@ -93,6 +127,14 @@ static Class NSStringClass = Nil;
   return self->logLevel;
 }
 
+- (void)addAppender:(NGLogAppender *)_appender {
+  [self->appenders addObject:_appender];
+}
+
+- (void)removeAppender:(NGLogAppender *)_appender {
+  [self->appenders removeObject:_appender];
+}
+
 /* logging */
 
 - (void)debugWithFormat:(NSString *)_fmt arguments:(va_list)_va {
@@ -147,12 +189,17 @@ static Class NSStringClass = Nil;
 
 - (void)logLevel:(NGLogLevel)_level message:(NSString *)_msg {
   NGLogEvent *event;
+  unsigned   i, count;
 
   event = [[NGLogEvent alloc] initWithLevel:_level message:_msg];
 
-  // iterate appenders
-  // TODO: as soon as we have more appenders, we need to iterate on them
-  [self->_appender appendLogEvent:event];
+  count = [self->appenders count];
+  for(i = 0; i < count; i++) {
+    NGLogAppender *appender;
+    
+    appender = [self->appenders objectAtIndex:i];
+    [appender appendLogEvent:event];
+  }
   [event release];
 }
 
@@ -174,4 +221,44 @@ static Class NSStringClass = Nil;
   return self->logLevel >= NGLogLevelFatal;
 }
 
+
+/* Private */
+
++ (NGLogLevel)_logLevelForString:(NSString *)_level {
+  if (![_level isNotNull]) {
+    _level = [_level uppercaseString];
+    if ([_level isEqualToString:@"DEBUG"])
+      return NGLogLevelDebug;
+    else if ([_level isEqualToString:@"INFO"])
+      return NGLogLevelInfo;
+    else if ([_level isEqualToString:@"WARN"])
+      return NGLogLevelWarn;
+    else if ([_level isEqualToString:@"ERROR"])
+      return NGLogLevelError;
+    else if ([_level isEqualToString:@"FATAL"])
+      return NGLogLevelFatal;
+    return NGLogLevelAll; /* better than nothing */
+  }
+  return NGLogLevelInfo;
+}
+
+/* description */
+
+- (NSString *)description {
+  NSString *lvl;
+  
+  switch (self->logLevel) {
+    case NGLogLevelOff:   lvl = @"OFF";   break;
+    case NGLogLevelDebug: lvl = @"DEBUG"; break;
+    case NGLogLevelInfo:  lvl = @"INFO";  break;
+    case NGLogLevelWarn:  lvl = @"WARN";  break;
+    case NGLogLevelError: lvl = @"ERROR"; break;
+    case NGLogLevelFatal: lvl = @"FATAL"; break;
+    default:              lvl = @"ALL";   break;
+  }
+  return [NSString stringWithFormat:@"<%@[0x%08X] logLevel=%@ appenders:%@>",
+                     NSStringFromClass([self class]), self,
+                     lvl, self->appenders];
+}
+
 @end /* NGLogger */
index 550ed3dfa4d38b5f1033d0b75be342d925b1cbb1..c51b37eb3ec668abf0892f4bccf08e83e392b7bb 100644 (file)
 #include "NGLoggerManager.h"
 #include "NGLogLevel.h"
 #include "NGLogger.h"
+#include "NSNull+misc.h"
 #include "common.h"
 
+@interface NGLoggerManager (PrivateAPI)
+- (NGLogger *)_getConfiguredLoggerNamed:(NSString *)_name;
+@end
+
 @implementation NGLoggerManager
 
-static NGLoggerManager *sharedInstance;
-static NSNull          *sharedNull;
+static NGLoggerManager *sharedInstance = nil;
+static NSNull          *sharedNull     = nil;
+static BOOL            debugAll        = NO;
 
 + (void)initialize {
-  static BOOL didInit = NO;
-  
-  if (didInit)
-    return;
+  static BOOL    didInit = NO;
+  NSUserDefaults *ud;
+
+  if (didInit) return;
   
-  didInit        = YES;
-  sharedInstance = [[self alloc] init];
-  sharedNull     = [[NSNull null] retain];
+  didInit         = YES;
+  sharedInstance  = [[self alloc] init];
+  sharedNull      = [[NSNull null] retain];
+  ud              = [NSUserDefaults standardUserDefaults];
+  debugAll        = [ud boolForKey:@"NGLogDebugAllEnabled"];
 }
 
 + (id)defaultLoggerManager {
@@ -71,28 +79,26 @@ static NSNull          *sharedNull;
     NSUserDefaults *ud;
 
     ud = [NSUserDefaults standardUserDefaults];
-    if (![ud boolForKey:_defaultKey]) {
+    if (!debugAll && ![ud boolForKey:_defaultKey]) {
       [self->loggerMap setObject:sharedNull forKey:_defaultKey];
       logger = sharedNull;
     }
     else {
-      logger = [[NGLogger alloc] initWithLogLevel:NGLogLevelDebug];
+      logger = [self _getConfiguredLoggerNamed:_defaultKey];
       [self->loggerMap setObject:logger forKey:_defaultKey];
-      [logger release];
     }
   }
   return (logger != sharedNull) ? logger : nil;
 }
 
 - (NGLogger *)loggerForFacilityNamed:(NSString *)_name {
-  id logger;
+  NGLogger *logger;
   
   // TODO: expensive, use a faster map (at least NSMapTable)
   if ((logger = [self->loggerMap objectForKey:_name]) != nil)
     return logger;
-  
-  // TODO: is a registration really faster? I guess not?
-  logger = [NGLogger defaultLogger]; /* fallback to shared logger */
+
+  logger = [self _getConfiguredLoggerNamed:_name];
   [self->loggerMap setObject:logger forKey:_name];
   return logger;
 }
@@ -104,4 +110,21 @@ static NSNull          *sharedNull;
   return [self loggerForFacilityNamed:name];
 }
 
+/* Private */
+
+- (NGLogger *)_getConfiguredLoggerNamed:(NSString *)_name {
+  NSString *configKey;
+  
+  configKey = [NSString stringWithFormat:@"%@LoggerConfig", _name];
+  return [NGLogger loggerWithConfigFromUserDefaults:configKey];
+}
+
+/* description */
+
+- (NSString *)description {
+  return [NSString stringWithFormat:@"<%@[0x%08X] debugAll=%@ #loggers=%d>",
+                     NSStringFromClass([self class]), self,
+                     debugAll ? @"YES" : @"NO", [self->loggerMap count]];
+}
+
 @end /* NGLoggerManager */
index 38af7b35d1295a2459434198c5bc0c9f797ef834..0ed06f525fe862d0ba5f57ce6aa4ed66fbcff006 100644 (file)
@@ -1,6 +1,6 @@
 # version
 
-SUBMINOR_VERSION:=135
+SUBMINOR_VERSION:=136
 
 # v4.3.115 requires libFoundation v1.0.59
 # v4.2.72  requires libEOControl  v4.2.39