[mapguide-commits] r4531 - in trunk/MgDev: Common/MapGuideCommon/System Server/src/Common/Cache Server/src/Common/Manager Server/src/Core

svn_mapguide at osgeo.org svn_mapguide at osgeo.org
Wed Jan 13 18:40:03 EST 2010


Author: brucedechant
Date: 2010-01-13 18:40:02 -0500 (Wed, 13 Jan 2010)
New Revision: 4531

Added:
   trunk/MgDev/Server/src/Core/PerformanceLoggingEventHandler.cpp
   trunk/MgDev/Server/src/Core/PerformanceLoggingEventHandler.h
Modified:
   trunk/MgDev/Common/MapGuideCommon/System/ConfigProperties.cpp
   trunk/MgDev/Common/MapGuideCommon/System/ConfigProperties.h
   trunk/MgDev/Server/src/Common/Cache/FeatureServiceCache.cpp
   trunk/MgDev/Server/src/Common/Cache/FeatureServiceCache.h
   trunk/MgDev/Server/src/Common/Manager/Connection.cpp
   trunk/MgDev/Server/src/Common/Manager/LogManager.cpp
   trunk/MgDev/Server/src/Common/Manager/LogManager.h
   trunk/MgDev/Server/src/Common/Manager/LogType.h
   trunk/MgDev/Server/src/Common/Manager/ServerManager.cpp
   trunk/MgDev/Server/src/Core/EventTimer.h
   trunk/MgDev/Server/src/Core/Makefile.am
   trunk/MgDev/Server/src/Core/Server.cpp
   trunk/MgDev/Server/src/Core/ServerCore.vcproj
   trunk/MgDev/Server/src/Core/ServerCoreBuild.cpp
   trunk/MgDev/Server/src/Core/TimedEvent.h
   trunk/MgDev/Server/src/Core/TimedEventHandler.cpp
   trunk/MgDev/Server/src/Core/serverconfig.ini
Log:
Fix for trac ticket 1173 - Add performance logging
http://trac.osgeo.org/mapguide/ticket/1173

Notes:
- Add support for a performance log 


Modified: trunk/MgDev/Common/MapGuideCommon/System/ConfigProperties.cpp
===================================================================
--- trunk/MgDev/Common/MapGuideCommon/System/ConfigProperties.cpp	2010-01-13 21:45:23 UTC (rev 4530)
+++ trunk/MgDev/Common/MapGuideCommon/System/ConfigProperties.cpp	2010-01-13 23:40:02 UTC (rev 4531)
@@ -421,6 +421,19 @@
 const STRING MgConfigProperties::DefaultErrorLogPropertyParameters                          = L"";
 
 // ******************************************************************
+// Performance Log Properties
+// ******************************************************************
+const STRING MgConfigProperties::PerformanceLogPropertiesSection                            = L"PerformanceLogProperties";
+const STRING MgConfigProperties::PerformanceLogPropertyEnabled                              = L"Enabled";
+const bool   MgConfigProperties::DefaultPerformanceLogPropertyEnabled                       = false;
+const STRING MgConfigProperties::PerformanceLogPropertyFilename                             = L"Filename";
+const STRING MgConfigProperties::DefaultPerformanceLogPropertyFilename                      = L"Performance.log";
+const STRING MgConfigProperties::PerformanceLogPropertyParameters                           = L"Parameters";
+const STRING MgConfigProperties::DefaultPerformanceLogPropertyParameters                    = L"";
+const STRING MgConfigProperties::PerformanceLogPropertyInterval                             = L"Interval";
+const INT32  MgConfigProperties::DefaultPerformanceLogPropertyInterval                      = 300;
+
+// ******************************************************************
 // Session Log Properties
 // ******************************************************************
 const STRING MgConfigProperties::SessionLogPropertiesSection                                = L"SessionLogProperties";
@@ -673,6 +686,15 @@
     { L""                                                                           , 0                         , 0.0                                   , 0.0                                   , L""                                       }
 };
 
+const MgConfigValidationInfo MgConfigProperties::sm_cviPerformanceLogProperties[] =
+{
+    { MgConfigProperties::PerformanceLogPropertyEnabled                             , MgPropertyType::Boolean   , 0                                     , 1                                     , L""                                       },
+    { MgConfigProperties::PerformanceLogPropertyFilename                            , MgPropertyType::String    , MG_CONFIG_MIN_FILE_NAME_LENGTH        , MG_CONFIG_MAX_FILE_NAME_LENGTH        , MG_CONFIG_FILE_NAME_RESERVED_CHARACTERS   },
+    { MgConfigProperties::PerformanceLogPropertyParameters                          , MgPropertyType::String    , MG_CONFIG_MIN_LOG_PARAMETERS_LENGTH   , MG_CONFIG_MAX_LOG_PARAMETERS_LENGTH   , L""                                       },
+    { MgConfigProperties::PerformanceLogPropertyInterval                            , MgPropertyType::Int32     , 0                                     , 60000                                 , L""                                       },
+    { L""                                                                           , 0                         , 0.0                                   , 0.0                                   , L""                                       }
+};
+
 const MgConfigValidationInfo MgConfigProperties::sm_cviSessionLogProperties[] =
 {
     { MgConfigProperties::SessionLogPropertyEnabled                                 , MgPropertyType::Boolean   , 0                                     , 1                                     , L""                                       },

Modified: trunk/MgDev/Common/MapGuideCommon/System/ConfigProperties.h
===================================================================
--- trunk/MgDev/Common/MapGuideCommon/System/ConfigProperties.h	2010-01-13 21:45:23 UTC (rev 4530)
+++ trunk/MgDev/Common/MapGuideCommon/System/ConfigProperties.h	2010-01-13 23:40:02 UTC (rev 4531)
@@ -717,6 +717,28 @@
     static const STRING ErrorLogPropertyParameters;                 /// value("Parameters")
     static const STRING DefaultErrorLogPropertyParameters;          /// value("")
 
+    /// PERFORMANCE LOG PROPERTIES SECTION -------------------------------------------------------------------------------------
+
+    /// Performance Log properties.  This log records all server statistical information.
+    static const STRING PerformanceLogPropertiesSection;                  /// value("PerformanceLogProperties")
+
+    /// Enables/disables the Performance log
+    static const STRING PerformanceLogPropertyEnabled;                    /// value("Enabled")
+    static const bool DefaultPerformanceLogPropertyEnabled;               /// value(false)
+
+    /// The Performance log's file name.  NOTE: As with the Access Log, the special characters: %d,
+    /// %m, %y may be used in the filename.
+    static const STRING PerformanceLogPropertyFilename;                   /// value("Filename")
+    static const STRING DefaultPerformanceLogPropertyFilename;            /// value("Performance.log")
+
+    /// The Performance log's parameters
+    static const STRING PerformanceLogPropertyParameters;                 /// value("Parameters")
+    static const STRING DefaultPerformanceLogPropertyParameters;          /// value("")
+
+    /// Sets the time duration (in seconds) between logging performance statistics
+    static const STRING PerformanceLogPropertyInterval;                   /// value("Interval")
+    static const INT32 DefaultPerformanceLogPropertyInterval;             /// value(300)
+
     /// SESSION LOG PROPERTIES SECTION -----------------------------------------------------------------------------------
 
     /// Session Log properties.  This log records state information for each connection
@@ -854,6 +876,7 @@
     static const MgConfigValidationInfo sm_cviAdminLogProperties[];
     static const MgConfigValidationInfo sm_cviAuthenticationLogProperties[];
     static const MgConfigValidationInfo sm_cviErrorLogProperties[];
+    static const MgConfigValidationInfo sm_cviPerformanceLogProperties[];
     static const MgConfigValidationInfo sm_cviSessionLogProperties[];
     static const MgConfigValidationInfo sm_cviTraceLogProperties[];
 

Modified: trunk/MgDev/Server/src/Common/Cache/FeatureServiceCache.cpp
===================================================================
--- trunk/MgDev/Server/src/Common/Cache/FeatureServiceCache.cpp	2010-01-13 21:45:23 UTC (rev 4530)
+++ trunk/MgDev/Server/src/Common/Cache/FeatureServiceCache.cpp	2010-01-13 23:40:02 UTC (rev 4531)
@@ -22,7 +22,8 @@
 /// \brief
 /// Construct the object.
 ///
-MgFeatureServiceCache::MgFeatureServiceCache()
+MgFeatureServiceCache::MgFeatureServiceCache() :
+    m_nDroppedEntries(0)
 {
     Initialize(MgConfigProperties::DefaultFeatureServicePropertyCacheSize,
         MgConfigProperties::DefaultFeatureServicePropertyCacheTimeLimit);
@@ -216,6 +217,7 @@
     {
         SAFE_RELEASE(oldEntry->second);
         m_featureServiceCacheEntries.erase(oldEntry);
+        m_nDroppedEntries++;
     }
 }
 
@@ -510,3 +512,26 @@
 
     return data.Detach();
 }
+
+///////////////////////////////////////////////////////////////////////////////
+/// \brief
+/// Returns the size of the cache.
+///
+INT32 MgFeatureServiceCache::GetCacheSize()
+{
+    ACE_MT(ACE_GUARD_RETURN(ACE_Recursive_Thread_Mutex, ace_mon, m_mutex, -1));
+
+    INT32 size = (INT32)m_featureServiceCacheEntries.size();
+    return size;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// \brief
+/// Returns the # of dropped cache entries.
+///
+INT32 MgFeatureServiceCache::GetDroppedEntriesCount()
+{
+    ACE_MT(ACE_GUARD_RETURN(ACE_Recursive_Thread_Mutex, ace_mon, m_mutex, -1));
+
+    return m_nDroppedEntries;
+}

Modified: trunk/MgDev/Server/src/Common/Cache/FeatureServiceCache.h
===================================================================
--- trunk/MgDev/Server/src/Common/Cache/FeatureServiceCache.h	2010-01-13 21:45:23 UTC (rev 4530)
+++ trunk/MgDev/Server/src/Common/Cache/FeatureServiceCache.h	2010-01-13 23:40:02 UTC (rev 4531)
@@ -78,6 +78,9 @@
     void SetClassIdentityProperties(MgResourceIdentifier* resource, CREFSTRING schemaName, CREFSTRING className, MgPropertyDefinitionCollection* idProperties);
     MgPropertyDefinitionCollection* GetClassIdentityProperties(MgResourceIdentifier* resource, CREFSTRING schemaName, CREFSTRING className);
 
+    INT32 GetCacheSize();
+    INT32 GetDroppedEntriesCount();
+
 protected:
 
     void Compact();
@@ -94,6 +97,7 @@
 
     typedef std::map<STRING, MgFeatureServiceCacheEntry*> MgFeatureServiceCacheEntries;
     MgFeatureServiceCacheEntries m_featureServiceCacheEntries;
+    INT32 m_nDroppedEntries;
 };
 
 #endif

Modified: trunk/MgDev/Server/src/Common/Manager/Connection.cpp
===================================================================
--- trunk/MgDev/Server/src/Common/Manager/Connection.cpp	2010-01-13 21:45:23 UTC (rev 4530)
+++ trunk/MgDev/Server/src/Common/Manager/Connection.cpp	2010-01-13 23:40:02 UTC (rev 4531)
@@ -164,7 +164,7 @@
     double connectionTime = GetConnectionTime();
 
     // Log connection info (to the screen)
-    ACE_DEBUG ((LM_DEBUG, "Ended connection.  Operations processed: %d/%d, Connect Time: %f msec\n",
+    ACE_DEBUG ((LM_DEBUG, "Ended connection.  Ops processed: %d/%d, Connect Time: %f msec\n",
         m_nProcessedOperations, m_nReceivedOperations, connectionTime));
 }
 

Modified: trunk/MgDev/Server/src/Common/Manager/LogManager.cpp
===================================================================
--- trunk/MgDev/Server/src/Common/Manager/LogManager.cpp	2010-01-13 21:45:23 UTC (rev 4530)
+++ trunk/MgDev/Server/src/Common/Manager/LogManager.cpp	2010-01-13 23:40:02 UTC (rev 4531)
@@ -36,6 +36,7 @@
 const STRING MgLogManager::DefaultAdminLogFileName          = L"Admin.log";
 const STRING MgLogManager::DefaultAuthenticationLogFileName = L"Authentication.log";
 const STRING MgLogManager::DefaultErrorLogFileName          = L"Error.log";
+const STRING MgLogManager::DefaultPerformanceLogFileName    = L"Performance.log";
 const STRING MgLogManager::DefaultSessionLogFileName        = L"Session.log";
 const STRING MgLogManager::DefaultTraceLogFileName          = L"Trace.log";
 
@@ -55,6 +56,23 @@
 const STRING MgLogManager::StartTimeParam       = L"STARTTIME";
 const STRING MgLogManager::UserParam            = L"USER";
 
+// Performance Log parameters
+const STRING MgLogManager::PerformanceAdminOperationsQueueCount  = L"ADMINOPQCOUNT";
+const STRING MgLogManager::PerformanceClientOperationsQueueCount = L"CLIENTOPQCOUNT";
+const STRING MgLogManager::PerformanceSiteOperationsQueueCount   = L"SITEOPQCOUNT";
+const STRING MgLogManager::PerformanceAverageOperationTime       = L"AVGOPTIME";
+const STRING MgLogManager::PerformanceCpuUtilization             = L"CPU";
+const STRING MgLogManager::PerformanceWorkingSet                 = L"WORKINGSET";
+const STRING MgLogManager::PerformanceVirtualMemory              = L"VIRTUALMEMORY";
+const STRING MgLogManager::PerformanceTotalOperationTime         = L"TOTALOPTIME";
+const STRING MgLogManager::PerformanceTotalActiveConnections     = L"TOTALACTIVECONNECTIONS";
+const STRING MgLogManager::PerformanceTotalConnections           = L"TOTALCONNECTIONS";
+const STRING MgLogManager::PerformanceTotalProcessedOperations   = L"TOTALPROCESSEDOP";
+const STRING MgLogManager::PerformanceTotalReceivedOperations    = L"TOTALRECEIVEDOP";
+const STRING MgLogManager::PerformanceUptime                     = L"UPTIME";
+const STRING MgLogManager::PerformanceCacheSize                  = L"CACHESIZE";
+const STRING MgLogManager::PerformanceCacheDroppedEntries        = L"CACHEDROPPEDENTRIES";
+
 // Header line prefix strings
 const STRING MgLogManager::HeaderLine1          = L"# Log Type:";
 const STRING MgLogManager::HeaderLine2          = L"# Log Parameters:";
@@ -64,6 +82,7 @@
 const STRING MgLogManager::AdminLog             = L"Admin Log";
 const STRING MgLogManager::AuthenticationLog    = L"Authentication Log";
 const STRING MgLogManager::ErrorLog             = L"Error Log";
+const STRING MgLogManager::PerformanceLog       = L"Performance Log";
 const STRING MgLogManager::SessionLog           = L"Session Log";
 const STRING MgLogManager::TraceLog             = L"Trace Log";
 const STRING MgLogManager::UnspecifiedLog       = L"Unspecified";
@@ -92,6 +111,9 @@
     m_bErrorLogEnabled(true),
     m_bErrorLogHeader(false),
     m_ErrorLogFileName(MgLogManager::DefaultErrorLogFileName),
+    m_bPerformanceLogEnabled(false),
+    m_bPerformanceLogHeader(false),
+    m_PerformanceLogFileName(MgLogManager::DefaultPerformanceLogFileName),
     m_bSessionLogEnabled(true),
     m_bSessionLogHeader(false),
     m_SessionLogFileName(MgLogManager::DefaultSessionLogFileName),
@@ -129,6 +151,11 @@
         m_errorLogStream.close();
     }
 
+    if(m_performanceLogStream.is_open())
+    {
+        m_performanceLogStream.close();
+    }
+
     if(m_sessionLogStream.is_open())
     {
         m_sessionLogStream.close();
@@ -265,6 +292,14 @@
     m_ErrorLogFileName = ValidateLogFileName(logFileName);
     SetErrorLogEnabled(bLogEnabled);
 
+    // Performance Log
+    pConfiguration->GetBoolValue(MgConfigProperties::PerformanceLogPropertiesSection, MgConfigProperties::PerformanceLogPropertyEnabled, bLogEnabled, MgConfigProperties::DefaultPerformanceLogPropertyEnabled);
+    pConfiguration->GetStringValue(MgConfigProperties::PerformanceLogPropertiesSection, MgConfigProperties::PerformanceLogPropertyFilename, logFileName, MgConfigProperties::DefaultPerformanceLogPropertyFilename);
+    pConfiguration->GetStringValue(MgConfigProperties::PerformanceLogPropertiesSection, MgConfigProperties::PerformanceLogPropertyParameters, logParameters, MgConfigProperties::DefaultPerformanceLogPropertyParameters);
+    m_PerformanceLogParameters = logParameters;
+    m_PerformanceLogFileName = ValidateLogFileName(logFileName);
+    SetPerformanceLogEnabled(bLogEnabled);
+
     // Session Log
     pConfiguration->GetBoolValue(MgConfigProperties::SessionLogPropertiesSection, MgConfigProperties::SessionLogPropertyEnabled, bLogEnabled, MgConfigProperties::DefaultSessionLogPropertyEnabled);
     pConfiguration->GetStringValue(MgConfigProperties::SessionLogPropertiesSection, MgConfigProperties::SessionLogPropertyFilename, logFileName, MgConfigProperties::DefaultSessionLogPropertyFilename);
@@ -998,6 +1033,177 @@
     return byteReader.Detach();
 }
 
+void MgLogManager::SetPerformanceLogInfo(bool bEnabled, CREFSTRING filename, CREFSTRING parameters)
+{
+    MG_LOGMANAGER_TRY()
+
+    ACE_MT (ACE_GUARD (ACE_Recursive_Thread_Mutex, ace_mon, m_mutex));
+
+    // Disable existing log in use if there is one
+    DisableLog(mltError);
+
+    SetPerformanceLogParameters(parameters);
+    SetPerformanceLogFileName(filename);
+    SetPerformanceLogEnabled(bEnabled);
+
+    MG_LOGMANAGER_CATCH_AND_THROW(L"MgLogManager.SetPerformanceLogInfo");
+}
+
+bool MgLogManager::IsPerformanceLogEnabled()
+{
+    ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, m_mutex, false));
+
+    return m_bPerformanceLogEnabled;
+}
+
+void MgLogManager::SetPerformanceLogEnabled(bool bEnabled)
+{
+    MG_LOGMANAGER_TRY()
+
+    ACE_MT (ACE_GUARD (ACE_Recursive_Thread_Mutex, ace_mon, m_mutex));
+
+    m_bPerformanceLogEnabled = bEnabled;
+    if(m_bPerformanceLogEnabled)
+    {
+        ValidateLogHeaders(mltPerformance);
+        EnableLog(mltPerformance);
+    }
+    else
+    {
+        DisableLog(mltPerformance);
+    }
+
+    MG_LOGMANAGER_CATCH_AND_THROW(L"MgLogManager.SetPerformanceLogEnabled")
+}
+
+STRING MgLogManager::GetPerformanceLogFileName()
+{
+    ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, m_mutex, STRING(L"")));
+
+    return m_PerformanceLogFileName;
+}
+
+void MgLogManager::SetPerformanceLogFileName(CREFSTRING filename)
+{
+    ACE_MT (ACE_GUARD (ACE_Recursive_Thread_Mutex, ace_mon, m_mutex));
+
+    DisableLog(mltPerformance);
+    m_PerformanceLogFileName = ValidateLogFileName(filename);
+    EnableLog(mltPerformance);
+}
+
+STRING MgLogManager::GetPerformanceLogParameters()
+{
+    ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, m_mutex, STRING(L"")));
+
+    return m_PerformanceLogParameters;
+}
+
+void MgLogManager::SetPerformanceLogParameters(CREFSTRING parameters)
+{
+    MG_LOGMANAGER_TRY()
+
+    ACE_MT (ACE_GUARD (ACE_Recursive_Thread_Mutex, ace_mon, m_mutex));
+
+    if (0 != parameters.compare(m_PerformanceLogParameters))
+    {
+        ArchiveLog(mltPerformance);
+    }
+    m_PerformanceLogParameters = parameters;
+
+    MG_LOGMANAGER_CATCH_AND_THROW(L"MgLogManager.SetPerformanceLogParameters")
+}
+
+bool MgLogManager::ClearPerformanceLog()
+{
+    bool bResult = false;
+
+    MG_LOGMANAGER_TRY()
+
+    ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, m_mutex, false));
+
+    // Disable the log which closes the log for us
+    DisableLog(mltPerformance);
+
+    // Get the performance log filename and path
+    STRING filename = BuildFileName(m_PerformanceLogFileName);
+    bResult = RemoveLogFile(filename);
+
+    // Enable the log which opens the log for us
+    EnableLog(mltPerformance);
+
+    MG_LOGMANAGER_CATCH_AND_THROW(L"MgLogManager.ClearPerformanceLog")
+
+    return bResult;
+}
+
+MgByteReader* MgLogManager::GetPerformanceLog()
+{
+    Ptr<MgByteReader> byteReader;
+
+    MG_LOGMANAGER_TRY()
+
+    ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, m_mutex, NULL));
+
+    // Disable the log which closes the log for us
+    DisableLog(mltPerformance);
+
+    // Get the performance log filename and path
+    STRING filename = BuildFileName(m_PerformanceLogFileName);
+    byteReader = GetLogContents(filename);
+
+    // Enable the log which opens the log for us
+    EnableLog(mltPerformance);
+
+    MG_LOGMANAGER_CATCH_AND_THROW(L"MgLogManager.GetPerformanceLog")
+
+    return byteReader.Detach();
+}
+
+MgByteReader* MgLogManager::GetPerformanceLog(INT32 numEntries)
+{
+    Ptr<MgByteReader> byteReader;
+
+    MG_LOGMANAGER_TRY()
+
+    ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, m_mutex, NULL));
+
+    // Disable the log which closes the log for us
+    DisableLog(mltPerformance);
+
+    // Get the performance log filename and path
+    STRING filename = BuildFileName(m_PerformanceLogFileName);
+    byteReader = GetLogContents(filename, numEntries);
+
+    // Enable the log which opens the log for us
+    EnableLog(mltPerformance);
+
+    MG_LOGMANAGER_CATCH_AND_THROW(L"MgLogManager.GetPerformanceLog")
+
+    return byteReader.Detach();
+}
+
+MgByteReader* MgLogManager::GetPerformanceLog(MgDateTime* fromDate, MgDateTime* toDate)
+{
+    Ptr<MgByteReader> byteReader;
+
+    MG_LOGMANAGER_TRY()
+
+    ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, m_mutex, NULL));
+
+    // Disable the log which closes the log for us
+    DisableLog(mltPerformance);
+
+    byteReader = GetLogContents(mltPerformance, fromDate, toDate);
+
+    // Enable the log which opens the log for us
+    EnableLog(mltPerformance);
+
+    MG_LOGMANAGER_CATCH_AND_THROW(L"MgLogManager.GetPerformanceLog")
+
+    return byteReader.Detach();
+}
+
 void MgLogManager::SetSessionLogInfo(bool bEnabled, CREFSTRING filename, CREFSTRING parameters)
 {
     MG_LOGMANAGER_TRY()
@@ -1681,6 +1887,171 @@
     QueueLogEntry(mltError, logEntry, LM_ERROR);
 }
 
+void MgLogManager::LogPerformanceEntry(MgPropertyCollection* entry)
+{
+    // Message to be entered into the log
+    STRING logEntry;
+
+    MG_LOGMANAGER_TRY()
+
+    // Parse parameter string into an MgStringCollection
+    Ptr<MgStringCollection> paramList = MgStringCollection::ParseCollection(
+        GetPerformanceLogParameters().c_str(), L",");
+
+    // Go through parameter list and add the information appropriately
+    if (paramList != NULL)
+    {
+        std::string tmpStr;
+        Ptr<MgStringProperty> strProp;
+        Ptr<MgInt64Property> int64Prop;
+        Ptr<MgInt32Property> int32Prop;
+        Ptr<MgBooleanProperty> boolProp;
+        INT32 numParams = paramList->GetCount();
+        STRING param;
+
+        for (INT32 i = 0; i < numParams; ++i)
+        {
+            param = paramList->GetItem(i);
+
+            if (MgLogManager::PerformanceAdminOperationsQueueCount == param)
+            {
+                AddDelimiter(logEntry);
+
+                int32Prop = (MgInt32Property*)entry->GetItem(MgServerInformationProperties::AdminOperationsQueueCount);
+                MgUtil::Int32ToString(int32Prop->GetValue(), tmpStr);
+                logEntry += MgUtil::MultiByteToWideChar(tmpStr);
+            }
+            else if (MgLogManager::PerformanceClientOperationsQueueCount == param)
+            {
+                AddDelimiter(logEntry);
+
+                int32Prop = (MgInt32Property*)entry->GetItem(MgServerInformationProperties::ClientOperationsQueueCount);
+                MgUtil::Int32ToString(int32Prop->GetValue(), tmpStr);
+                logEntry += MgUtil::MultiByteToWideChar(tmpStr);
+            }
+            else if (MgLogManager::PerformanceSiteOperationsQueueCount == param)
+            {
+                AddDelimiter(logEntry);
+
+                int32Prop = (MgInt32Property*)entry->GetItem(MgServerInformationProperties::SiteOperationsQueueCount);
+                MgUtil::Int32ToString(int32Prop->GetValue(), tmpStr);
+                logEntry += MgUtil::MultiByteToWideChar(tmpStr);
+            }
+            else if (MgLogManager::PerformanceAverageOperationTime == param)
+            {
+                AddDelimiter(logEntry);
+
+                int32Prop = (MgInt32Property*)entry->GetItem(MgServerInformationProperties::AverageOperationTime);
+                MgUtil::Int32ToString(int32Prop->GetValue(), tmpStr);
+                logEntry += MgUtil::MultiByteToWideChar(tmpStr);
+            }
+            else if (MgLogManager::PerformanceCpuUtilization == param)
+            {
+                AddDelimiter(logEntry);
+
+                int32Prop = (MgInt32Property*)entry->GetItem(MgServerInformationProperties::CpuUtilization);
+                MgUtil::Int32ToString(int32Prop->GetValue(), tmpStr);
+                logEntry += MgUtil::MultiByteToWideChar(tmpStr);
+            }
+            else if (MgLogManager::PerformanceWorkingSet == param)
+            {
+                AddDelimiter(logEntry);
+
+                int64Prop = (MgInt64Property*)entry->GetItem(MgServerInformationProperties::WorkingSet);
+                MgUtil::Int64ToString(int64Prop->GetValue(), tmpStr);
+                logEntry += MgUtil::MultiByteToWideChar(tmpStr);
+            }
+            else if (MgLogManager::PerformanceVirtualMemory == param)
+            {
+                AddDelimiter(logEntry);
+
+                int64Prop = (MgInt64Property*)entry->GetItem(MgServerInformationProperties::VirtualMemory);
+                MgUtil::Int64ToString(int64Prop->GetValue(), tmpStr);
+                logEntry += MgUtil::MultiByteToWideChar(tmpStr);
+            }
+            else if (MgLogManager::PerformanceTotalOperationTime == param)
+            {
+                AddDelimiter(logEntry);
+
+                int32Prop = (MgInt32Property*)entry->GetItem(MgServerInformationProperties::TotalOperationTime);
+                MgUtil::Int32ToString(int32Prop->GetValue(), tmpStr);
+                logEntry += MgUtil::MultiByteToWideChar(tmpStr);
+            }
+            else if (MgLogManager::PerformanceTotalActiveConnections == param)
+            {
+                AddDelimiter(logEntry);
+
+                int32Prop = (MgInt32Property*)entry->GetItem(MgServerInformationProperties::TotalActiveConnections);
+                MgUtil::Int32ToString(int32Prop->GetValue(), tmpStr);
+                logEntry += MgUtil::MultiByteToWideChar(tmpStr);
+            }
+            else if (MgLogManager::PerformanceTotalConnections == param)
+            {
+                AddDelimiter(logEntry);
+
+                int32Prop = (MgInt32Property*)entry->GetItem(MgServerInformationProperties::TotalConnections);
+                MgUtil::Int32ToString(int32Prop->GetValue(), tmpStr);
+                logEntry += MgUtil::MultiByteToWideChar(tmpStr);
+            }
+            else if (MgLogManager::PerformanceTotalProcessedOperations == param)
+            {
+                AddDelimiter(logEntry);
+
+                int32Prop = (MgInt32Property*)entry->GetItem(MgServerInformationProperties::TotalProcessedOperations);
+                MgUtil::Int32ToString(int32Prop->GetValue(), tmpStr);
+                logEntry += MgUtil::MultiByteToWideChar(tmpStr);
+            }
+            else if (MgLogManager::PerformanceTotalReceivedOperations == param)
+            {
+                AddDelimiter(logEntry);
+
+                int32Prop = (MgInt32Property*)entry->GetItem(MgServerInformationProperties::TotalReceivedOperations);
+                MgUtil::Int32ToString(int32Prop->GetValue(), tmpStr);
+                logEntry += MgUtil::MultiByteToWideChar(tmpStr);
+            }
+            else if (MgLogManager::PerformanceUptime == param)
+            {
+                AddDelimiter(logEntry);
+
+                int32Prop = (MgInt32Property*)entry->GetItem(MgServerInformationProperties::Uptime);
+                MgUtil::Int32ToString(int32Prop->GetValue(), tmpStr);
+                logEntry += MgUtil::MultiByteToWideChar(tmpStr);
+            }
+            else if (MgLogManager::PerformanceCacheSize == param)
+            {
+                AddDelimiter(logEntry);
+
+                int32Prop = (MgInt32Property*)entry->GetItem(MgServerInformationProperties::CacheSize);
+                MgUtil::Int32ToString(int32Prop->GetValue(), tmpStr);
+                logEntry += MgUtil::MultiByteToWideChar(tmpStr);
+            }
+            else if (MgLogManager::PerformanceCacheDroppedEntries == param)
+            {
+                AddDelimiter(logEntry);
+
+                int32Prop = (MgInt32Property*)entry->GetItem(MgServerInformationProperties::CacheDroppedEntries);
+                MgUtil::Int32ToString(int32Prop->GetValue(), tmpStr);
+                logEntry += MgUtil::MultiByteToWideChar(tmpStr);
+            }
+        }
+    }
+
+    MG_LOGMANAGER_CATCH(L"MgLogManager.LogPerformanceEntry")
+
+    if (mgException != NULL)
+    {
+        // Use default message with just the given info.
+        logEntry = mgException->GetMessage();
+    }
+
+    QueueLogEntry(mltPerformance, logEntry, LM_INFO);
+}
+
+void MgLogManager::LogPerformanceEntry(CREFSTRING entry)
+{
+    QueueLogEntry(mltPerformance, entry, LM_INFO);
+}
+
 void MgLogManager::LogSessionEntry(const MgSessionInfo& sessionInfo)
 {
     // Message to be entered into the log
@@ -2133,6 +2504,14 @@
             pLogStream = &m_errorLogStream;
             bEnabled = m_bErrorLogEnabled;
             break;
+        case mltPerformance:
+            // Get the performance log filename and path
+            filename = BuildFileName(m_PerformanceLogFileName);
+            logTypeName = MgLogManager::PerformanceLog;
+            logParameters = GetPerformanceLogParameters();
+            pLogStream = &m_performanceLogStream;
+            bEnabled = m_bPerformanceLogEnabled;
+            break;
         case mltSession:
             // Get the session log filename and path
             filename = BuildFileName(m_SessionLogFileName);
@@ -2299,6 +2678,9 @@
     case mltError:
         filename = BuildFileName(m_ErrorLogFileName);
         break;
+    case mltPerformance:
+        filename = BuildFileName(m_PerformanceLogFileName);
+        break;
     case mltSession:
         filename = BuildFileName(m_SessionLogFileName);
         break;
@@ -2818,6 +3200,9 @@
         // Get the error log filename and path
         rawFilename = m_ErrorLogFileName;
         break;
+    case mltPerformance:
+        rawFilename = m_PerformanceLogFileName;
+        break;
     case mltSession:
         rawFilename = m_SessionLogFileName;
         break;
@@ -3320,6 +3705,10 @@
             logFileName = BuildFileName(m_ErrorLogFileName);
             pLogStream = &m_errorLogStream;
             break;
+        case mltPerformance:
+            logFileName = BuildFileName(m_PerformanceLogFileName);
+            pLogStream = &m_performanceLogStream;
+            break;
         case mltSession:
             logFileName = BuildFileName(m_SessionLogFileName);
             pLogStream = &m_sessionLogStream;
@@ -3443,6 +3832,13 @@
                 ArchiveLog(logType);
             }
             break;
+        case mltPerformance:
+            // Check Performance Log
+            if (!ValidatePerformanceLogHeader())
+            {
+                ArchiveLog(logType);
+            }
+            break;
         case mltSession:
             // Check Session Log
             if (!ValidateSessionLogHeader())
@@ -3556,6 +3952,27 @@
     return bValid;
 }
 
+bool MgLogManager::ValidatePerformanceLogHeader()
+{
+    bool bValid = false;
+
+    MG_LOGMANAGER_TRY()
+
+    ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon, m_mutex, false));
+
+    // Compare the log file parameters list with the current logging parameters
+    STRING logFileParameters = ReadParametersFromLogFile(mltPerformance);
+    STRING currentLogParams = GetPerformanceLogParameters();
+    if (0 == logFileParameters.compare(currentLogParams))
+    {
+        bValid = true;
+    }
+
+    MG_LOGMANAGER_CATCH(L"MgLogManager.ValidatePerformanceLogHeader")
+
+    return bValid;
+}
+
 bool MgLogManager::ValidateSessionLogHeader()
 {
     bool bValid = false;
@@ -3658,6 +4075,9 @@
         case mltError:
             logParameters = m_ErrorLogParameters;
             break;
+        case mltPerformance:
+            logParameters = m_PerformanceLogParameters;
+            break;
         case mltSession:
             logParameters = m_SessionLogParameters;
             break;
@@ -3746,6 +4166,10 @@
     {
         currentLogName = GetErrorLogFileName();
     }
+    else if (0 == logFileType.compare(MgLogManager::PerformanceLog))
+    {
+        currentLogName = GetPerformanceLogFileName();
+    }
     else if (0 == logFileType.compare(MgLogManager::SessionLog))
     {
         currentLogName= GetSessionLogFileName();
@@ -3876,6 +4300,10 @@
         rawFilename = m_ErrorLogFileName;
         logTimestamp = m_cacheErrorLogTimestamp;
         break;
+    case mltPerformance:
+        rawFilename = m_PerformanceLogFileName;
+        logTimestamp = m_cachePerformanceLogTimestamp;
+        break;
     case mltSession:
         rawFilename = m_SessionLogFileName;
         logTimestamp = m_cacheSessionLogTimestamp;
@@ -3982,6 +4410,11 @@
         // Match
         logType = mltError;
     }
+    else if(filename.compare(m_PerformanceLogFileName) == 0)
+    {
+        // Match
+        logType = mltPerformance;
+    }
     else if(filename.compare(m_SessionLogFileName) == 0)
     {
         // Match
@@ -4022,6 +4455,9 @@
         case mltError:
             bResult = m_bErrorLogEnabled;
             break;
+        case mltPerformance:
+            bResult = m_bPerformanceLogEnabled;
+            break;
         case mltSession:
             bResult = m_bSessionLogEnabled;
             break;
@@ -4069,6 +4505,13 @@
                 m_errorLogStream.close();
             }
             break;
+        case mltPerformance:
+            if(m_performanceLogStream.is_open())
+            {
+                // Close the file
+                m_performanceLogStream.close();
+            }
+            break;
         case mltSession:
             if(m_sessionLogStream.is_open())
             {
@@ -4126,6 +4569,14 @@
                 m_errorLogStream.open(MgUtil::WideCharToMultiByte(filename).c_str(), ios::out | ios::app | ios::binary);
             }
             break;
+        case mltPerformance:
+            if(!m_performanceLogStream.is_open())
+            {
+                // Open the file
+                STRING filename = BuildFileName(m_PerformanceLogFileName);
+                m_performanceLogStream.open(MgUtil::WideCharToMultiByte(filename).c_str(), ios::out | ios::app | ios::binary);
+            }
+            break;
         case mltSession:
             if(!m_sessionLogStream.is_open())
             {
@@ -4167,6 +4618,9 @@
         case mltError:
             m_bErrorLogHeader = bHeader;
             break;
+        case mltPerformance:
+            m_bPerformanceLogHeader = bHeader;
+            break;
         case mltSession:
             m_bSessionLogHeader = bHeader;
             break;
@@ -4198,6 +4652,9 @@
         case mltError:
             bResult = m_bErrorLogHeader;
             break;
+        case mltPerformance:
+            bResult = m_bPerformanceLogHeader;
+            break;
         case mltSession:
             bResult = m_bSessionLogHeader;
             break;
@@ -4253,6 +4710,16 @@
         }
     }
 
+    // mltPerformance:
+    if (IsPerformanceLogEnabled())
+    {
+        STRING performanceLogFileName = BuildFileName(m_PerformanceLogFileName);
+        if (MgFileUtil::PathnameExists(performanceLogFileName))
+        {
+            m_cachePerformanceLogTimestamp = MgFileUtil::GetFileModificationTime(performanceLogFileName);
+        }
+    }
+
     // mltSession:
     if (IsSessionLogEnabled())
     {

Modified: trunk/MgDev/Server/src/Common/Manager/LogManager.h
===================================================================
--- trunk/MgDev/Server/src/Common/Manager/LogManager.h	2010-01-13 21:45:23 UTC (rev 4530)
+++ trunk/MgDev/Server/src/Common/Manager/LogManager.h	2010-01-13 23:40:02 UTC (rev 4531)
@@ -129,6 +129,24 @@
     } \
   } while (0)
 
+#define MG_LOG_PERFORMANCE_PROPERTIES_ENTRY(Entry) \
+  do { \
+    MgLogManager* pMan = MgLogManager::GetInstance(); \
+    if(pMan->IsPerformanceLogEnabled()) \
+    { \
+        pMan->LogPerformanceEntry(Entry); \
+    } \
+  } while (0)
+
+#define MG_LOG_PERFORMANCE_STRING_ENTRY(Entry) \
+  do { \
+    MgLogManager* pMan = MgLogManager::GetInstance(); \
+    if(pMan->IsPerformanceLogEnabled()) \
+    { \
+        pMan->LogPerformanceEntry(Entry); \
+    } \
+  } while (0)
+
 #define MG_LOG_OPERATION_MESSAGE(Operation) \
     wchar_t bufferConversion[255]; \
     bufferConversion[0] = 0; \
@@ -288,6 +306,8 @@
     void LogAdminEntry(CREFSTRING opId, CREFSTRING client, CREFSTRING clientIp, CREFSTRING userName);
     void LogAuthenticationEntry(CREFSTRING entry, CREFSTRING client, CREFSTRING clientIp, CREFSTRING userName);
     void LogErrorEntry(CREFSTRING entry, CREFSTRING client, CREFSTRING clientIp, CREFSTRING userName, CREFSTRING stackTrace, CREFSTRING type);
+    void LogPerformanceEntry(MgPropertyCollection* entry);
+    void LogPerformanceEntry(CREFSTRING entry);
     void LogSessionEntry(const MgSessionInfo& sessionInfo);
     void LogTraceEntry(CREFSTRING entry, CREFSTRING client, CREFSTRING clientIp, CREFSTRING userName, CREFSTRING stackTrace = L"", CREFSTRING type = L"");
     void LogSystemErrorEntry(MgException* except);
@@ -344,6 +364,19 @@
     MgByteReader* GetErrorLog(INT32 numEntries);
     MgByteReader* GetErrorLog(MgDateTime* fromDate, MgDateTime* toDate);
 
+    // Performance log methods
+    void SetPerformanceLogInfo(bool bEnabled, CREFSTRING filename, CREFSTRING parameters);
+    bool IsPerformanceLogEnabled();
+    void SetPerformanceLogEnabled(bool bEnabled);
+    STRING GetPerformanceLogFileName();
+    void SetPerformanceLogFileName(CREFSTRING filename);
+    STRING GetPerformanceLogParameters();
+    void SetPerformanceLogParameters(CREFSTRING parameters);
+    bool ClearPerformanceLog();
+    MgByteReader* GetPerformanceLog();
+    MgByteReader* GetPerformanceLog(INT32 numEntries);
+    MgByteReader* GetPerformanceLog(MgDateTime* fromDate, MgDateTime* toDate);
+
     // Session log methods
     void SetSessionLogInfo(bool bEnabled, CREFSTRING filename, CREFSTRING parameters);
     bool IsSessionLogEnabled();
@@ -380,6 +413,7 @@
     static const STRING DefaultAdminLogFileName;
     static const STRING DefaultAuthenticationLogFileName;
     static const STRING DefaultErrorLogFileName;
+    static const STRING DefaultPerformanceLogFileName;
     static const STRING DefaultSessionLogFileName;
     static const STRING DefaultTraceLogFileName;
 
@@ -415,6 +449,23 @@
     static const STRING StartTimeParam;
     static const STRING UserParam;
 
+    // Strings that represent the parameters that are used for the performance log
+    static const STRING PerformanceAdminOperationsQueueCount;
+    static const STRING PerformanceClientOperationsQueueCount;
+    static const STRING PerformanceSiteOperationsQueueCount;
+    static const STRING PerformanceAverageOperationTime;
+    static const STRING PerformanceCpuUtilization;
+    static const STRING PerformanceWorkingSet;
+    static const STRING PerformanceVirtualMemory;
+    static const STRING PerformanceTotalOperationTime;
+    static const STRING PerformanceTotalActiveConnections;
+    static const STRING PerformanceTotalConnections;
+    static const STRING PerformanceTotalProcessedOperations;
+    static const STRING PerformanceTotalReceivedOperations;
+    static const STRING PerformanceUptime;
+    static const STRING PerformanceCacheSize;
+    static const STRING PerformanceCacheDroppedEntries;
+
     // Strings that represent the prefix of the header lines in the log files
     static const STRING HeaderLine1;
     static const STRING HeaderLine2;
@@ -424,6 +475,7 @@
     static const STRING AdminLog;
     static const STRING AuthenticationLog;
     static const STRING ErrorLog;
+    static const STRING PerformanceLog;
     static const STRING SessionLog;
     static const STRING TraceLog;
     static const STRING UnspecifiedLog;
@@ -443,6 +495,7 @@
     std::ofstream m_adminLogStream;
     std::ofstream m_authenticationLogStream;
     std::ofstream m_errorLogStream;
+    std::ofstream m_performanceLogStream;
     std::ofstream m_sessionLogStream;
     std::ofstream m_traceLogStream;
     ACE_OSTREAM_TYPE* m_outputStream;
@@ -508,6 +561,7 @@
     bool ValidateAdminLogHeader();
     bool ValidateAuthenticationLogHeader();
     bool ValidateErrorLogHeader();
+    bool ValidatePerformanceLogHeader();
     bool ValidateSessionLogHeader();
     bool ValidateTraceLogHeader();
 
@@ -566,6 +620,12 @@
     STRING m_ErrorLogFileName;
     STRING m_ErrorLogParameters;
 
+    // Performance Log
+    bool m_bPerformanceLogEnabled;
+    bool m_bPerformanceLogHeader;
+    STRING m_PerformanceLogFileName;
+    STRING m_PerformanceLogParameters;
+
     // Session Log
     bool m_bSessionLogEnabled;
     bool m_bSessionLogHeader;
@@ -587,6 +647,7 @@
     MgDateTime m_cacheAdminLogTimestamp;
     MgDateTime m_cacheAuthenticationLogTimestamp;
     MgDateTime m_cacheErrorLogTimestamp;
+    MgDateTime m_cachePerformanceLogTimestamp;
     MgDateTime m_cacheSessionLogTimestamp;
     MgDateTime m_cacheTraceLogTimestamp;
 };

Modified: trunk/MgDev/Server/src/Common/Manager/LogType.h
===================================================================
--- trunk/MgDev/Server/src/Common/Manager/LogType.h	2010-01-13 21:45:23 UTC (rev 4530)
+++ trunk/MgDev/Server/src/Common/Manager/LogType.h	2010-01-13 23:40:02 UTC (rev 4531)
@@ -26,7 +26,8 @@
     mltAuthentication,
     mltError,
     mltSession,
-    mltTrace
+    mltTrace,
+    mltPerformance
 };
 
 #endif

Modified: trunk/MgDev/Server/src/Common/Manager/ServerManager.cpp
===================================================================
--- trunk/MgDev/Server/src/Common/Manager/ServerManager.cpp	2010-01-13 21:45:23 UTC (rev 4530)
+++ trunk/MgDev/Server/src/Common/Manager/ServerManager.cpp	2010-01-13 23:40:02 UTC (rev 4531)
@@ -570,6 +570,21 @@
     }
 #endif
 
+    // Add cache information
+    MgCacheManager* cacheManager = MgCacheManager::GetInstance();
+    if(cacheManager)
+    {
+        MgFeatureServiceCache* fsCache = cacheManager->GetFeatureServiceCache();
+        INT32 fsCacheSize = fsCache->GetCacheSize();
+        INT32 fsCacheDroppedEntries = fsCache->GetDroppedEntriesCount();
+
+        pProperty = new MgInt32Property(MgServerInformationProperties::CacheSize, fsCacheSize);
+        pProperties->Add(pProperty);
+
+        pProperty = new MgInt32Property(MgServerInformationProperties::CacheDroppedEntries, fsCacheDroppedEntries);
+        pProperties->Add(pProperty);
+    }
+
     MG_CATCH_AND_THROW(L"MgServerManager.GetInformationProperties")
 
     return pProperties.Detach();

Modified: trunk/MgDev/Server/src/Core/EventTimer.h
===================================================================
--- trunk/MgDev/Server/src/Core/EventTimer.h	2010-01-13 21:45:23 UTC (rev 4530)
+++ trunk/MgDev/Server/src/Core/EventTimer.h	2010-01-13 23:40:02 UTC (rev 4531)
@@ -20,7 +20,7 @@
 
 class MgTimedEventHandler;
 
-const int MG_MAX_EVENT_TIMERS = 8;
+const int MG_MAX_EVENT_TIMERS = 9;
 
 class MgEventTimer
 {
@@ -38,6 +38,7 @@
         ResourceChange                      = 5,
         FeatureServiceCacheTimeLimit        = 6,
         DataTransactionTimeout              = 7,
+        PerformanceLogging                  = 8,
     };
 
 /// Constructors/Destructor

Modified: trunk/MgDev/Server/src/Core/Makefile.am
===================================================================
--- trunk/MgDev/Server/src/Core/Makefile.am	2010-01-13 21:45:23 UTC (rev 4530)
+++ trunk/MgDev/Server/src/Core/Makefile.am	2010-01-13 23:40:02 UTC (rev 4531)
@@ -56,6 +56,7 @@
   FeatureServiceCacheTimeLimitEventHandler.cpp \
   main.cpp \
   OperationThread.cpp \
+  PerformanceLoggingEventHandler.cpp \
   RepositoryCheckpointEventHandler.cpp \
   ResourceChangeEventHandler.cpp \
   Server.cpp \
@@ -76,6 +77,7 @@
   EventTimerManager.h \
   FeatureServiceCacheTimeLimitEventHandler.h \
   OperationThread.h \
+  PerformanceLoggingEventHandler.h \
   RepositoryCheckpointEventHandler.h \
   ResourceChangeEventHandler.h \
   Server.h \

Added: trunk/MgDev/Server/src/Core/PerformanceLoggingEventHandler.cpp
===================================================================
--- trunk/MgDev/Server/src/Core/PerformanceLoggingEventHandler.cpp	                        (rev 0)
+++ trunk/MgDev/Server/src/Core/PerformanceLoggingEventHandler.cpp	2010-01-13 23:40:02 UTC (rev 4531)
@@ -0,0 +1,89 @@
+//
+//  Copyright (C) 2004-2009 by Autodesk, Inc.
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of version 2.1 of the GNU Lesser
+//  General Public License as published by the Free Software Foundation.
+//
+//  This library 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 this library; if not, write to the Free Software
+//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+#include "MapGuideCommon.h"
+#include "PerformanceLoggingEventHandler.h"
+#include "ServiceManager.h"
+
+///////////////////////////////////////////////////////////////////////////////
+/// \brief
+/// Constructs the object.
+///
+MgPerformanceLoggingEventHandler::MgPerformanceLoggingEventHandler(MgEventTimer& timer) :
+    MgTimedEventHandler(timer)
+{
+    MgConfiguration* configuration = MgConfiguration::GetInstance();
+    ACE_ASSERT(NULL != configuration);
+    INT32 interval = MgConfigProperties::DefaultPerformanceLogPropertyInterval;
+    m_bPerformanceLogEnabled = MgConfigProperties::DefaultPerformanceLogPropertyEnabled;
+
+    if (NULL != configuration)
+    {
+        configuration->GetIntValue(
+            MgConfigProperties::PerformanceLogPropertiesSection,
+            MgConfigProperties::PerformanceLogPropertyInterval,
+            interval,
+            MgConfigProperties::DefaultPerformanceLogPropertyInterval);
+
+        configuration->GetBoolValue(
+            MgConfigProperties::PerformanceLogPropertiesSection,
+            MgConfigProperties::PerformanceLogPropertyEnabled,
+            m_bPerformanceLogEnabled,
+            MgConfigProperties::DefaultPerformanceLogPropertyEnabled);
+    }
+
+    m_timer.SetInterval(interval);
+    m_event.SetId(MgTimedEvent::PerformanceLogging);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// \brief
+/// Destructs the object.
+///
+MgPerformanceLoggingEventHandler::~MgPerformanceLoggingEventHandler()
+{
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// \brief
+/// Handles the specified event.
+///
+void MgPerformanceLoggingEventHandler::HandleEvent(long eventId)
+{
+    MG_TRY()
+
+    // Perform performance statistics logging.
+    if (MgTimedEvent::PerformanceLogging == eventId)
+    {
+        MgServerManager* serverManager = MgServerManager::GetInstance();
+        ACE_ASSERT(NULL != serverManager);
+
+        if (NULL != serverManager)
+        {
+            // We check to see if the log is enabled here as an optimization because the GetInformationProperties() API call can be expensive.
+            if(m_bPerformanceLogEnabled)
+            {
+                Ptr<MgPropertyCollection> properties = serverManager->GetInformationProperties();
+
+                // Log the statistics
+                MG_LOG_PERFORMANCE_PROPERTIES_ENTRY(properties);
+            }
+        }
+    }
+
+    MG_CATCH_AND_THROW(L"MgPerformanceLoggingEventHandler.HandleEvent")
+}

Added: trunk/MgDev/Server/src/Core/PerformanceLoggingEventHandler.h
===================================================================
--- trunk/MgDev/Server/src/Core/PerformanceLoggingEventHandler.h	                        (rev 0)
+++ trunk/MgDev/Server/src/Core/PerformanceLoggingEventHandler.h	2010-01-13 23:40:02 UTC (rev 4531)
@@ -0,0 +1,59 @@
+//
+//  Copyright (C) 2004-2009 by Autodesk, Inc.
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of version 2.1 of the GNU Lesser
+//  General Public License as published by the Free Software Foundation.
+//
+//  This library 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 this library; if not, write to the Free Software
+//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+#ifndef MGPERFORMANCELOGGINGEVENTHANDLER_H_
+#define MGPERFORMANCELOGGINGEVENTHANDLER_H_
+
+#include "TimedEventHandler.h"
+
+///////////////////////////////////////////////////////////////////////////////
+/// \brief
+/// Derived Event Handler class to perform performance logging.
+///
+class MgPerformanceLoggingEventHandler : public MgTimedEventHandler
+{
+/// Constructors/Destructor
+
+public:
+
+    MgPerformanceLoggingEventHandler(MgEventTimer& timer);
+    virtual ~MgPerformanceLoggingEventHandler();
+
+private:
+
+    // Unimplemented Constructors/Methods
+
+    MgPerformanceLoggingEventHandler();
+    MgPerformanceLoggingEventHandler(const MgPerformanceLoggingEventHandler&);
+    MgPerformanceLoggingEventHandler& operator=(const MgPerformanceLoggingEventHandler&);
+
+/// Methods
+
+protected:
+
+    virtual void HandleEvent(long eventId);
+
+/// Data Members
+
+private:
+    bool m_bPerformanceLogEnabled;
+
+};
+
+/// Inline Methods
+
+#endif

Modified: trunk/MgDev/Server/src/Core/Server.cpp
===================================================================
--- trunk/MgDev/Server/src/Core/Server.cpp	2010-01-13 21:45:23 UTC (rev 4530)
+++ trunk/MgDev/Server/src/Core/Server.cpp	2010-01-13 23:40:02 UTC (rev 4531)
@@ -168,6 +168,7 @@
     ACE_DEBUG ((LM_INFO, ACE_TEXT("(%t) %W\n"), message.c_str()));
     MG_LOG_SYSTEM_ENTRY(LM_INFO, message.c_str());
     MG_LOG_ERROR_ENTRY(message.c_str());
+    MG_LOG_PERFORMANCE_STRING_ENTRY(message.c_str());
     MG_LOG_TRACE_ENTRY(L"MgServer::fini() - End");
 
 #ifdef _WIN32
@@ -534,6 +535,7 @@
                             ACE_DEBUG ((LM_INFO, ACE_TEXT("(%t) %W\n"), message.c_str()));
                             MG_LOG_SYSTEM_ENTRY(LM_INFO, message.c_str());
                             MG_LOG_ERROR_ENTRY(message.c_str());
+                            MG_LOG_PERFORMANCE_STRING_ENTRY(message.c_str());
 
                             // Start up the thread pools
                             nResult = clientThreads.Activate();

Modified: trunk/MgDev/Server/src/Core/ServerCore.vcproj
===================================================================
--- trunk/MgDev/Server/src/Core/ServerCore.vcproj	2010-01-13 21:45:23 UTC (rev 4530)
+++ trunk/MgDev/Server/src/Core/ServerCore.vcproj	2010-01-13 23:40:02 UTC (rev 4531)
@@ -620,6 +620,46 @@
 				>
 			</File>
 			<File
+				RelativePath=".\PerformanceLoggingEventHandler.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Debug|x64"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|x64"
+					ExcludedFromBuild="true"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath=".\PerformanceLoggingEventHandler.h"
+				>
+			</File>
+			<File
 				RelativePath=".\RepositoryCheckpointEventHandler.cpp"
 				>
 				<FileConfiguration

Modified: trunk/MgDev/Server/src/Core/ServerCoreBuild.cpp
===================================================================
--- trunk/MgDev/Server/src/Core/ServerCoreBuild.cpp	2010-01-13 21:45:23 UTC (rev 4530)
+++ trunk/MgDev/Server/src/Core/ServerCoreBuild.cpp	2010-01-13 23:40:02 UTC (rev 4531)
@@ -24,6 +24,7 @@
 #include "FeatureServiceCacheTimeLimitEventHandler.cpp"
 #include "main.cpp"
 #include "OperationThread.cpp"
+#include "PerformanceLoggingEventHandler.cpp"
 #include "RepositoryCheckpointEventHandler.cpp"
 #include "ResourceChangeEventHandler.cpp"
 #include "Server.cpp"

Modified: trunk/MgDev/Server/src/Core/TimedEvent.h
===================================================================
--- trunk/MgDev/Server/src/Core/TimedEvent.h	2010-01-13 21:45:23 UTC (rev 4530)
+++ trunk/MgDev/Server/src/Core/TimedEvent.h	2010-01-13 23:40:02 UTC (rev 4531)
@@ -34,6 +34,7 @@
         ResourceChange                      = 60,
         FeatureServiceCacheTimeLimit        = 70,
         DataTransactionTimeout              = 80,
+        PerformanceLogging                  = 90,
     };
 
 /// Constructors/Destructor

Modified: trunk/MgDev/Server/src/Core/TimedEventHandler.cpp
===================================================================
--- trunk/MgDev/Server/src/Core/TimedEventHandler.cpp	2010-01-13 21:45:23 UTC (rev 4530)
+++ trunk/MgDev/Server/src/Core/TimedEventHandler.cpp	2010-01-13 23:40:02 UTC (rev 4531)
@@ -90,6 +90,10 @@
             eventHandler.reset(new MgDataTransactionTimeoutEventHandler(timer));
             break;
 
+        case MgEventTimer::PerformanceLogging:
+            eventHandler.reset(new MgPerformanceLoggingEventHandler(timer));
+            break;
+
         default:
             throw new MgInvalidArgumentException(
                 L"MgTimedEventHandler.Create", __LINE__, __WFILE__, NULL, L"", NULL);

Modified: trunk/MgDev/Server/src/Core/serverconfig.ini
===================================================================
--- trunk/MgDev/Server/src/Core/serverconfig.ini	2010-01-13 21:45:23 UTC (rev 4530)
+++ trunk/MgDev/Server/src/Core/serverconfig.ini	2010-01-13 23:40:02 UTC (rev 4531)
@@ -478,6 +478,23 @@
 Filename                           = "Error.log"
 Parameters                         = CLIENT,CLIENTIP,USER,ERROR,STACKTRACE
 
+[PerformanceLogProperties]
+# *****************************************************************************
+# P E R F O R M A N C E   L O G
+#
+# Property Name                    Description
+# -----------------------------------------------------------------------------
+# Enabled                          0 = log disabled, 1 = log enabled
+# Filename                         Name of the log file
+# Parameters                       Log parameters
+# Interval                         Time interval in seconds for when the server
+#                                  writes the performance information to the log
+# *****************************************************************************
+Enabled                            = 0
+Filename                           = "Performance.log"
+Parameters                         = ADMINOPQCOUNT,CLIENTOPQCOUNT,SITEOPQCOUNT,AVGOPTIME,CPU,WORKINGSET,VIRTUALMEMORY,TOTALOPTIME,TOTALACTIVECONNECTIONS,TOTALCONNECTIONS,TOTALPROCESSEDOP,TOTALRECEIVEDOP,UPTIME, CACHESIZE, CACHEDROPPEDENTRIES
+Interval                           = 300
+
 [SessionLogProperties]
 # *****************************************************************************
 # S E S S I O N  L O G



More information about the mapguide-commits mailing list