diff --git a/src/classes/logstream.class.php b/src/classes/logstream.class.php index 344b9b8..922292e 100644 --- a/src/classes/logstream.class.php +++ b/src/classes/logstream.class.php @@ -27,10 +27,6 @@ * * A copy of the GPL can be found in the file "COPYING" in this * distribution. - * - * Adiscon LogAnalyzer is also available under a commercial license. - * For details, contact info@adiscon.com or visit - * http://loganalyzer.adiscon.com/commercial ********************************************************************* */ @@ -212,7 +208,7 @@ abstract class LogStream { * * @return integer Error stat */ - public abstract function ConsolidateDataByField($szConsFieldId, $nRecordLimit, $szSortFieldId, $nSortingOrder, $bIncludeLogStreamFields = false); + public abstract function ConsolidateDataByField($szConsFieldId, $nRecordLimit, $szSortFieldId, $nSortingOrder, $bIncludeLogStreamFields = false, $bIncludeMinMaxDateFields = false); /** @@ -257,6 +253,71 @@ abstract class LogStream { public abstract function SaveMessageChecksum( $arrProperitesIn ); + /* + * Helper function to set the checksum for all messages in the current logstream class + */ + public abstract function UpdateAllMessageChecksum( ); + + + /* + * Helper function for logstream classes to clear filter based stuff + */ + public abstract function ResetFilters( ); + + + /* + * Helper function for logstream classes to check if all fields are available! + */ + public abstract function VerifyFields( $arrProperitesIn ); + + + /* + * Helper function for logstream classes to create missing indexes, only applies to database based logstream classes + */ + public abstract function CreateMissingFields( $arrProperitesIn ); + + + /* + * Helper function for logstream classes to check for data indexes, only applies to database based logstream classes + */ + public abstract function VerifyIndexes( $arrProperitesIn ); + + + /* + * Helper function for logstream classes to create missing indexes, only applies to database based logstream classes + */ + public abstract function CreateMissingIndexes( $arrProperitesIn ); + + + /* + * Helper function for logstream classes to check for missing triggers, only applies to database based logstream classes + */ + public abstract function VerifyChecksumTrigger( $myTriggerProperty ); + + + /* + * Helper function for logstream classes to create missing trigger, only applies to database based logstream classes + */ + public abstract function CreateMissingTrigger( $myTriggerProperty, $myCheckSumProperty ); + + + /* + * Helper function for logstream classes to create the SQL statement needed to create the trigger, only applies to database based logstream classes + */ + public abstract function GetCreateMissingTriggerSQL( $myDBTriggerField, $myDBTriggerCheckSumField ); + + /* + * Helper function for logstream classes to check if the checksum field is configured correctly + */ + public abstract function VerifyChecksumField( ); + + + /* + * Helper function for logstream classes to change the checksum field from unsigned INT + */ + public abstract function ChangeChecksumFieldUnsigned( ); + + /* * Helper functino to trigger initialisation of MsgParsers */ @@ -279,8 +340,11 @@ abstract class LogStream { else $finalfilters = $szFilters; - OutputDebugMessage("SetFilter combined = '" . $finalfilters . "'. ", DEBUG_DEBUG); + OutputDebugMessage("LogStream|SetFilter: SetFilter combined = '" . $finalfilters . "'. ", DEBUG_DEBUG); + // Reset Filters first to make sure we do not add multiple filters! + $this->_filters = null; + // Parse Filters from string $this->ParseFilters($finalfilters); @@ -590,6 +654,23 @@ abstract class LogStream { return null; } + /* + * Helper function to get the internal Field ID by database field name! + */ + public function GetFieldIDbyDatabaseMapping($szTableType, $szFieldName) + { + global $content, $dbmapping; + + foreach( $dbmapping[$szTableType]['DBMAPPINGS'] as $myFieldID => $myDBMapping ) + { + if ( $myDBMapping == $szFieldName ) + return $myFieldID; + } + + // Default return! + return $szFieldName; + } + /* * --- PIRVATE HELPERS! */ @@ -1188,7 +1269,5 @@ abstract class LogStream { return -1; } - - } ?> \ No newline at end of file diff --git a/src/classes/logstreamconfig.class.php b/src/classes/logstreamconfig.class.php index bfc0429..bf66574 100644 --- a/src/classes/logstreamconfig.class.php +++ b/src/classes/logstreamconfig.class.php @@ -27,10 +27,6 @@ * * A copy of the GPL can be found in the file "COPYING" in this * distribution. - * - * Adiscon LogAnalyzer is also available under a commercial license. - * For details, contact info@adiscon.com or visit - * http://loganalyzer.adiscon.com/commercial ********************************************************************* */ diff --git a/src/classes/logstreamconfigdb.class.php b/src/classes/logstreamconfigdb.class.php index 1dd8104..003f174 100644 --- a/src/classes/logstreamconfigdb.class.php +++ b/src/classes/logstreamconfigdb.class.php @@ -27,10 +27,6 @@ * * A copy of the GPL can be found in the file "COPYING" in this * distribution. - * - * Adiscon LogAnalyzer is also available under a commercial license. - * For details, contact info@adiscon.com or visit - * http://loganalyzer.adiscon.com/commercial ********************************************************************* */ diff --git a/src/classes/logstreamconfigdisk.class.php b/src/classes/logstreamconfigdisk.class.php index b0af9d3..a4b5ad6 100644 --- a/src/classes/logstreamconfigdisk.class.php +++ b/src/classes/logstreamconfigdisk.class.php @@ -27,10 +27,6 @@ * * A copy of the GPL can be found in the file "COPYING" in this * distribution. - * - * Adiscon LogAnalyzer is also available under a commercial license. - * For details, contact info@adiscon.com or visit - * http://loganalyzer.adiscon.com/commercial ********************************************************************* */ diff --git a/src/classes/logstreamconfigpdo.class.php b/src/classes/logstreamconfigpdo.class.php index 23e898a..7ae4f9c 100644 --- a/src/classes/logstreamconfigpdo.class.php +++ b/src/classes/logstreamconfigpdo.class.php @@ -27,10 +27,6 @@ * * A copy of the GPL can be found in the file "COPYING" in this * distribution. - * - * Adiscon LogAnalyzer is also available under a commercial license. - * For details, contact info@adiscon.com or visit - * http://loganalyzer.adiscon.com/commercial ********************************************************************* */ @@ -68,6 +64,35 @@ class LogStreamConfigPDO extends LogStreamConfig { return new LogStreamPDO($o); } + + public function GetPDOTriggersSupported() + { + // TRIGGERS are not supported for all db engines! + switch ($this->DBType) + { + case DB_MYSQL: + return true; + case DB_MSSQL: + return true; + case DB_ODBC: + return false; + case DB_PGSQL: + return true; + case DB_OCI: + return false; + case DB_DB2: + return false; + case DB_FIREBIRD: + return false; + case DB_INFORMIX: + return false; + case DB_SQLITE: + return false; + default: + return false; + } + } + public function GetPDODatabaseType() { switch ($this->DBType) diff --git a/src/classes/logstreamdb.class.php b/src/classes/logstreamdb.class.php index 513628d..3684fde 100644 --- a/src/classes/logstreamdb.class.php +++ b/src/classes/logstreamdb.class.php @@ -32,10 +32,6 @@ * * A copy of the GPL can be found in the file "COPYING" in this * distribution. - * - * Adiscon LogAnalyzer is also available under a commercial license. - * For details, contact info@adiscon.com or visit - * http://loganalyzer.adiscon.com/commercial ********************************************************************* */ @@ -116,6 +112,15 @@ class LogStreamDB extends LogStream { return SUCCESS; } + /* + * Helper function to clear the current querystring! + */ + public function ResetFilters() + { + // Clear _SQLwhereClause variable! + $this->_SQLwhereClause = ""; + } + /** * Close the database connection. * @@ -176,6 +181,313 @@ class LogStreamDB extends LogStream { return SUCCESS; } + + /* + * Implementation of VerifyFields: Checks if fields exist in table + */ + public function VerifyFields( $arrProperitesIn ) + { + global $dbmapping, $fields; + + // Get List of Indexes as Array + $arrFieldKeys = $this->GetFieldsAsArray(); + $szTableType = $this->_logStreamConfigObj->DBTableType; + + // Loop through all fields to see which one is missing! + foreach ( $arrProperitesIn as $myproperty ) + { +// echo $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] . "
"; + if ( isset($dbmapping[$szTableType]['DBMAPPINGS'][$myproperty]) && in_array($dbmapping[$szTableType]['DBMAPPINGS'][$myproperty], $arrFieldKeys) ) + { + OutputDebugMessage("LogStreamDB|VerifyFields: Found Field for '" . $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] . "'", DEBUG_ULTRADEBUG); + continue; + } + else + { + // Index is missing for this field! + OutputDebugMessage("LogStreamDB|VerifyFields: Missing Field for '" . $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] . "'", DEBUG_WARN); + return ERROR_DB_DBFIELDNOTFOUND; + } + } + + // Successfull + return SUCCESS; + } + + + /* + * Implementation of VerifyIndexes: Checks if indexes exist for desired fields + */ + public function VerifyIndexes( $arrProperitesIn ) + { + global $dbmapping, $fields; + + // Get List of Indexes as Array + $arrIndexKeys = $this->GetIndexesAsArray(); + $szTableType = $this->_logStreamConfigObj->DBTableType; + + // Loop through all fields to see which one is missing! + foreach ( $arrProperitesIn as $myproperty ) + { +// echo $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] . "
"; + if ( isset($dbmapping[$szTableType]['DBMAPPINGS'][$myproperty]) && in_array($dbmapping[$szTableType]['DBMAPPINGS'][$myproperty], $arrIndexKeys) ) + { + OutputDebugMessage("LogStreamDB|VerifyIndexes: Found INDEX for '" . $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] . "'", DEBUG_ULTRADEBUG); + continue; + } + else + { + // Index is missing for this field! + OutputDebugMessage("LogStreamDB|VerifyIndexes: Missing INDEX for '" . $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] . "'", DEBUG_WARN); + return ERROR_DB_INDEXESMISSING; + } + } + + // Successfull + return SUCCESS; + } + + + /* + * Implementation of VerifyChecksumTrigger: Checks if checksum trigger exists + */ + public function VerifyChecksumTrigger( $myTriggerProperty ) + { + global $dbmapping, $fields; + + // Get List of Triggers as Array + $arrIndexTriggers = $this->GetTriggersAsArray(); + + $szTableType = $this->_logStreamConfigObj->DBTableType; + $szDBName = $this->_logStreamConfigObj->DBName; + $szTableName = $this->_logStreamConfigObj->DBTableName; + $szDBTriggerField = $dbmapping[$szTableType]['DBMAPPINGS'][$myTriggerProperty]; + + // Create Triggername + $szTriggerName = $szDBName . "_" . $szTableName . "_" . $szDBTriggerField; + + // Try to find logstream trigger + if ( count($arrIndexTriggers) > 0 ) + { + if ( in_array($szTriggerName, $arrIndexTriggers) ) + return SUCCESS; + else + { + // Index is missing for this field! + OutputDebugMessage("LogStreamDB|VerifyChecksumTrigger: Missing TRIGGER '" . $szTriggerName . "' for Table '" . $szTableName . "'", DEBUG_WARN); + return ERROR_DB_TRIGGERMISSING; + } + } + else + { + // Index is missing for this field! + OutputDebugMessage("LogStreamDB|VerifyChecksumTrigger: No TRIGGERS found in your database", DEBUG_WARN); + return ERROR_DB_TRIGGERMISSING; + } + } + + + /* + * Implementation of CreateMissingIndexes: Checks if indexes exist for desired fields + */ + public function CreateMissingIndexes( $arrProperitesIn ) + { + global $dbmapping, $fields, $querycount; + + // Get List of Indexes as Array + $arrIndexKeys = $this->GetIndexesAsArray(); + $szTableType = $this->_logStreamConfigObj->DBTableType; + + // Loop through all fields to see which one is missing! + foreach ( $arrProperitesIn as $myproperty ) + { + if ( isset($dbmapping[$szTableType]['DBMAPPINGS'][$myproperty]) && in_array($dbmapping[$szTableType]['DBMAPPINGS'][$myproperty], $arrIndexKeys) ) + continue; + else + { + // Update Table schema now! + $szSql = "ALTER TABLE " . $this->_logStreamConfigObj->DBTableName . " ADD INDEX ( " . $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] . " )"; + + // Index is missing for this field! + OutputDebugMessage("LogStreamDB|CreateMissingIndexes: Createing missing INDEX for '" . $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] . "' - " . $szSql, DEBUG_INFO); + + // Add missing INDEX now! + $myQuery = mysql_query($szSql, $this->_dbhandle); + if (!$myQuery) + { + // Return failure! + $this->PrintDebugError("Dynamically Adding INDEX for '" . $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] . "' failed with Statement: '" . $szSql . "'"); + return ERROR_DB_INDEXFAILED; + } + } + } + + // Successfull + return SUCCESS; + } + + + /* + * Implementation of CreateMissingFields: Checks if indexes exist for desired fields + */ + public function CreateMissingFields( $arrProperitesIn ) + { + global $dbmapping, $fields, $querycount; + + // Get List of Indexes as Array + $arrFieldKeys = $this->GetFieldsAsArray(); + $szTableType = $this->_logStreamConfigObj->DBTableType; + + // Loop through all fields to see which one is missing! + foreach ( $arrProperitesIn as $myproperty ) + { + if ( isset($dbmapping[$szTableType]['DBMAPPINGS'][$myproperty]) && in_array($dbmapping[$szTableType]['DBMAPPINGS'][$myproperty], $arrFieldKeys) ) + continue; + else + { + if ( $this->HandleMissingField( $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty], $arrProperitesIn ) == SUCCESS ) + { + // Index is missing for this field! + OutputDebugMessage("LogStreamDB|CreateMissingFields: Createing missing FIELD for '" . $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty], DEBUG_INFO); + } + else + { + // Return failure! + $this->PrintDebugError("Dynamically Adding FIELD for '" . $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] . "' failed!"); + return ERROR_DB_ADDDBFIELDFAILED; + } + } + } + + // Successfull + return SUCCESS; + } + + + /* + * Implementation of GetCreateMissingTriggerSQL: Creates SQL needed to create a TRIGGER + */ + public function GetCreateMissingTriggerSQL( $myDBTriggerField, $myDBTriggerCheckSumField ) + { + global $dbmapping, $fields, $querycount; + + // Get List of Triggers as Array + $szDBName = $this->_logStreamConfigObj->DBName; + $szTableName = $this->_logStreamConfigObj->DBTableName; + + // Create Triggername + $szTriggerName = $szDBName . "_" . $szTableName . "_" . $myDBTriggerField; + + // Create TRIGGER SQL! + $szSql = "CREATE TRIGGER " . $szTriggerName . " BEFORE INSERT ON `" . $szTableName . "` + FOR EACH ROW + BEGIN + SET NEW." . $myDBTriggerCheckSumField . " = crc32(NEW." . $myDBTriggerField . "); + END + ;"; + + return $szSql; + } + + + /* + * Implementation of CreateMissingTrigger: Creates missing triggers ! + */ + public function CreateMissingTrigger( $myTriggerProperty, $myCheckSumProperty ) + { + global $dbmapping, $fields, $querycount; + + // Get List of Triggers as Array + $szTableName = $this->_logStreamConfigObj->DBTableName; + $szTableType = $this->_logStreamConfigObj->DBTableType; + $szDBTriggerField = $dbmapping[$szTableType]['DBMAPPINGS'][$myTriggerProperty]; + $szDBTriggerCheckSumField = $dbmapping[$szTableType]['DBMAPPINGS'][$myCheckSumProperty]; + + // Get SQL Code to create the trigger! + $szSql = $this->GetCreateMissingTriggerSQL( $szDBTriggerField, $szDBTriggerCheckSumField ); + + // Index is missing for this field! + OutputDebugMessage("LogStreamDB|CreateMissingTrigger: Creating missing TRIGGER for '" . $szTableName . "' - $szDBTriggerCheckSumField = crc32(NEW.$szDBTriggerField)" . $szSql, DEBUG_INFO); + + // Add missing INDEX now! + $myQuery = mysql_query($szSql, $this->_dbhandle); + if (!$myQuery) + { + // Return failure! + $this->PrintDebugError("Dynamically Adding TRIGGER for '" . $szTableName . "' failed!

If you want to manually add the TRIGGER, use the following SQL Command:
" . str_replace("\n", "
", $szSql) . "
"); + + return ERROR_DB_TRIGGERFAILED; + } + + // Successfull + return SUCCESS; + } + + + /* + * Implementation of ChangeChecksumFieldUnsigned: Changes the Checkusm field to unsigned! + */ + public function ChangeChecksumFieldUnsigned() + { + global $dbmapping, $fields, $querycount; + + // Get variables + $szTableType = $this->_logStreamConfigObj->DBTableType; + + // Change Checksumfield to use UNSIGNED! + $szUpdateSql = "ALTER TABLE `" . $this->_logStreamConfigObj->DBTableName . "` CHANGE `" . + $dbmapping[$szTableType]['DBMAPPINGS'][MISC_CHECKSUM] . "` `" . + $dbmapping[$szTableType]['DBMAPPINGS'][MISC_CHECKSUM] . "` INT(11) UNSIGNED NOT NULL DEFAULT '0'"; + + // Update Table schema now! + $myQuery = mysql_query($szUpdateSql, $this->_dbhandle); + if (!$myQuery) + { + // Return failure! + $this->PrintDebugError("ER_BAD_FIELD_ERROR - Failed to Change field '" . $dbmapping[$szTableType]['DBMAPPINGS'][MISC_CHECKSUM] . "' from signed to unsigned with sql statement: '" . $szUpdateSql . "'"); + return ERROR_DB_CHECKSUMCHANGEFAILED; + } + + // return results + return SUCCESS; + } + + + /* + * Implementation of VerifyChecksumField: Verifies if the checkusm field is signed or unsigned! + */ + public function VerifyChecksumField() + { + global $dbmapping, $fields, $querycount; + + // Get variables + $szTableType = $this->_logStreamConfigObj->DBTableType; + + // Create SQL and Get INDEXES for table! + $szSql = "SHOW COLUMNS FROM " . $this->_logStreamConfigObj->DBTableName . " WHERE Field = '" . $dbmapping[$szTableType]['DBMAPPINGS'][MISC_CHECKSUM] . "'"; + $myQuery = mysql_query($szSql, $this->_dbhandle); + if ($myQuery) + { + // Get result! + $myRow = mysql_fetch_array($myQuery, MYSQL_ASSOC); + if (strpos( strtolower($myRow['Type']), "unsigned") === false ) + { + // return error code! + return ERROR_DB_CHECKSUMERROR; + } + + // Free query now + mysql_free_result ($myQuery); + + // Increment for the Footer Stats + $querycount++; + } + + // return results + return SUCCESS; + } + + /** * Read the data from a specific uID which means in this * case beginning with from the Database ID @@ -618,6 +930,46 @@ class LogStreamDB extends LogStream { return $rowcount; } + + /* + * Implementation of the UpdateAllMessageChecksum + * + * Update all missing checksum properties in the current database + */ + public function UpdateAllMessageChecksum( ) + { + global $querycount, $dbmapping; + $szTableType = $this->_logStreamConfigObj->DBTableType; + + // UPDATE DATA NOW! + $szSql = "UPDATE " . $this->_logStreamConfigObj->DBTableName . + " SET " . $dbmapping[$szTableType]['DBMAPPINGS'][MISC_CHECKSUM] . " = crc32(" . $dbmapping[$szTableType]['DBMAPPINGS'][SYSLOG_MESSAGE] . ") " . + " WHERE " . $dbmapping[$szTableType]['DBMAPPINGS'][MISC_CHECKSUM] . " IS NULL OR " . $dbmapping[$szTableType]['DBMAPPINGS'][MISC_CHECKSUM] . " = 0"; + + // Output Debug Informations + OutputDebugMessage("LogStreamDB|UpdateAllMessageChecksum: Running Created SQL Query:
" . $szSql, DEBUG_ULTRADEBUG); + + // Running SQL Query + $myQuery = mysql_query($szSql, $this->_dbhandle); + if ($myQuery) + { + // Debug Output + OutputDebugMessage("LogStreamDB|UpdateAllMessageChecksum: Successfully updated Checksum of '" . mysql_affected_rows($this->_dbhandle) . "' datarecords", DEBUG_INFO); + + // Return success + return SUCCESS; + } + else + { + // error occured, output DEBUG message + $this->PrintDebugError("SaveMessageChecksum failed with SQL Statement ' " . $szSql . " '"); + + // Failed + return ERROR; + } + } + + /* * Implementation of the SaveMessageChecksum * @@ -630,16 +982,13 @@ class LogStreamDB extends LogStream { if ( isset($arrProperitesIn[SYSLOG_UID]) && isset($arrProperitesIn[MISC_CHECKSUM]) && isset($dbmapping[$szTableType]['DBMAPPINGS'][MISC_CHECKSUM]) ) { - // DELETE DATA NOW! + // UPDATE DATA NOW! $szSql = "UPDATE " . $this->_logStreamConfigObj->DBTableName . " SET " . $dbmapping[$szTableType]['DBMAPPINGS'][MISC_CHECKSUM] . " = " . $arrProperitesIn[MISC_CHECKSUM] . " WHERE " . $dbmapping[$szTableType]['DBMAPPINGS'][SYSLOG_UID] . " = " . $arrProperitesIn[SYSLOG_UID]; $myQuery = mysql_query($szSql, $this->_dbhandle); if ($myQuery) { - // Free res! - // NOT NEEDED HERE! mysql_free_result($myQuery); - // Return success return SUCCESS; } @@ -692,7 +1041,7 @@ class LogStreamDB extends LogStream { // Set Sorted Field if ( $szConsFieldId == $szSortFieldId ) - $myDBSortedFieldName = "ItemCount"; + $myDBSortedFieldName = "itemcount"; else $myDBSortedFieldName = $szSortFieldId; // --- @@ -722,13 +1071,16 @@ class LogStreamDB extends LogStream { // Create SQL String now! $szSql = "SELECT " . $myDBQueryFields . - "count(" . $myDBConsFieldName . ") as ItemCount " . + "count(" . $myDBConsFieldName . ") as itemcount " . " FROM " . $this->_logStreamConfigObj->DBTableName . $this->_SQLwhereClause . " GROUP BY " . $myDBGroupByFieldName . " ORDER BY " . $myDBSortedFieldName . " " . $szSortingOrder . $szLimitSql ; + // Output Debug Informations + OutputDebugMessage("LogStreamDB|ConsolidateItemListByField: Running Created SQL Query:
" . $szSql, DEBUG_ULTRADEBUG); + // Perform Database Query $myquery = mysql_query($szSql, $this->_dbhandle); if ( !$myquery ) @@ -770,7 +1122,7 @@ class LogStreamDB extends LogStream { * * @return integer Error stat */ - public function ConsolidateDataByField($szConsFieldId, $nRecordLimit, $szSortFieldId, $nSortingOrder, $aIncludeCustomFields = null, $bIncludeLogStreamFields = false) + public function ConsolidateDataByField($szConsFieldId, $nRecordLimit, $szSortFieldId, $nSortingOrder, $aIncludeCustomFields = null, $bIncludeLogStreamFields = false, $bIncludeMinMaxDateFields = false) { global $content, $dbmapping, $fields; @@ -819,13 +1171,20 @@ class LogStreamDB extends LogStream { } else // Only Include ConsolidateField $myDBQueryFields = $myDBConsFieldName . ", "; - + + // Add Min and Max fields for DATE if desired + if ( $bIncludeMinMaxDateFields ) + { + $myDBQueryFields .= "Min(" . $dbmapping[$szTableType]['DBMAPPINGS'][SYSLOG_DATE] . ") as firstoccurrence_date, "; + $myDBQueryFields .= "Max(" . $dbmapping[$szTableType]['DBMAPPINGS'][SYSLOG_DATE] . ") as lastoccurrence_date, "; + } + if ( $szConsFieldId == $szSortFieldId ) - $myDBSortedFieldName = "ItemCount"; + $myDBSortedFieldName = "itemcount"; else $myDBSortedFieldName = $szSortFieldId; // --- - + // Special handling for date fields if ( $nConsFieldType == FILTER_TYPE_DATE ) { @@ -841,7 +1200,7 @@ class LogStreamDB extends LogStream { $szLimitSql = ""; // Create SQL Where Clause! - if ( $this->_SQLwhereClause == "" ) + if ( strlen($this->_SQLwhereClause) <= 0 ) { $res = $this->CreateSQLWhereClause(); if ( $res != SUCCESS ) @@ -851,18 +1210,21 @@ class LogStreamDB extends LogStream { // Create SQL String now! $szSql = "SELECT " . $myDBQueryFields . - "count(" . $myDBConsFieldName . ") as ItemCount " . + "count(" . $myDBConsFieldName . ") as itemcount " . " FROM " . $this->_logStreamConfigObj->DBTableName . $this->_SQLwhereClause . " GROUP BY " . $myDBGroupByFieldName . " ORDER BY " . $myDBSortedFieldName . " " . $szSortingOrder . $szLimitSql ; + // Output Debug Informations + OutputDebugMessage("LogStreamDB|ConsolidateDataByField: Running Created SQL Query:
" . $szSql, DEBUG_ULTRADEBUG); + // Perform Database Query $myquery = mysql_query($szSql, $this->_dbhandle); if ( !$myquery ) return ERROR_DB_QUERYFAILED; - + // Initialize Array variable $aResult = array(); @@ -874,12 +1236,17 @@ class LogStreamDB extends LogStream { foreach ( $myRow as $myFieldName => $myFieldValue ) { - if ( $myFieldName == $dbmapping[$szTableType]['DBMAPPINGS'][$szConsFieldId] ) + $myFieldID = $this->GetFieldIDbyDatabaseMapping($szTableType, $myFieldName); + $aNewRow[ $myFieldID ] = $myFieldValue; + +/* if ( $myFieldName == $dbmapping[$szTableType]['DBMAPPINGS'][$szConsFieldId] ) $aNewRow[$szConsFieldId] = $myFieldValue; else + { $aNewRow[$myFieldName] = $myFieldValue; +*/ +// } } - // Add new row to result $aResult[] = $aNewRow; } @@ -891,7 +1258,6 @@ class LogStreamDB extends LogStream { return ERROR_NOMORERECORDS; } - /** * Implementation of GetCountSortedByField * @@ -965,6 +1331,7 @@ class LogStreamDB extends LogStream { } + /* * ============= Beginn of private functions ============= */ @@ -1503,58 +1870,190 @@ class LogStreamDB extends LogStream { /* * Function handles missing database fields automatically! */ - private function HandleMissingField() + private function HandleMissingField( $szMissingField = null, $arrProperties = null ) { global $dbmapping, $fields; // Get Err description $errdesc = mysql_error(); - - // check matching of error msg! - if ( preg_match("/Unknown column '(.*?)' in '(.*?)'$/", $errdesc, $errOutArr ) ) + + // Try to get missing field from SQL Error of not specified as argument + if ( $szMissingField == null ) { - $szTableType = $this->_logStreamConfigObj->DBTableType; - - // Loop through all fields to see which one is missing! - foreach ( $this->_arrProperties as $myproperty ) + if ( preg_match("/Unknown column '(.*?)' in '(.*?)'$/", $errdesc, $errOutArr ) ) + $szMissingField = $errOutArr[1]; + else { - if ( isset($dbmapping[$szTableType]['DBMAPPINGS'][$myproperty]) && $errOutArr[1] == $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] ) - { - // Create SQL Numeric field - $szUpdateSql = ""; - if ( $fields[$myproperty]['FieldType'] == FILTER_TYPE_NUMBER ) - $szUpdateSql = "ALTER TABLE `" . $this->_logStreamConfigObj->DBTableName . "` ADD `" . $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] . "` int(11) NOT NULL DEFAULT '0'"; - if ( $fields[$myproperty]['FieldType'] == FILTER_TYPE_STRING ) - $szUpdateSql = "ALTER TABLE `" . $this->_logStreamConfigObj->DBTableName . "` ADD `" . $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] . "` varchar(60) NOT NULL DEFAULT ''"; - if ( $fields[$myproperty]['FieldType'] == FILTER_TYPE_DATE ) - $szUpdateSql = "ALTER TABLE `" . $this->_logStreamConfigObj->DBTableName . "` ADD `" . $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] . "` datetime NOT NULL DEFAULT '0000-00-00 00:00:00'"; + $this->PrintDebugError("ER_BAD_FIELD_ERROR - SQL Statement: ". $errdesc); + return ERROR_DB_DBFIELDNOTFOUND; + } + } - if ( strlen($szUpdateSql) > 0 ) - { - // Update Table schema now! - $myQuery = mysql_query($szUpdateSql, $this->_dbhandle); - if (!$myQuery) - { - // Return failure! - $this->PrintDebugError("ER_BAD_FIELD_ERROR - Dynamically Adding field '" . $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] . "' with Statement failed: '" . $szUpdateSql . "'"); - return ERROR_DB_DBFIELDNOTFOUND; - } - } - else + // Set Properties to default if NULL + if ( $arrProperties == null ) + $arrProperties = $this->_arrProperties; + + // Get Tabletype + $szTableType = $this->_logStreamConfigObj->DBTableType; + + // Loop through all fields to see which one is missing! + foreach ( $arrProperties as $myproperty ) + { + if ( isset($dbmapping[$szTableType]['DBMAPPINGS'][$myproperty]) && $szMissingField == $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] ) + { + // Create SQL Numeric field + $szUpdateSql = ""; $szUnsigned = ""; + if ( $fields[$myproperty]['FieldType'] == FILTER_TYPE_NUMBER ) + { + // This will add the checksum field as unsigned automatically! + if ( $myproperty == MISC_CHECKSUM ) + $szUnsigned = "UNSIGNED"; + $szUpdateSql = "ALTER TABLE `" . $this->_logStreamConfigObj->DBTableName . "` ADD `" . $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] . "` int(11) " . $szUnsigned . " NOT NULL DEFAULT '0'"; + } + if ( $fields[$myproperty]['FieldType'] == FILTER_TYPE_STRING ) + $szUpdateSql = "ALTER TABLE `" . $this->_logStreamConfigObj->DBTableName . "` ADD `" . $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] . "` varchar(60) NOT NULL DEFAULT ''"; + if ( $fields[$myproperty]['FieldType'] == FILTER_TYPE_DATE ) + $szUpdateSql = "ALTER TABLE `" . $this->_logStreamConfigObj->DBTableName . "` ADD `" . $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] . "` datetime NOT NULL DEFAULT '0000-00-00 00:00:00'"; + + if ( strlen($szUpdateSql) > 0 ) + { + // Update Table schema now! + $myQuery = mysql_query($szUpdateSql, $this->_dbhandle); + if (!$myQuery) { // Return failure! - $this->PrintDebugError("ER_BAD_FIELD_ERROR - Field '" . $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] . "' is missing has to be added manually to the database layout!'"); - return ERROR_DB_DBFIELDNOTFOUND; + $this->PrintDebugError("ER_BAD_FIELD_ERROR - Dynamically Adding field '" . $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] . "' with Statement failed: '" . $szUpdateSql . "'"); + return ERROR_DB_ADDDBFIELDFAILED; } } + else + { + // Return failure! + $this->PrintDebugError("ER_BAD_FIELD_ERROR - Field '" . $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] . "' is missing has to be added manually to the database layout!'"); + return ERROR_DB_ADDDBFIELDFAILED; + } + } + } + + // Reached this point means success! + return SUCCESS; + } + + /* + * Helper function to return a list of Indexes for the logstream table + */ + private function GetIndexesAsArray() + { + global $querycount; + + // Verify database connection (This also opens the database!) + $res = $this->Verify(); + if ( $res != SUCCESS ) + return $res; + + // Init Array + $arrIndexKeys = array(); + + // Create SQL and Get INDEXES for table! + $szSql = "SHOW INDEX FROM " . $this->_logStreamConfigObj->DBTableName; + $myQuery = mysql_query($szSql, $this->_dbhandle); + if ($myQuery) + { + // Loop through results + while ($myRow = mysql_fetch_array($myQuery, MYSQL_ASSOC)) + { + // Add to index keys + $arrIndexKeys[] = strtolower($myRow['Key_name']); } - // Reached this point means success! - return SUCCESS; + // Free query now + mysql_free_result ($myQuery); + + // Increment for the Footer Stats + $querycount++; } - else - $this->PrintDebugError("ER_BAD_FIELD_ERROR - SQL Statement: ". $errdesc); - return ERROR_DB_DBFIELDNOTFOUND; + + // return Array + return $arrIndexKeys; + } + + + /* + * Helper function to return a list of Fields from the logstream table + */ + private function GetFieldsAsArray() + { + global $querycount; + + // Verify database connection (This also opens the database!) + $res = $this->Verify(); + if ( $res != SUCCESS ) + return $res; + + // Init Array + $arrFieldKeys = array(); + + // Create SQL and Get INDEXES for table! + $szSql = "SHOW FIELDS FROM " . $this->_logStreamConfigObj->DBTableName; + $myQuery = mysql_query($szSql, $this->_dbhandle); + if ($myQuery) + { + // Loop through results + while ($myRow = mysql_fetch_array($myQuery, MYSQL_ASSOC)) + { + // Add to index keys + $arrFieldKeys[] = strtolower($myRow['Field']); + } + + // Free query now + mysql_free_result ($myQuery); + + // Increment for the Footer Stats + $querycount++; + } + + // return Array + return $arrFieldKeys; + } + + + /* + * Helper function to return a list of Indexes for the logstream table + */ + private function GetTriggersAsArray() + { + global $querycount; + + // Verify database connection (This also opens the database!) + $res = $this->Verify(); + if ( $res != SUCCESS ) + return $res; + + // Init Array + $arrIndexTriggers = array(); + + // Create SQL and Get INDEXES for table! + $szSql = "SHOW TRIGGERS"; + $myQuery = mysql_query($szSql, $this->_dbhandle); + if ($myQuery) + { + // Loop through results + while ($myRow = mysql_fetch_array($myQuery, MYSQL_ASSOC)) + { +// print_r ( $myRow ); + // Add to index keys + $arrIndexTriggers[] = strtolower($myRow['Trigger']); + } + + // Free query now + mysql_free_result ($myQuery); + + // Increment for the Footer Stats + $querycount++; + } + + // return Array + return $arrIndexTriggers; } // --- End of Class! diff --git a/src/classes/logstreamdisk.class.php b/src/classes/logstreamdisk.class.php index 4784c5b..f127a75 100644 --- a/src/classes/logstreamdisk.class.php +++ b/src/classes/logstreamdisk.class.php @@ -33,10 +33,6 @@ * * A copy of the GPL can be found in the file "COPYING" in this * distribution. - * - * Adiscon LogAnalyzer is also available under a commercial license. - * For details, contact info@adiscon.com or visit - * http://loganalyzer.adiscon.com/commercial ********************************************************************* */ @@ -96,6 +92,7 @@ class LogStreamDisk extends LogStream { return SUCCESS; } + /** * Close the file. * @@ -616,7 +613,6 @@ class LogStreamDisk extends LogStream { public function GetLogStreamStats() { // Get some file data! - /* // return results! return $stats; @@ -662,6 +658,108 @@ class LogStreamDisk extends LogStream { } + /* + * Implementation of the UpdateAllMessageChecksum + * + * not implemented! + */ + public function UpdateAllMessageChecksum( ) + { + return SUCCESS; + } + + + /* + * Helper function to clear the current querystring! + */ + public function ResetFilters() + { + // nothing todo in this logstream + return SUCCESS; + } + + + /* + * Helper function to verify fields | not needed in disk logstream! + */ + public function VerifyFields( $arrProperitesIn ) + { + return SUCCESS; + } + + + /* + * Helper function to create missing fields | not needed in disk logstream! + */ + public function CreateMissingFields( $arrProperitesIn ) + { + return SUCCESS; + } + + + /* + * Helper function to verify indexes | not needed in disk logstream! + */ + public function VerifyIndexes( $arrProperitesIn ) + { + return SUCCESS; + } + + + /* + * Helper function to create missing indexes | not needed in disk logstream! + */ + public function CreateMissingIndexes( $arrProperitesIn ) + { + return SUCCESS; + } + + + /* + * Helper function to verify triggers | not needed in disk logstream! + */ + public function VerifyChecksumTrigger( $myTriggerProperty ) + { + return SUCCESS; + } + + + /* + * Helper function to verify triggers | not needed in disk logstream! + */ + public function CreateMissingTrigger( $myTriggerProperty, $myCheckSumProperty ) + { + return SUCCESS; + } + + + /* + * Helper function to create missing triggers | not needed in disk logstream! + */ + public function GetCreateMissingTriggerSQL( $myDBTriggerField, $myDBTriggerCheckSumField ) + { + return SUCCESS; + } + + + /* + * Helper function to verify checksum field | not needed in disk logstream! + */ + public function VerifyChecksumField( ) + { + return SUCCESS; + } + + + /* + * Helper function to correct the checksum field | not needed in disk logstream! + */ + public function ChangeChecksumFieldUnsigned( ) + { + return SUCCESS; + } + + /** * Implementation of ConsolidateItemListByField * @@ -756,7 +854,7 @@ class LogStreamDisk extends LogStream { * * @return integer Error stat */ - public function ConsolidateDataByField($szConsFieldId, $nRecordLimit, $szSortFieldId, $nSortingOrder, $aIncludeCustomFields = null, $bIncludeLogStreamFields = false) + public function ConsolidateDataByField($szConsFieldId, $nRecordLimit, $szSortFieldId, $nSortingOrder, $aIncludeCustomFields = null, $bIncludeLogStreamFields = false, $bIncludeMinMaxDateFields = false) { global $content, $fields; @@ -781,6 +879,11 @@ class LogStreamDisk extends LogStream { { if ( isset($logArray[$szConsFieldId]) ) { + // --- Special Case for the checksum field, we need to generate the checksum ourself! + if ( $szConsFieldId == MISC_CHECKSUM ) + $logArray[$szConsFieldId] = crc32( $logArray[SYSLOG_MESSAGE] ); + // --- + if ( $nConsFieldType == FILTER_TYPE_DATE ) { // Convert to FULL Day Date for now! @@ -794,7 +897,10 @@ class LogStreamDisk extends LogStream { $myFieldData = $content['LN_STATS_OTHERS']; if ( isset($aResult[ $myFieldData ]) ) + { $aResult[ $myFieldData ]['ItemCount']++; + $aResult[ $myFieldData ]['LastOccurrence_Date'] = $logArray[SYSLOG_DATE]; + } else { // Initialize entry if we haven't exceeded the RecordLImit yet! @@ -815,6 +921,9 @@ class LogStreamDisk extends LogStream { $aResult[ $myFieldData ][$szSortFieldId] = $logArray[$szSortFieldId]; $aResult[ $myFieldData ]['ItemCount'] = 1; + + $aResult[ $myFieldData ]['FirstOccurrence_Date'] = $logArray[SYSLOG_DATE]; + $aResult[ $myFieldData ]['LastOccurrence_Date'] = $logArray[SYSLOG_DATE]; } else { diff --git a/src/classes/logstreampdo.class.php b/src/classes/logstreampdo.class.php index 729acfc..2994b38 100644 --- a/src/classes/logstreampdo.class.php +++ b/src/classes/logstreampdo.class.php @@ -28,10 +28,6 @@ * * A copy of the GPL can be found in the file "COPYING" in this * distribution. - * - * Adiscon LogAnalyzer is also available under a commercial license. - * For details, contact info@adiscon.com or visit - * http://loganalyzer.adiscon.com/commercial ********************************************************************* */ @@ -122,6 +118,15 @@ class LogStreamPDO extends LogStream { return SUCCESS; } + /* + * Helper function to clear the current querystring! + */ + public function ResetFilters() + { + // Clear _SQLwhereClause variable! + $this->_SQLwhereClause = ""; + } + /** * Close the database connection. * @@ -132,8 +137,7 @@ class LogStreamPDO extends LogStream { // trigger closing database query! $this->DestroyMainSQLQuery(); -// TODO CLOSE DB CONN?! - + // TODO CLOSE DB CONN?! return true; } @@ -223,6 +227,397 @@ class LogStreamPDO extends LogStream { return SUCCESS; } + + /* + * Implementation of VerifyFields: Checks if fields exist in table + */ + public function VerifyFields( $arrProperitesIn ) + { + global $dbmapping, $fields; + + // Get List of Indexes as Array + $arrFieldKeys = $this->GetFieldsAsArray(); + $szTableType = $this->_logStreamConfigObj->DBTableType; + + // FIELD Listing failed! Nothing we can do in this case! + if ( $arrFieldKeys == null ) + return SUCCESS; + + // Loop through all fields to see which one is missing! + foreach ( $arrProperitesIn as $myproperty ) + { +// echo $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] . "
"; + if ( isset($dbmapping[$szTableType]['DBMAPPINGS'][$myproperty]) && in_array($dbmapping[$szTableType]['DBMAPPINGS'][$myproperty], $arrFieldKeys) ) + { + OutputDebugMessage("LogStreamPDO|VerifyFields: Found Field for '" . $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] . "'", DEBUG_ULTRADEBUG); + continue; + } + else + { + // Index is missing for this field! + OutputDebugMessage("LogStreamPDO|VerifyFields: Missing Field for '" . $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] . "'", DEBUG_WARN); + return ERROR_DB_DBFIELDNOTFOUND; + } + } + + // Successfull + return SUCCESS; + } + + + /* + * Implementation of VerifyIndexes: Checks if indexes exist for desired fields + */ + public function VerifyIndexes( $arrProperitesIn ) + { + global $dbmapping, $fields; + + // Get List of Indexes as Array + $arrIndexKeys = $this->GetIndexesAsArray(); + $szTableType = $this->_logStreamConfigObj->DBTableType; + + // INDEX Listing failed! Nothing we can do in this case! + if ( !isset($arrIndexKeys) )// == null ) + return SUCCESS; + + // Loop through all fields to see which one is missing! + foreach ( $arrProperitesIn as $myproperty ) + { + if ( count($arrIndexKeys) <= 0 ) + { + // NO INDEXES at all! + OutputDebugMessage("LogStreamPDO|VerifyIndexes: NO INDEXES found !", DEBUG_WARN); + return ERROR_DB_INDEXESMISSING; + } + if ( isset($dbmapping[$szTableType]['DBMAPPINGS'][$myproperty]) && in_array($dbmapping[$szTableType]['DBMAPPINGS'][$myproperty], $arrIndexKeys) ) + { + OutputDebugMessage("LogStreamPDO|VerifyIndexes: Found INDEX for '" . $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] . "'", DEBUG_ULTRADEBUG); + continue; + } + else + { + // Index is missing for this field! + OutputDebugMessage("LogStreamPDO|VerifyIndexes: Missing INDEX for '" . $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] . "'", DEBUG_WARN); + return ERROR_DB_INDEXESMISSING; + } + } + + // Successfull + return SUCCESS; + } + + + /* + * Implementation of VerifyChecksumTrigger: Checks if checksum trigger exists + */ + public function VerifyChecksumTrigger( $myTriggerProperty ) + { + global $dbmapping, $fields; + + // Avoid Check if TRIGGERS are not supported! + if ( $this->_logStreamConfigObj->GetPDOTriggersSupported() == false ) + return SUCCESS; + + // Get List of Triggers as Array + $arrIndexTriggers = $this->GetTriggersAsArray(); + + // TRIGGER Listing failed! Nothing we can do in this case! + if ( !isset($arrIndexTriggers) )// == null ) +// if ( $arrIndexTriggers == null ) + return SUCCESS; + + $szTableType = $this->_logStreamConfigObj->DBTableType; + $szDBName = $this->_logStreamConfigObj->DBName; + $szTableName = $this->_logStreamConfigObj->DBTableName; + $szDBTriggerField = $dbmapping[$szTableType]['DBMAPPINGS'][$myTriggerProperty]; + + // Create Triggername + $szTriggerName = strtolower($szDBName . "_" . $szTableName . "_" . $szDBTriggerField); + + // Try to find logstream trigger + if ( count($arrIndexTriggers) > 0 ) + { + if ( in_array($szTriggerName, $arrIndexTriggers) ) + { + OutputDebugMessage("LogStreamPDO|VerifyChecksumTrigger: Found TRIGGER '" . $szTriggerName. "' for table '" . $szTableName . "'", DEBUG_ULTRADEBUG); + return SUCCESS; + } + else + { + // Index is missing for this field! + OutputDebugMessage("LogStreamPDO|VerifyChecksumTrigger: Missing TRIGGER '" . $szTriggerName . "' for Table '" . $szTableName . "'", DEBUG_WARN); + return ERROR_DB_TRIGGERMISSING; + } + } + else + { + // Index is missing for this field! + OutputDebugMessage("LogStreamPDO|VerifyChecksumTrigger: No TRIGGERS found in your database", DEBUG_WARN); + return ERROR_DB_TRIGGERMISSING; + } + } + + + /* + * Implementation of CreateMissingIndexes: Checks if indexes exist for desired fields + */ + public function CreateMissingIndexes( $arrProperitesIn ) + { + global $dbmapping, $fields, $querycount; + + // Get List of Indexes as Array + $arrIndexKeys = $this->GetIndexesAsArray(); + $szTableType = $this->_logStreamConfigObj->DBTableType; + + // Loop through all fields to see which one is missing! + foreach ( $arrProperitesIn as $myproperty ) + { + if ( isset($dbmapping[$szTableType]['DBMAPPINGS'][$myproperty]) && in_array($dbmapping[$szTableType]['DBMAPPINGS'][$myproperty], $arrIndexKeys) ) + continue; + else + { + // Update Table schema now! + if ( $this->_logStreamConfigObj->DBType == DB_MYSQL ) + $szSql = "ALTER TABLE " . $this->_logStreamConfigObj->DBTableName . " ADD INDEX ( " . $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] . " )"; + else if ( $this->_logStreamConfigObj->DBType == DB_PGSQL ) + $szSql = "CREATE INDEX " . $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] . "_idx ON " . $this->_logStreamConfigObj->DBTableName . " (" . $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] . ");"; + else if ( $this->_logStreamConfigObj->DBType == DB_MSSQL ) + $szSql = "CREATE INDEX " . $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] . "_idx ON " . $this->_logStreamConfigObj->DBTableName . " (" . $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] . ");"; + else + // Not supported in this case! + return ERROR_DB_INDEXFAILED; + + + // Index is missing for this field! + OutputDebugMessage("LogStreamPDO|CreateMissingIndexes: Createing missing INDEX for '" . $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] . "' - " . $szSql, DEBUG_INFO); + + // Add missing INDEX now! + $myQuery = $this->_dbhandle->query($szSql); + if (!$myQuery) + { + // Return failure! + $this->PrintDebugError("Dynamically Adding INDEX for '" . $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] . "' failed with Statement: '" . $szSql . "'"); + return ERROR_DB_INDEXFAILED; + } + else // Free query now + $myQuery->closeCursor(); + } + } + + // Successfull + return SUCCESS; + } + + + /* + * Implementation of CreateMissingFields: Checks if indexes exist for desired fields + */ + public function CreateMissingFields( $arrProperitesIn ) + { + global $dbmapping, $fields, $querycount; + + // Get List of Indexes as Array + $arrFieldKeys = $this->GetFieldsAsArray(); + $szTableType = $this->_logStreamConfigObj->DBTableType; + + // Loop through all fields to see which one is missing! + foreach ( $arrProperitesIn as $myproperty ) + { + if ( isset($dbmapping[$szTableType]['DBMAPPINGS'][$myproperty]) && in_array($dbmapping[$szTableType]['DBMAPPINGS'][$myproperty], $arrFieldKeys) ) + continue; + else + { + if ( $this->HandleMissingField( $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty], $arrProperitesIn ) == SUCCESS ) + { + // Index is missing for this field! + OutputDebugMessage("LogStreamPDO|CreateMissingFields: Createing missing FIELD for '" . $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty], DEBUG_INFO); + } + else + { + // Return failure! + $this->PrintDebugError("Dynamically Adding FIELD for '" . $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] . "' failed!"); + return ERROR_DB_ADDDBFIELDFAILED; + } + } + } + + // Successfull + return SUCCESS; + } + + + /* + * Implementation of GetCreateMissingTriggerSQL: Creates SQL needed to create a TRIGGER + */ + public function GetCreateMissingTriggerSQL( $myDBTriggerField, $myDBTriggerCheckSumField ) + { + global $dbmapping, $fields, $querycount; + + // Get List of Triggers as Array + $szDBName = $this->_logStreamConfigObj->DBName; + $szTableName = $this->_logStreamConfigObj->DBTableName; + + // Create Triggername + $szTriggerName = strtolower($szDBName . "_" . $szTableName . "_" . $myDBTriggerField); + + // Create TRIGGER SQL! + if ( $this->_logStreamConfigObj->DBType == DB_MYSQL ) + $szSql ="CREATE TRIGGER " . $szTriggerName . " BEFORE INSERT ON `" . $szTableName . "` + FOR EACH ROW + BEGIN + SET NEW." . $myDBTriggerCheckSumField . " = crc32(NEW." . $myDBTriggerField . "); + END + ;"; + else if ( $this->_logStreamConfigObj->DBType == DB_PGSQL ) + // Experimental Trigger Support for POSTGRESQL + $szSql =" + CREATE LANGUAGE plpgsql ; + CREATE FUNCTION " . $szTriggerName . "() RETURNS trigger AS $" . $szTriggerName . "$ + BEGIN + NEW." . $myDBTriggerCheckSumField . " := hashtext(NEW." . $myDBTriggerField . "); + RETURN NEW; + END; + $" . $szTriggerName . "$ LANGUAGE plpgsql; + + CREATE TRIGGER " . $szTriggerName . " BEFORE INSERT OR UPDATE ON \"" . $szTableName . "\" + FOR EACH ROW EXECUTE PROCEDURE " . $szTriggerName . "(); + "; + else if ( $this->_logStreamConfigObj->DBType == DB_MSSQL ) + { + // Trigger code for MSSQL! + $szSql ="CREATE TRIGGER " . $szTriggerName . " ON " . $szTableName . " AFTER INSERT AS + BEGIN + -- SET NOCOUNT ON added to prevent extra result sets from + -- interfering with SELECT statements. + SET NOCOUNT ON; + + -- Insert statements for trigger here + UPDATE " . $szTableName . " + SET " . $myDBTriggerCheckSumField . " = checksum(I." . $myDBTriggerField . ") + FROM systemevents JOIN inserted I on " . $szTableName . "." . $dbmapping[$szTableType]['DBMAPPINGS']['SYSLOG_UID'] . " = I." . $dbmapping[$szTableType]['DBMAPPINGS']['SYSLOG_UID'] . " + END + "; + } + else + // NOT SUPPORTED + return null; + + return $szSql; + } + + + /* + * Implementation of CreateMissingTrigger: Creates missing triggers ! + */ + public function CreateMissingTrigger( $myTriggerProperty, $myCheckSumProperty ) + { + global $dbmapping, $fields, $querycount; + + // Avoid if TRIGGERS are not supported! + if ( $this->_logStreamConfigObj->GetPDOTriggersSupported() == false ) + return SUCCESS; + + // Get List of Triggers as Array + $szTableName = $this->_logStreamConfigObj->DBTableName; + $szTableType = $this->_logStreamConfigObj->DBTableType; + $szDBTriggerField = $dbmapping[$szTableType]['DBMAPPINGS'][$myTriggerProperty]; + $szDBTriggerCheckSumField = $dbmapping[$szTableType]['DBMAPPINGS'][$myCheckSumProperty]; + + // Get SQL Code to create the trigger! + $szSql = $this->GetCreateMissingTriggerSQL( $szDBTriggerField, $szDBTriggerCheckSumField ); + + // Index is missing for this field! + OutputDebugMessage("LogStreamPDO|CreateMissingTrigger: Creating missing TRIGGER for '" . $szTableName . "' - $szDBTriggerCheckSumField = crc32(NEW.$szDBTriggerField)" . $szSql, DEBUG_INFO); + + // Add missing INDEX now! + $myQuery = $this->_dbhandle->query($szSql); + if (!$myQuery) + { + // Return failure! + $this->PrintDebugError("Dynamically Adding TRIGGER for '" . $szTableName . "' failed!

If you want to manually add the TRIGGER, use the following SQL Command:
" . str_replace("\n", "
", $szSql) . "
"); + return ERROR_DB_TRIGGERFAILED; + } + else // Free query now + $myQuery->closeCursor(); + + // Successfull + return SUCCESS; + } + + + /* + * Implementation of ChangeChecksumFieldUnsigned: Changes the Checkusm field to unsigned! + */ + public function ChangeChecksumFieldUnsigned() + { + global $dbmapping, $fields, $querycount; + + // Get variables + $szTableType = $this->_logStreamConfigObj->DBTableType; + +// TODO if ( $this->_logStreamConfigObj->DBType == DB_MYSQL ) + // Change Checksumfield to use UNSIGNED! + $szUpdateSql = "ALTER TABLE `" . $this->_logStreamConfigObj->DBTableName . "` CHANGE `" . + $dbmapping[$szTableType]['DBMAPPINGS'][MISC_CHECKSUM] . "` `" . + $dbmapping[$szTableType]['DBMAPPINGS'][MISC_CHECKSUM] . "` INT(11) UNSIGNED NOT NULL DEFAULT '0'"; + + // Update Table schema now! + $myQuery = $this->_dbhandle->query($szUpdateSql); + if (!$myQuery) + { + // Return failure! + $this->PrintDebugError("ER_BAD_FIELD_ERROR - Failed to Change field '" . $dbmapping[$szTableType]['DBMAPPINGS'][MISC_CHECKSUM] . "' from signed to unsigned with sql statement: '" . $szUpdateSql . "'"); + return ERROR_DB_CHECKSUMCHANGEFAILED; + } + else // Free query now + $myQuery->closeCursor(); + + // return results + return SUCCESS; + } + + + /* + * Implementation of VerifyChecksumField: Verifies if the checkusm field is signed or unsigned! + */ + public function VerifyChecksumField() + { + global $dbmapping, $fields, $querycount; + + // Get variables + $szTableType = $this->_logStreamConfigObj->DBTableType; + + // Create SQL and Get INDEXES for table! + if ( $this->_logStreamConfigObj->DBType == DB_MYSQL ) + $szSql = "SHOW COLUMNS FROM " . $this->_logStreamConfigObj->DBTableName . " WHERE Field = '" . $dbmapping[$szTableType]['DBMAPPINGS'][MISC_CHECKSUM] . "'"; + else + // NOT SUPPORTED or NEEDED + return SUCCESS; + + // Run Query to check the Checksum field! + $myQuery = $this->_dbhandle->query($szSql); + if ($myQuery) + { + // Get result! + $myRow = $myQuery->fetch(PDO::FETCH_ASSOC); + if (strpos( strtolower($myRow['Type']), "unsigned") === false ) + { + // return error code! + return ERROR_DB_CHECKSUMERROR; + } + + // Free query now + $myQuery->closeCursor(); + + // Increment for the Footer Stats + $querycount++; + } + + // return results + return SUCCESS; + } + + /** * Read the data from a specific uID which means in this * case beginning with from the Database ID @@ -707,6 +1102,69 @@ class LogStreamPDO extends LogStream { } + /* + * Implementation of the UpdateAllMessageChecksum + * + * Update all missing checksum properties in the current database + */ + public function UpdateAllMessageChecksum( ) + { + global $querycount, $dbmapping; + $szTableType = $this->_logStreamConfigObj->DBTableType; + + // UPDATE DATA NOW! + if ( $this->_logStreamConfigObj->DBType == DB_MYSQL ) + { + $szSql = "UPDATE " . $this->_logStreamConfigObj->DBTableName . + " SET " . $dbmapping[$szTableType]['DBMAPPINGS'][MISC_CHECKSUM] . " = crc32(" . $dbmapping[$szTableType]['DBMAPPINGS'][SYSLOG_MESSAGE] . ") " . + " WHERE " . $dbmapping[$szTableType]['DBMAPPINGS'][MISC_CHECKSUM] . " IS NULL OR " . $dbmapping[$szTableType]['DBMAPPINGS'][MISC_CHECKSUM] . " = 0"; + } + elseif ($this->_logStreamConfigObj->DBType == DB_PGSQL ) + { + $szSql = "UPDATE " . $this->_logStreamConfigObj->DBTableName . + " SET " . $dbmapping[$szTableType]['DBMAPPINGS'][MISC_CHECKSUM] . " = hashtext(" . $dbmapping[$szTableType]['DBMAPPINGS'][SYSLOG_MESSAGE] . ") " . + " WHERE " . $dbmapping[$szTableType]['DBMAPPINGS'][MISC_CHECKSUM] . " IS NULL OR " . $dbmapping[$szTableType]['DBMAPPINGS'][MISC_CHECKSUM] . " = 0"; + } + elseif ($this->_logStreamConfigObj->DBType == DB_MSSQL ) + { + $szSql = "UPDATE " . $this->_logStreamConfigObj->DBTableName . + " SET " . $dbmapping[$szTableType]['DBMAPPINGS'][MISC_CHECKSUM] . " = checksum(" . $dbmapping[$szTableType]['DBMAPPINGS'][SYSLOG_MESSAGE] . ") " . + " WHERE " . $dbmapping[$szTableType]['DBMAPPINGS'][MISC_CHECKSUM] . " IS NULL OR " . $dbmapping[$szTableType]['DBMAPPINGS'][MISC_CHECKSUM] . " = 0"; + } + else + { + // Failed | Checksum function not supported! + $this->PrintDebugError("UpdateAllMessageChecksum failed, PDO LogStream does not support CRC32 Checksums in SQL Statements!"); + return ERROR; + } + + // Output Debug Informations + OutputDebugMessage("LogStreamPDO|UpdateAllMessageChecksum: Running Created SQL Query:
" . $szSql, DEBUG_ULTRADEBUG); + + // Running SQL Query + $myQuery = $this->_dbhandle->query($szSql); + if ( $myQuery ) + { + // Output Debug Informations + OutputDebugMessage("LogStreamPDO|UpdateAllMessageChecksum: Successfully updated Checksum of '" . $myQuery->rowCount() . "' datarecords", DEBUG_INFO); + + // Free query now + $myQuery->closeCursor(); + + // Return success + return SUCCESS; + } + else + { + // error occured, output DEBUG message + $this->PrintDebugError("UpdateAllMessageChecksum failed with SQL Statement ' " . $szSql . " '"); + + // Failed + return ERROR; + } + } + + /* * Implementation of the SaveMessageChecksum * @@ -781,7 +1239,7 @@ class LogStreamPDO extends LogStream { // Set Sorted Field if ( $szConsFieldId == $szSortFieldId ) - $myDBSortedFieldName = "ItemCount"; + $myDBSortedFieldName = "itemcount"; else $myDBSortedFieldName = $szSortFieldId; // --- @@ -827,7 +1285,7 @@ class LogStreamPDO extends LogStream { // Create SQL String now! $szSql = "SELECT " . $myDBQueryFields . - "count(" . $myDBConsFieldName . ") as ItemCount " . + "count(" . $myDBConsFieldName . ") as itemcount " . " FROM " . $this->_logStreamConfigObj->DBTableName . $this->_SQLwhereClause . " GROUP BY " . $myDBGroupByFieldName . @@ -890,7 +1348,7 @@ class LogStreamPDO extends LogStream { * * @return integer Error stat */ - public function ConsolidateDataByField($szConsFieldId, $nRecordLimit, $szSortFieldId, $nSortingOrder, $aIncludeCustomFields = null, $bIncludeLogStreamFields = false) + public function ConsolidateDataByField($szConsFieldId, $nRecordLimit, $szSortFieldId, $nSortingOrder, $aIncludeCustomFields = null, $bIncludeLogStreamFields = false, $bIncludeMinMaxDateFields = false) { global $content, $dbmapping, $fields;; @@ -921,12 +1379,26 @@ class LogStreamPDO extends LogStream { foreach ( $aIncludeCustomFields as $myFieldName ) { if ( isset($dbmapping[$szTableType]['DBMAPPINGS'][$myFieldName]) ) - $myDBQueryFields .= $dbmapping[$szTableType]['DBMAPPINGS'][$myFieldName] . ", "; + { + if ( $this->_logStreamConfigObj->DBType == DB_PGSQL || + $this->_logStreamConfigObj->DBType == DB_MSSQL ) + $myDBQueryFields .= "Max(" . $dbmapping[$szTableType]['DBMAPPINGS'][$myFieldName] . ") AS " . $dbmapping[$szTableType]['DBMAPPINGS'][$myFieldName] . ", "; + else + // Default for other PDO Engines + $myDBQueryFields .= $dbmapping[$szTableType]['DBMAPPINGS'][$myFieldName] . ", "; + } } // Append Sortingfield if ( !in_array($szConsFieldId, $aIncludeCustomFields) ) - $myDBQueryFields .= $myDBConsFieldName . ", "; + { + if ( $this->_logStreamConfigObj->DBType == DB_PGSQL || + $this->_logStreamConfigObj->DBType == DB_MSSQL ) + $myDBQueryFields .= "Max(" . $myDBConsFieldName . ") AS " . $dbmapping[$szTableType]['DBMAPPINGS'][$myFieldName] . ", "; + else + // Default for other PDO Engines + $myDBQueryFields .= $myDBConsFieldName . ", "; + } } else if ( $bIncludeLogStreamFields ) { @@ -934,14 +1406,35 @@ class LogStreamPDO extends LogStream { foreach ( $this->_arrProperties as $myFieldName ) { if ( isset($dbmapping[$szTableType]['DBMAPPINGS'][$myFieldName]) ) - $myDBQueryFields .= $dbmapping[$szTableType]['DBMAPPINGS'][$myFieldName] . ", "; + { + if ( $this->_logStreamConfigObj->DBType == DB_PGSQL || + $this->_logStreamConfigObj->DBType == DB_MSSQL ) + $myDBQueryFields .= "Max(" . $dbmapping[$szTableType]['DBMAPPINGS'][$myFieldName] . ") AS " . $dbmapping[$szTableType]['DBMAPPINGS'][$myFieldName] . ", "; + else + // Default for other PDO Engines + $myDBQueryFields .= $dbmapping[$szTableType]['DBMAPPINGS'][$myFieldName] . ", "; + } } } else // Only Include ConsolidateField - $myDBQueryFields = $myDBConsFieldName . ", "; + { + if ( $this->_logStreamConfigObj->DBType == DB_PGSQL || + $this->_logStreamConfigObj->DBType == DB_MSSQL ) + $myDBQueryFields = "Max(" . $myDBConsFieldName . ") as " . $myDBConsFieldName. ", "; + else + // Default for other PDO Engines + $myDBQueryFields = $myDBConsFieldName . ", "; + } + + // Add Min and Max fields for DATE if desired + if ( $bIncludeMinMaxDateFields ) + { + $myDBQueryFields .= "Min(" . $dbmapping[$szTableType]['DBMAPPINGS'][SYSLOG_DATE] . ") as firstoccurrence_date, "; + $myDBQueryFields .= "Max(" . $dbmapping[$szTableType]['DBMAPPINGS'][SYSLOG_DATE] . ") as lastoccurrence_date, "; + } if ( $szConsFieldId == $szSortFieldId ) - $myDBSortedFieldName = "ItemCount"; + $myDBSortedFieldName = "itemcount"; else $myDBSortedFieldName = $szSortFieldId; // --- @@ -959,6 +1452,9 @@ class LogStreamPDO extends LogStream { else if($this->_logStreamConfigObj->DBType == DB_MSSQL ) { // TODO FIND A WAY FOR MSSQL! + // Helper variable for the select statement + $mySelectFieldName = $myDBGroupByFieldName . "Grouped"; + $myDBQueryFieldName = "DATE( " . $myDBConsFieldName . ") AS " . $myDBGroupByFieldName ; } } @@ -968,23 +1464,40 @@ class LogStreamPDO extends LogStream { // Append LIMIT in this case! if ( $this->_logStreamConfigObj->DBType == DB_MYSQL || $this->_logStreamConfigObj->DBType == DB_PGSQL ) - $szLimitSql = " LIMIT " . $nRecordLimit; + { + $szLimitSqlBefore = ""; + $szLimitSqlAfter = " LIMIT " . $nRecordLimit; + } + else if( $this->_logStreamConfigObj->DBType == DB_MSSQL ) + { + $szLimitSqlBefore = " TOP(" . $nRecordLimit . ") "; + $szLimitSqlAfter = ""; + } else - $szLimitSql = ""; - // TODO FIND A WAY FOR MSSQL! + { + $szLimitSqlBefore = ""; + $szLimitSqlAfter = ""; + } } else - $szLimitSql = ""; + { + $szLimitSqlBefore = ""; + $szLimitSqlAfter = ""; + } // Create SQL String now! $szSql = "SELECT " . + $szLimitSqlBefore . $myDBQueryFields . - "count(" . $myDBConsFieldName . ") as ItemCount " . + "count(" . $myDBConsFieldName . ") as itemcount " . " FROM " . $this->_logStreamConfigObj->DBTableName . $this->_SQLwhereClause . " GROUP BY " . $myDBGroupByFieldName . " ORDER BY " . $myDBSortedFieldName . " " . $szSortingOrder . - $szLimitSql ; + $szLimitSqlAfter ; + + // Output Debug Informations + OutputDebugMessage("LogStreamPDO|ConsolidateDataByField: Running Created SQL Query:
" . $szSql, DEBUG_DEBUG); // Perform Database Query $this->_myDBQuery = $this->_dbhandle->query($szSql); @@ -1010,10 +1523,14 @@ class LogStreamPDO extends LogStream { foreach ( $myRow as $myFieldName => $myFieldValue ) { + $myFieldID = $this->GetFieldIDbyDatabaseMapping($szTableType, $myFieldName); + $aNewRow[ $myFieldID ] = $myFieldValue; + /* if ( $myFieldName == $dbmapping[$szTableType]['DBMAPPINGS'][$szConsFieldId] ) $aNewRow[$szConsFieldId] = $myFieldValue; else $aNewRow[$myFieldName] = $myFieldValue; + */ } // Add new row to result @@ -1694,77 +2211,259 @@ class LogStreamPDO extends LogStream { /* * Function handles missing database fields automatically! */ - private function HandleMissingField() + private function HandleMissingField( $szMissingField = null, $arrProperties = null ) { global $dbmapping, $fields; // Get Err description $errdesc = $this->_dbhandle->errorInfo(); - // check matching of error msg! - if ( - preg_match("/Unknown column '(.*?)' in '(.*?)'$/", $errdesc[2], $errOutArr ) || // MySQL - preg_match("/column \"(.*?)\" does not exist/", $errdesc[2], $errOutArr ) // PostgreSQL -// ERROR: column "checksum" does not exist LINE 1: ... eventsource, eventcategory, eventuser, systemid, checksum, ... ^ - ) + // Try to get missing field from SQL Error of not specified as argument + if ( $szMissingField == null ) { - $szTableType = $this->_logStreamConfigObj->DBTableType; - - // Loop through all fields to see which one is missing! - foreach ( $this->_arrProperties as $myproperty ) + // check matching of error msg! + if ( + preg_match("/Unknown column '(.*?)' in '(.*?)'$/", $errdesc[2], $errOutArr ) || // MySQL + preg_match("/column \"(.*?)\" does not exist/", $errdesc[2], $errOutArr ) || // PostgreSQL + preg_match("/Invalid column name '(.*?)'/", $errdesc[2], $errOutArr ) // MSSQL +// ERROR: column "checksum" does not exist LINE 1: ... eventsource, eventcategory, eventuser, systemid, checksum, ... ^ + ) { - if ( isset($dbmapping[$szTableType]['DBMAPPINGS'][$myproperty]) && $errOutArr[1] == $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] ) - { - $szUpdateSql = ""; - if ( $this->_logStreamConfigObj->DBType == DB_MYSQL ) - { - // MYSQL Statements - if ( $fields[$myproperty]['FieldType'] == FILTER_TYPE_NUMBER ) - $szUpdateSql = "ALTER TABLE `" . $this->_logStreamConfigObj->DBTableName . "` ADD `" . $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] . "` int(11) NOT NULL DEFAULT '0'"; - if ( $fields[$myproperty]['FieldType'] == FILTER_TYPE_STRING ) - $szUpdateSql = "ALTER TABLE `" . $this->_logStreamConfigObj->DBTableName . "` ADD `" . $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] . "` varchar(60) NULL"; - if ( $fields[$myproperty]['FieldType'] == FILTER_TYPE_DATE ) - $szUpdateSql = "ALTER TABLE `" . $this->_logStreamConfigObj->DBTableName . "` ADD `" . $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] . "` datetime NOT NULL DEFAULT '0000-00-00 00:00:00'"; - } - else if ( $this->_logStreamConfigObj->DBType == DB_PGSQL ) - { - // MYSQL Statements - if ( $fields[$myproperty]['FieldType'] == FILTER_TYPE_NUMBER ) - $szUpdateSql = "ALTER TABLE " . $this->_logStreamConfigObj->DBTableName . " ADD " . $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] . " int NOT NULL DEFAULT '0'"; - if ( $fields[$myproperty]['FieldType'] == FILTER_TYPE_STRING ) - $szUpdateSql = "ALTER TABLE " . $this->_logStreamConfigObj->DBTableName . " ADD " . $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] . " varchar(60) NULL"; - if ( $fields[$myproperty]['FieldType'] == FILTER_TYPE_DATE ) - $szUpdateSql = "ALTER TABLE " . $this->_logStreamConfigObj->DBTableName . " ADD " . $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] . " timestamp without time zone NULL"; - } + $szMissingField = $errOutArr[1]; + } + else + { + $this->PrintDebugError("ER_BAD_FIELD_ERROR - SQL Statement: ". $errdesc[2]); + return ERROR_DB_DBFIELDNOTFOUND; + } + } - if ( strlen($szUpdateSql) > 0 ) - { - // Update Table schema now! - $myQuery = $this->_dbhandle->query($szUpdateSql); - if (!$myQuery) - { - // Return failure! - $this->PrintDebugError("ER_BAD_FIELD_ERROR - Dynamically Adding field '" . $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] . "' with Statement failed: '" . $szUpdateSql . "'"); - return ERROR_DB_DBFIELDNOTFOUND; - } - else // Free query now - $myQuery->closeCursor(); - } - else + // Set Properties to default if NULL + if ( $arrProperties == null ) + $arrProperties = $this->_arrProperties; + + // Get Tabletype + $szTableType = $this->_logStreamConfigObj->DBTableType; + + // Loop through all fields to see which one is missing! + foreach ( $arrProperties as $myproperty ) + { + if ( isset($dbmapping[$szTableType]['DBMAPPINGS'][$myproperty]) && $szMissingField == $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] ) + { + $szUpdateSql = ""; + if ( $this->_logStreamConfigObj->DBType == DB_MYSQL ) + { + // MYSQL Statements + if ( $fields[$myproperty]['FieldType'] == FILTER_TYPE_NUMBER ) + $szUpdateSql = "ALTER TABLE `" . $this->_logStreamConfigObj->DBTableName . "` ADD `" . $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] . "` int(11) NOT NULL DEFAULT '0'"; + if ( $fields[$myproperty]['FieldType'] == FILTER_TYPE_STRING ) + $szUpdateSql = "ALTER TABLE `" . $this->_logStreamConfigObj->DBTableName . "` ADD `" . $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] . "` varchar(60) NULL"; + if ( $fields[$myproperty]['FieldType'] == FILTER_TYPE_DATE ) + $szUpdateSql = "ALTER TABLE `" . $this->_logStreamConfigObj->DBTableName . "` ADD `" . $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] . "` datetime NOT NULL DEFAULT '0000-00-00 00:00:00'"; + } + else if ( $this->_logStreamConfigObj->DBType == DB_PGSQL ) + { + // MYSQL Statements + if ( $fields[$myproperty]['FieldType'] == FILTER_TYPE_NUMBER ) + $szUpdateSql = "ALTER TABLE " . $this->_logStreamConfigObj->DBTableName . " ADD " . $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] . " int NOT NULL DEFAULT '0'"; + if ( $fields[$myproperty]['FieldType'] == FILTER_TYPE_STRING ) + $szUpdateSql = "ALTER TABLE " . $this->_logStreamConfigObj->DBTableName . " ADD " . $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] . " varchar(60) NULL"; + if ( $fields[$myproperty]['FieldType'] == FILTER_TYPE_DATE ) + $szUpdateSql = "ALTER TABLE " . $this->_logStreamConfigObj->DBTableName . " ADD " . $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] . " timestamp without time zone NULL"; + } + else if ( $this->_logStreamConfigObj->DBType == DB_MSSQL ) + { + // MYSQL Statements + if ( $fields[$myproperty]['FieldType'] == FILTER_TYPE_NUMBER ) + $szUpdateSql = "ALTER TABLE " . $this->_logStreamConfigObj->DBTableName . " ADD " . $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] . " INT NOT NULL DEFAULT '0'"; + if ( $fields[$myproperty]['FieldType'] == FILTER_TYPE_STRING ) + $szUpdateSql = "ALTER TABLE " . $this->_logStreamConfigObj->DBTableName . " ADD " . $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] . " VARCHAR(60) NULL"; + if ( $fields[$myproperty]['FieldType'] == FILTER_TYPE_DATE ) + $szUpdateSql = "ALTER TABLE " . $this->_logStreamConfigObj->DBTableName . " ADD " . $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] . " DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00'"; + } + + // Run SQL Command to add the missing field! + if ( strlen($szUpdateSql) > 0 ) + { + // Update Table schema now! + $myQuery = $this->_dbhandle->query($szUpdateSql); + if (!$myQuery) { // Return failure! - $this->PrintDebugError("ER_BAD_FIELD_ERROR - Field '" . $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] . "' is missing has to be added manually to the database layout!'"); + $this->PrintDebugError("ER_BAD_FIELD_ERROR - Dynamically Adding field '" . $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] . "' with Statement failed: '" . $szUpdateSql . "'"); return ERROR_DB_DBFIELDNOTFOUND; } + else // Free query now + $myQuery->closeCursor(); + } + else + { + // Return failure! + $this->PrintDebugError("ER_BAD_FIELD_ERROR - Field '" . $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] . "' is missing and failed to be added automatically! The fields has to be added manually to the database layout!'"); + + global $extraErrorDescription; + $extraErrorDescription = "Field '" . $dbmapping[$szTableType]['DBMAPPINGS'][$myproperty] . "' was missing and has been automatically added to the database layout."; + + return ERROR_DB_DBFIELDNOTFOUND; } } + } - // Reached this point means success! - return SUCCESS; + // Reached this point means success! + return SUCCESS; + } + + + /* + * Helper function to return a list of Indexes for the logstream table + */ + private function GetIndexesAsArray() + { + global $querycount; + + // Verify database connection (This also opens the database!) + $res = $this->Verify(); + if ( $res != SUCCESS ) + return $res; + + // Init Array + $arrIndexKeys = array(); + + // Create SQL and Get INDEXES for table! + if ( $this->_logStreamConfigObj->DBType == DB_MYSQL ) + $szSql = "SHOW INDEX FROM " . $this->_logStreamConfigObj->DBTableName; + else if ( $this->_logStreamConfigObj->DBType == DB_PGSQL ) + $szSql = "SELECT c.relname AS \"Key_name\" FROM pg_catalog.pg_class c JOIN pg_catalog.pg_index i ON i.indexrelid = c.oid JOIN pg_catalog.pg_class t ON i.indrelid = t.oid WHERE c.relkind = 'i' AND t.relname = 'systemevents' AND c.relname LIKE '%idx%'"; + else if ( $this->_logStreamConfigObj->DBType == DB_MSSQL ) + $szSql = "SELECT sysindexes.name AS Key_name FROM sysobjects, sysindexes WHERE sysobjects.xtype='U' AND sysindexes.id=object_id(sysobjects.name) and sysobjects.name='" . $this->_logStreamConfigObj->DBTableName . "' ORDER BY sysobjects.name ASC"; + else + // Not supported in this case! + return null; + + OutputDebugMessage("LogStreamPDO|GetIndexesAsArray: List Indexes for '" . $this->_logStreamConfigObj->DBTableName . "' - " . $szSql, DEBUG_ULTRADEBUG); + $myQuery = $this->_dbhandle->query($szSql); + if ($myQuery) + { + // Loop through results + while ( $myRow = $myQuery->fetch(PDO::FETCH_ASSOC) ) + { + // Add to index keys + if ( $this->_logStreamConfigObj->DBType == DB_PGSQL || $this->_logStreamConfigObj->DBType == DB_MSSQL ) + $arrIndexKeys[] = str_replace( "_idx", "", strtolower($myRow['Key_name']) ); + else + $arrIndexKeys[] = strtolower($myRow['Key_name']); + } + + // Free query now + $myQuery->closeCursor(); + + // Increment for the Footer Stats + $querycount++; + } + + // return Array + return $arrIndexKeys; + } + + + /* + * Helper function to return a list of Fields from the logstream table + */ + private function GetFieldsAsArray() + { + global $querycount; + + // Verify database connection (This also opens the database!) + $res = $this->Verify(); + if ( $res != SUCCESS ) + return $res; + + // Init Array + $arrFieldKeys = array(); + + // Create SQL and Get FIELDS for table! + if ( $this->_logStreamConfigObj->DBType == DB_MYSQL ) + $szSql = "SHOW FIELDS FROM " . $this->_logStreamConfigObj->DBTableName; + else if ( $this->_logStreamConfigObj->DBType == DB_PGSQL ) + $szSql = "SELECT column_name as \"Field\" FROM information_schema.COLUMNS WHERE table_name = '" . $this->_logStreamConfigObj->DBTableName . "'"; + else if ( $this->_logStreamConfigObj->DBType == DB_MSSQL ) + $szSql = "SELECT syscolumns.name AS Field FROM sysobjects JOIN syscolumns ON sysobjects.id = syscolumns.id WHERE sysobjects.xtype='U' AND sysobjects.name='" . $this->_logStreamConfigObj->DBTableName . "'"; + else + // Not supported in this case! + return null; + + OutputDebugMessage("LogStreamPDO|GetFieldsAsArray: List Columns for '" . $this->_logStreamConfigObj->DBTableName . "' - " . $szSql, DEBUG_ULTRADEBUG); + $myQuery = $this->_dbhandle->query($szSql); + if ($myQuery) + { + // Loop through results + while ( $myRow = $myQuery->fetch(PDO::FETCH_ASSOC) ) + { + // Add to index keys + $arrFieldKeys[] = strtolower($myRow['Field']); + } + + // Free query now + $myQuery->closeCursor(); + + // Increment for the Footer Stats + $querycount++; } else - $this->PrintDebugError("ER_BAD_FIELD_ERROR - SQL Statement: ". $errdesc[2]); - return ERROR_DB_DBFIELDNOTFOUND; + $this->PrintDebugError("ERROR_DB_QUERYFAILED - GetFieldsAsArray SQL '" . $szSql . "' failed!"); + + + // return Array + return $arrFieldKeys; + } + + + /* + * Helper function to return a list of Indexes for the logstream table + */ + private function GetTriggersAsArray() + { + global $querycount; + + // Verify database connection (This also opens the database!) + $res = $this->Verify(); + if ( $res != SUCCESS ) + return $res; + + // Init Array + $arrIndexTriggers = array(); + + // Create SQL and Get INDEXES for table! + if ( $this->_logStreamConfigObj->DBType == DB_MYSQL ) + $szSql = "SHOW TRIGGERS"; + else if ( $this->_logStreamConfigObj->DBType == DB_PGSQL ) + $szSql = "SELECT tgname as \"Trigger\" from pg_trigger;"; + else if ( $this->_logStreamConfigObj->DBType == DB_MSSQL ) + $szSql = "SELECT B.Name as TableName,A.name AS 'Trigger' FROM sysobjects A,sysobjects B WHERE A.xtype='TR' AND A.parent_obj = B.id"; // AND B.Name='systemevents'"; + else + // Not supported in this case! + return null; + + OutputDebugMessage("LogStreamPDO|GetTriggersAsArray: List Triggers for '" . $this->_logStreamConfigObj->DBTableName . "' - " . $szSql, DEBUG_ULTRADEBUG); + $myQuery = $this->_dbhandle->query($szSql); + if ($myQuery) + { + // Loop through results + while ( $myRow = $myQuery->fetch(PDO::FETCH_ASSOC) ) + { + // Add to index keys + $arrIndexTriggers[] = strtolower($myRow['Trigger']); + } + + // Free query now + $myQuery->closeCursor(); + + // Increment for the Footer Stats + $querycount++; + } + + // return Array + return $arrIndexTriggers; } diff --git a/src/classes/reports/report.class.php b/src/classes/reports/report.class.php index 75c3e6e..a84f799 100644 --- a/src/classes/reports/report.class.php +++ b/src/classes/reports/report.class.php @@ -117,6 +117,25 @@ abstract class Report { */ public abstract function InitAdvancedSettings(); + + /** + * If the reports needs to optimize the logstream, it is checked and verified by this function + */ + public abstract function CheckLogStreamSource( $mySourceID ); + + + /** + * If the reports needs INDEXES, these are created by this function + */ + public abstract function CreateLogStreamIndexes( $mySourceID ); + + + /** + * If the reports needs a TRIGGER, these are created by this function + */ + public abstract function CreateLogStreamTrigger( $mySourceID ); + + /** * verifyDataSource, verifies if data is accessable and * contains what we need @@ -637,5 +656,241 @@ abstract class Report { return $res; } + + /** + * If the reports needs to optimize the logstream, it is checked and verified by this function + */ + public function CheckLogStreamSourceByPropertyArray( $mySourceID, $arrProperties, $myTriggerProperty ) + { + global $content, $fields; + $res = SUCCESS; + + if ( $this->_streamCfgObj == null ) + { + if ( isset($content['Sources'][$mySourceID]) ) + { + // Obtain and get the Config Object + $this->_streamCfgObj = $content['Sources'][$mySourceID]['ObjRef']; + + // Return success if logstream is FILE based! + if ( $content['Sources'][$mySourceID]['SourceType'] == SOURCE_DISK ) + return SUCCESS; + } + else + return ERROR_SOURCENOTFOUND; + } + + if ( $this->_streamObj == null ) + { + // Create LogStream Object + $this->_streamObj = $this->_streamCfgObj->LogStreamFactory($this->_streamCfgObj); + } + + // Check datasource and return result + $res = $this->_streamObj->Verify(); + if ( $res == SUCCESS ) + { + // Will check if all necessary fields are available! + $res = $this->_streamObj->VerifyFields( $this->_arrProperties ); + if ($res != SUCCESS ) + return $res; + + // Will check if certain INDEXES do exists for database logstream! + $res = $this->_streamObj->VerifyIndexes( $arrProperties ); + if ($res != SUCCESS ) + return $res; + + // Will check if checksum field is correctly configured for database logstream! + $res = $this->_streamObj->VerifyChecksumField( ); + if ($res != SUCCESS ) + return $res; + + // Will check if TRIGGERS are installed! Requires SUPER access in database logstream! + $res = $this->_streamObj->VerifyChecksumTrigger( $myTriggerProperty ); + if ($res != SUCCESS ) + return $res; + } + + // return results! + return $res; + } + + + /** + * If the reports needs extra FIELDS, they are created by this function + */ + public function CreateMissingLogStreamFields( $mySourceID ) + { + global $content, $fields; + $res = SUCCESS; + + if ( $this->_streamCfgObj == null ) + { + if ( isset($content['Sources'][$mySourceID]) ) + { + // Obtain and get the Config Object + $this->_streamCfgObj = $content['Sources'][$mySourceID]['ObjRef']; + + // Return success if logstream is FILE based! + if ( $content['Sources'][$mySourceID]['SourceType'] == SOURCE_DISK ) + return SUCCESS; + } + else + return ERROR_SOURCENOTFOUND; + } + + if ( $this->_streamObj == null ) + { + // Create LogStream Object + $this->_streamObj = $this->_streamCfgObj->LogStreamFactory($this->_streamCfgObj); + } + + // Check datasource and return result + $res = $this->_streamObj->Verify(); + if ( $res == SUCCESS ) + { + // Will add missing fields for this database logstream ! + $res = $this->_streamObj->CreateMissingFields( $this->_arrProperties ); + if ($res != SUCCESS ) + return $res; + } + + // return results! + return $res; + } + + + /** + * If the reports needs INDEXES, they are created by this function + */ + public function CreateLogStreamIndexesByPropertyArray( $mySourceID, $arrProperties ) + { + global $content, $fields; + $res = SUCCESS; + + if ( $this->_streamCfgObj == null ) + { + if ( isset($content['Sources'][$mySourceID]) ) + { + // Obtain and get the Config Object + $this->_streamCfgObj = $content['Sources'][$mySourceID]['ObjRef']; + + // Return success if logstream is FILE based! + if ( $content['Sources'][$mySourceID]['SourceType'] == SOURCE_DISK ) + return SUCCESS; + } + else + return ERROR_SOURCENOTFOUND; + } + + if ( $this->_streamObj == null ) + { + // Create LogStream Object + $this->_streamObj = $this->_streamCfgObj->LogStreamFactory($this->_streamCfgObj); + } + + // Check datasource and return result + $res = $this->_streamObj->Verify(); + if ( $res == SUCCESS ) + { + // Will check if certain INDEXES do exists for database logstream classes! + $res = $this->_streamObj->CreateMissingIndexes( $arrProperties ); + if ($res != SUCCESS ) + return $res; + } + + // return results! + return $res; + } + + + /** + * If the reports needs INDEXES, these are created by this function + */ + public function CreateLogStreamTriggerByPropertyArray( $mySourceID, $myTriggerProperty, $myChecksumProperty ) + { + global $content, $fields; + $res = SUCCESS; + + if ( $this->_streamCfgObj == null ) + { + if ( isset($content['Sources'][$mySourceID]) ) + { + // Obtain and get the Config Object + $this->_streamCfgObj = $content['Sources'][$mySourceID]['ObjRef']; + + // Return success if logstream is FILE based! + if ( $content['Sources'][$mySourceID]['SourceType'] == SOURCE_DISK ) + return SUCCESS; + } + else + return ERROR_SOURCENOTFOUND; + } + + if ( $this->_streamObj == null ) + { + // Create LogStream Object + $this->_streamObj = $this->_streamCfgObj->LogStreamFactory($this->_streamCfgObj); + } + + // Check datasource and return result + $res = $this->_streamObj->Verify(); + if ( $res == SUCCESS ) + { + // Will check if certain INDEXES do exists for database logstream classes! + $res = $this->_streamObj->CreateMissingTrigger( $myTriggerProperty, $myChecksumProperty ); + if ($res != SUCCESS ) + return $res; + } + + // return results! + return $res; + } + + + /** + * If the reports needs INDEXES, these are created by this function + */ + public function ChangeChecksumFieldUnsigned( $mySourceID ) + { + global $content, $fields; + $res = SUCCESS; + + if ( $this->_streamCfgObj == null ) + { + if ( isset($content['Sources'][$mySourceID]) ) + { + // Obtain and get the Config Object + $this->_streamCfgObj = $content['Sources'][$mySourceID]['ObjRef']; + + // Return success if logstream is FILE based! + if ( $content['Sources'][$mySourceID]['SourceType'] == SOURCE_DISK ) + return SUCCESS; + } + else + return ERROR_SOURCENOTFOUND; + } + + if ( $this->_streamObj == null ) + { + // Create LogStream Object + $this->_streamObj = $this->_streamCfgObj->LogStreamFactory($this->_streamCfgObj); + } + + // Check datasource and return result + $res = $this->_streamObj->Verify(); + if ( $res == SUCCESS ) + { + // Will change the Checksum Field to UNSIGNED INT + $res = $this->_streamObj->ChangeChecksumFieldUnsigned( ); + if ($res != SUCCESS ) + return $res; + } + + // return results! + return $res; + } + + } ?> \ No newline at end of file diff --git a/src/classes/reports/report.eventlog.eventsummary.class.php b/src/classes/reports/report.eventlog.eventsummary.class.php index 78c052f..87fe38e 100644 --- a/src/classes/reports/report.eventlog.eventsummary.class.php +++ b/src/classes/reports/report.eventlog.eventsummary.class.php @@ -160,13 +160,13 @@ class Report_eventsummary extends Report { $tmpReportData['DisplayName'] = GetSeverityDisplayName( $tmpReportData[SYSLOG_SEVERITY] ); $tmpReportData['bgcolor'] = $severity_colors[ $tmpReportData[SYSLOG_SEVERITY] ]; - $iTotalEvents += $tmpReportData['ItemCount']; + $iTotalEvents += $tmpReportData['itemcount']; } // Prepent Item with totalevents count $totalItem['DisplayName'] = "Total Events"; $totalItem['bgcolor'] = "#999999"; - $totalItem['ItemCount'] = $iTotalEvents; + $totalItem['itemcount'] = $iTotalEvents; // Prepent to array array_unshift( $content["report_summary"], $totalItem ); @@ -289,6 +289,44 @@ class Report_eventsummary extends Report { } + /* + * Implementation of CheckLogStreamSource + */ + public function CheckLogStreamSource( $mySourceID ) + { + // Call basic report Check function + $res = $this->CheckLogStreamSourceByPropertyArray( $mySourceID, array(SYSLOG_HOST, MISC_CHECKSUM, SYSLOG_DATE, SYSLOG_SEVERITY, SYSLOG_MESSAGETYPE), SYSLOG_MESSAGE ); + + // return results! + return $res; + } + + + /* + * Implementation of CreateLogStreamIndexes | Will create missing INDEXES + */ + public function CreateLogStreamIndexes( $mySourceID ) + { + // Call basic report Check function + $res = $this->CreateLogStreamIndexesByPropertyArray( $mySourceID, array(SYSLOG_HOST, MISC_CHECKSUM, SYSLOG_DATE, SYSLOG_SEVERITY, SYSLOG_MESSAGETYPE) ); + + // return results! + return $res; + } + + + /* + * Implementation of CreateLogStreamIndexes | Will create missing TRIGGER + */ + public function CreateLogStreamTrigger( $mySourceID ) + { + // Call basic report Check function + $res = $this->CreateLogStreamTriggerByPropertyArray( $mySourceID, SYSLOG_MESSAGE, MISC_CHECKSUM ); + + // return results! + return $res; + } + // --- Private functions... /** @@ -296,15 +334,50 @@ class Report_eventsummary extends Report { */ private function ConsolidateEventsPerHost( $arrHosts ) { - global $content, $gl_starttime; + global $content, $gl_starttime, $fields; // Now open the stream for data processing $res = $this->_streamObj->Open( $this->_arrProperties, true ); if ( $res == SUCCESS ) { - // Set reading direction -// $this->_streamObj->SetReadDirection( EnumReadDirection::Backward ); + // --- New Method to consolidate data! + // TimeStats + $nowtime = microtime_float(); + $content["report_rendertime"] .= number_format($nowtime - $gl_starttime, 2, '.', '') . "s "; + // Update all Checksums first! + $this->_streamObj->UpdateAllMessageChecksum(); + + // TimeStats + $nowtime = microtime_float(); + $content["report_rendertime"] .= number_format($nowtime - $gl_starttime, 2, '.', '') . "s "; + + foreach ( $arrHosts as $myHost ) + { + // Set custom filters + $this->_streamObj->ResetFilters(); + $this->_streamObj->SetFilter( $this->_filterString . " " . $fields[SYSLOG_MESSAGETYPE]['SearchField'] . ":=" . IUT_NT_EventReport . ",=" . IUT_WEVTMONV2 . " " . $fields[SYSLOG_HOST]['SearchField'] . ":=" . $myHost ); + + // Set Host Item Basics if not set yet + $content["report_consdata"][ $myHost ][SYSLOG_HOST] = $myHost; + + // Get Data for single host + $content["report_consdata"][ $myHost ]['cons_events'] = $this->_streamObj->ConsolidateDataByField( MISC_CHECKSUM, $this->_maxEventsPerHost, MISC_CHECKSUM, SORTING_ORDER_DESC, null, true, true ); + //print_r ($fields[SYSLOG_MESSAGE]); + foreach ( $content["report_consdata"][ $myHost ]['cons_events'] as &$myConsData ) + { + // Set Basic data entries + if (!isset( $content['filter_severity_list'][$myConsData[SYSLOG_SEVERITY]] )) + $myConsData[SYSLOG_SEVERITY] = SYSLOG_NOTICE; // Set default in this case + } + } + + // TimeStats + $nowtime = microtime_float(); + $content["report_rendertime"] .= number_format($nowtime - $gl_starttime, 2, '.', '') . "s "; + // --- + +/* OLD CODE // Init uid helper $uID = UID_UNKNOWN; @@ -349,7 +422,7 @@ class Report_eventsummary extends Report { if ( isset($content["report_consdata"][ $logArray[SYSLOG_HOST] ]['cons_events'][ $strChecksum ]) ) { // Increment counter and set First/Last Event date - $content["report_consdata"][ $logArray[SYSLOG_HOST] ]['cons_events'][ $strChecksum ]['ItemCount']++; + $content["report_consdata"][ $logArray[SYSLOG_HOST] ]['cons_events'][ $strChecksum ]['itemcount']++; // Set FirstEvent date if necessary! if ( $logArray[SYSLOG_DATE][EVTIME_TIMESTAMP] < $content["report_consdata"][ $logArray[SYSLOG_HOST] ]['cons_events'][ $strChecksum ]['FirstEvent_Date'][EVTIME_TIMESTAMP] ) @@ -368,7 +441,7 @@ class Report_eventsummary extends Report { $content["report_consdata"][ $logArray[SYSLOG_HOST] ]['cons_events'][ $strChecksum ][SYSLOG_MESSAGE] = $logArray[SYSLOG_MESSAGE]; // Set Counter and First/Last Event date - $content["report_consdata"][ $logArray[SYSLOG_HOST] ]['cons_events'][ $strChecksum ]['ItemCount'] = 1; + $content["report_consdata"][ $logArray[SYSLOG_HOST] ]['cons_events'][ $strChecksum ]['itemcount'] = 1; $content["report_consdata"][ $logArray[SYSLOG_HOST] ]['cons_events'][ $strChecksum ]['FirstEvent_Date'] = $logArray[SYSLOG_DATE]; $content["report_consdata"][ $logArray[SYSLOG_HOST] ]['cons_events'][ $strChecksum ]['LastEvent_Date'] = $logArray[SYSLOG_DATE]; } @@ -381,59 +454,74 @@ class Report_eventsummary extends Report { // TimeStats $nowtime = microtime_float(); $content["report_rendertime"] .= number_format($nowtime - $gl_starttime, 2, '.', '') . "s "; + } +*/ - // Start Postprocessing - foreach( $content["report_consdata"] as &$tmpConsolidatedComputer ) + // Start Postprocessing + foreach( $content["report_consdata"] as &$tmpConsolidatedComputer ) + { + // First use callback function to sort array + uasort($tmpConsolidatedComputer['cons_events'], "MultiSortArrayByItemCountDesc"); + + // Remove entries according to _maxEventsPerHost + if ( count($tmpConsolidatedComputer['cons_events']) > $this->_maxEventsPerHost ) { - // First use callback function to sort array - uasort($tmpConsolidatedComputer['cons_events'], "MultiSortArrayByItemCountDesc"); + $iDropCount = 0; + + do + { + array_pop($tmpConsolidatedComputer['cons_events']); + $iDropCount++; + } while ( count($tmpConsolidatedComputer['cons_events']) > $this->_maxEventsPerHost ); - // Remove entries according to _maxEventsPerHost - if ( count($tmpConsolidatedComputer['cons_events']) > $this->_maxEventsPerHost ) + // Append a dummy entry which shows count of all other events + if ( $iDropCount > 0 ) { - $iDropCount = 0; + $lastEntry[SYSLOG_SEVERITY] = SYSLOG_NOTICE; + $lastEntry[SYSLOG_EVENT_ID] = "-"; + $lastEntry[SYSLOG_EVENT_SOURCE] = $content['LN_GEN_ALL_OTHER_EVENTS']; + $lastEntry[SYSLOG_MESSAGE] = $content['LN_GEN_ALL_OTHER_EVENTS']; + $lastEntry['itemcount'] = $iDropCount; + $lastEntry['FirstEvent_Date'] = "-"; + $lastEntry['LastEvent_Date'] = "-"; - do - { - array_pop($tmpConsolidatedComputer['cons_events']); - $iDropCount++; - } while ( count($tmpConsolidatedComputer['cons_events']) > $this->_maxEventsPerHost ); - - // Append a dummy entry which shows count of all other events - if ( $iDropCount > 0 ) - { - $lastEntry[SYSLOG_SEVERITY] = SYSLOG_NOTICE; - $lastEntry[SYSLOG_EVENT_ID] = "-"; - $lastEntry[SYSLOG_EVENT_SOURCE] = $content['LN_GEN_ALL_OTHER_EVENTS']; - $lastEntry[SYSLOG_MESSAGE] = $content['LN_GEN_ALL_OTHER_EVENTS']; - $lastEntry['ItemCount'] = $iDropCount; - $lastEntry['FirstEvent_Date'] = "-"; - $lastEntry['LastEvent_Date'] = "-"; - - $tmpConsolidatedComputer['cons_events'][] = $lastEntry; - } - } - - // TimeStats - $nowtime = microtime_float(); - $content["report_rendertime"] .= number_format($nowtime - $gl_starttime, 2, '.', '') . "s "; - - // PostProcess Events! - foreach( $tmpConsolidatedComputer["cons_events"] as &$tmpMyEvent ) - { - $tmpMyEvent['FirstEvent_Date_Formatted'] = GetFormatedDate( $tmpMyEvent['FirstEvent_Date'] ); - $tmpMyEvent['LastEvent_Date_Formatted'] = GetFormatedDate( $tmpMyEvent['LastEvent_Date'] ); - $tmpMyEvent['syslogseverity_text'] = $content['filter_severity_list'][ $tmpMyEvent['syslogseverity'] ]["DisplayName"]; + $tmpConsolidatedComputer['cons_events'][] = $lastEntry; } } + + // TimeStats + $nowtime = microtime_float(); + $content["report_rendertime"] .= number_format($nowtime - $gl_starttime, 2, '.', '') . "s "; + + // PostProcess Events! + foreach( $tmpConsolidatedComputer["cons_events"] as &$tmpMyEvent ) + { + $tmpMyEvent['FirstEvent_Date_Formatted'] = GetFormatedDate( $tmpMyEvent['firstoccurrence_date'] ); + $tmpMyEvent['LastEvent_Date_Formatted'] = GetFormatedDate( $tmpMyEvent['lastoccurrence_date'] ); + $tmpMyEvent['syslogseverity_text'] = $content['filter_severity_list'][ $tmpMyEvent['syslogseverity'] ]["DisplayName"]; + $tmpMyEvent['syslogseverity_bgcolor'] = $this->GetSeverityBGColor($tmpMyEvent['syslogseverity']); + } } - else - return $ret; + // --- } // Work done! return SUCCESS; } + + /* + * Helper function to obtain Severity background color + */ + private function GetSeverityBGColor( $nSeverity ) + { + global $severity_colors; + + if ( isset( $severity_colors[$nSeverity] ) ) + return $severity_colors[$nSeverity]; + else + return $severity_colors[SYSLOG_INFO]; //Default + } + } ?> \ No newline at end of file diff --git a/src/classes/reports/report.eventlog.eventsummary/report.eventlog.eventsummary.template.html b/src/classes/reports/report.eventlog.eventsummary/report.eventlog.eventsummary.template.html index 8796d34..7efd33a 100644 --- a/src/classes/reports/report.eventlog.eventsummary/report.eventlog.eventsummary.template.html +++ b/src/classes/reports/report.eventlog.eventsummary/report.eventlog.eventsummary.template.html @@ -56,7 +56,7 @@ {DisplayName} - {ItemCount} + {itemcount} @@ -68,7 +68,7 @@ - {FROMHOST}({ItemCount}), + {FROMHOST}({itemcount}), @@ -91,33 +91,32 @@

{FROMHOST}

- +
+ - + + + + + + - + - - - - - - - diff --git a/src/classes/reports/report.eventlog.eventsummary/report.eventlog.eventsummary.template.pdf b/src/classes/reports/report.eventlog.eventsummary/report.eventlog.eventsummary.template.pdf index 0fae148..61bc6ef 100644 --- a/src/classes/reports/report.eventlog.eventsummary/report.eventlog.eventsummary.template.pdf +++ b/src/classes/reports/report.eventlog.eventsummary/report.eventlog.eventsummary.template.pdf @@ -38,7 +38,7 @@ - +
{ln_report_number}{ln_report_count} {ln_report_firstevent} {ln_report_lastevent} {ln_report_process} {ln_report_severity} {ln_report_eventid} {ln_report_description}{ln_report_count}
{ZAEHLER}{itemcount}{itemcount} {FirstEvent_Date_Formatted} {LastEvent_Date_Formatted} {sourceproc}{syslogseverity_text}{syslogseverity_text} {id} {msg}{ItemCount}{ItemCount}
{DisplayName}{ItemCount}{itemcount}
@@ -52,7 +52,7 @@ - {FROMHOST}({ItemCount}), + {FROMHOST}({itemcount}), @@ -68,27 +68,27 @@ + - + + + + + + - - - - - - diff --git a/src/classes/reports/report.syslog.syslogsummary.class.php b/src/classes/reports/report.syslog.syslogsummary.class.php index 65386d7..ac70ede 100644 --- a/src/classes/reports/report.syslog.syslogsummary.class.php +++ b/src/classes/reports/report.syslog.syslogsummary.class.php @@ -157,13 +157,13 @@ class Report_syslogsummary extends Report { $tmpReportData['DisplayName'] = $this->GetSeverityDisplayName( $tmpReportData[SYSLOG_SEVERITY] ); $tmpReportData['bgcolor'] = $this->GetSeverityBGColor( $tmpReportData[SYSLOG_SEVERITY] ); // $severity_colors[ $tmpReportData[SYSLOG_SEVERITY] ]; - $iTotalEvents += $tmpReportData['ItemCount']; + $iTotalEvents += $tmpReportData['itemcount']; } // Prepent Item with totalevents count $totalItem['DisplayName'] = "Total Events"; $totalItem['bgcolor'] = "#999999"; - $totalItem['ItemCount'] = $iTotalEvents; + $totalItem['itemcount'] = $iTotalEvents; // Prepent to array array_unshift( $content["report_summary"], $totalItem ); @@ -286,6 +286,44 @@ class Report_syslogsummary extends Report { } + /* + * Implementation of CheckLogStreamSource + */ + public function CheckLogStreamSource( $mySourceID ) + { + // Call basic report Check function + $res = $this->CheckLogStreamSourceByPropertyArray( $mySourceID, array(SYSLOG_HOST, MISC_CHECKSUM, SYSLOG_DATE, SYSLOG_SEVERITY, SYSLOG_MESSAGETYPE), SYSLOG_MESSAGE ); + + // return results! + return $res; + } + + + /* + * Implementation of CreateLogStreamIndexes | Will create missing INDEXES + */ + public function CreateLogStreamIndexes( $mySourceID ) + { + // Call basic report Check function + $res = $this->CreateLogStreamIndexesByPropertyArray( $mySourceID, array(SYSLOG_HOST, MISC_CHECKSUM, SYSLOG_DATE, SYSLOG_SEVERITY, SYSLOG_MESSAGETYPE) ); + + // return results! + return $res; + } + + + /* + * Implementation of CreateLogStreamIndexes | Will create missing INDEXES + */ + public function CreateLogStreamTrigger( $mySourceID ) + { + // Call basic report Check function + $res = $this->CreateLogStreamTriggerByPropertyArray( $mySourceID, SYSLOG_MESSAGE, MISC_CHECKSUM ); + + // return results! + return $res; + } + // --- Private functions... /** @@ -293,15 +331,54 @@ class Report_syslogsummary extends Report { */ private function ConsolidateSyslogmessagesPerHost( $arrHosts ) { - global $content, $gl_starttime; + global $content, $gl_starttime, $fields; // Now open the stream for data processing $res = $this->_streamObj->Open( $this->_arrProperties, true ); if ( $res == SUCCESS ) { - // Set reading direction -// $this->_streamObj->SetReadDirection( EnumReadDirection::Backward ); + // --- New Method to consolidate data! + // TimeStats + $nowtime = microtime_float(); + $content["report_rendertime"] .= number_format($nowtime - $gl_starttime, 2, '.', '') . "s "; + // Update all Checksums first! + $this->_streamObj->UpdateAllMessageChecksum(); + + // TimeStats + $nowtime = microtime_float(); + $content["report_rendertime"] .= number_format($nowtime - $gl_starttime, 2, '.', '') . "s "; + + foreach ( $arrHosts as $myHost ) + { + // Set custom filters + $this->_streamObj->ResetFilters(); + $this->_streamObj->SetFilter( $this->_filterString . " " . $fields[SYSLOG_MESSAGETYPE]['SearchField'] . ":=" . IUT_Syslog . " " . $fields[SYSLOG_HOST]['SearchField'] . ":=" . $myHost ); + + // Set Host Item Basics if not set yet + $content["report_consdata"][ $myHost ][SYSLOG_HOST] = $myHost; + + // Get Data for single host + $content["report_consdata"][ $myHost ]['cons_msgs'] = $this->_streamObj->ConsolidateDataByField( MISC_CHECKSUM, $this->_maxMsgsPerHost, MISC_CHECKSUM, SORTING_ORDER_DESC, null, true, true ); + + //print_r ($fields[SYSLOG_MESSAGE]); + foreach ( $content["report_consdata"][ $myHost ]['cons_msgs'] as &$myConsData ) + { + // Set Basic data entries + if (!isset( $content['filter_facility_list'][$myConsData[SYSLOG_FACILITY]] )) + $myConsData[SYSLOG_FACILITY] = SYSLOG_LOCAL0; // Set default in this case + if (!isset( $content['filter_severity_list'][$myConsData[SYSLOG_SEVERITY]] )) + $myConsData[SYSLOG_SEVERITY] = SYSLOG_NOTICE; // Set default in this case + } + } + + // TimeStats + $nowtime = microtime_float(); + $content["report_rendertime"] .= number_format($nowtime - $gl_starttime, 2, '.', '') . "s "; + // --- + +/* + // --- Old Method! // Init uid helper $uID = UID_UNKNOWN; @@ -346,15 +423,15 @@ class Report_syslogsummary extends Report { if ( isset($content["report_consdata"][ $logArray[SYSLOG_HOST] ]['cons_msgs'][ $strChecksum ]) ) { // Increment counter and set First/Last Event date - $content["report_consdata"][ $logArray[SYSLOG_HOST] ]['cons_msgs'][ $strChecksum ]['ItemCount']++; + $content["report_consdata"][ $logArray[SYSLOG_HOST] ]['cons_msgs'][ $strChecksum ]['itemcount']++; // Set FirstEvent date if necessary! - if ( $logArray[SYSLOG_DATE][EVTIME_TIMESTAMP] < $content["report_consdata"][ $logArray[SYSLOG_HOST] ]['cons_msgs'][ $strChecksum ]['FirstOccurrence_Date'][EVTIME_TIMESTAMP] ) - $content["report_consdata"][ $logArray[SYSLOG_HOST] ]['cons_msgs'][ $strChecksum ]['FirstOccurrence_Date'] = $logArray[SYSLOG_DATE]; + if ( $logArray[SYSLOG_DATE][EVTIME_TIMESTAMP] < $content["report_consdata"][ $logArray[SYSLOG_HOST] ]['cons_msgs'][ $strChecksum ]['firstoccurrence_date'][EVTIME_TIMESTAMP] ) + $content["report_consdata"][ $logArray[SYSLOG_HOST] ]['cons_msgs'][ $strChecksum ]['firstoccurrence_date'] = $logArray[SYSLOG_DATE]; // Set LastEvent date if necessary! - if ( $logArray[SYSLOG_DATE][EVTIME_TIMESTAMP] > $content["report_consdata"][ $logArray[SYSLOG_HOST] ]['cons_msgs'][ $strChecksum ]['LastOccurrence_Date'][EVTIME_TIMESTAMP] ) - $content["report_consdata"][ $logArray[SYSLOG_HOST] ]['cons_msgs'][ $strChecksum ]['LastOccurrence_Date'] = $logArray[SYSLOG_DATE]; + if ( $logArray[SYSLOG_DATE][EVTIME_TIMESTAMP] > $content["report_consdata"][ $logArray[SYSLOG_HOST] ]['cons_msgs'][ $strChecksum ]['lastoccurrence_date'][EVTIME_TIMESTAMP] ) + $content["report_consdata"][ $logArray[SYSLOG_HOST] ]['cons_msgs'][ $strChecksum ]['lastoccurrence_date'] = $logArray[SYSLOG_DATE]; } else { @@ -371,9 +448,9 @@ class Report_syslogsummary extends Report { $content["report_consdata"][ $logArray[SYSLOG_HOST] ]['cons_msgs'][ $strChecksum ][SYSLOG_MESSAGE] = $logArray[SYSLOG_MESSAGE]; // Set Counter and First/Last Event date - $content["report_consdata"][ $logArray[SYSLOG_HOST] ]['cons_msgs'][ $strChecksum ]['ItemCount'] = 1; - $content["report_consdata"][ $logArray[SYSLOG_HOST] ]['cons_msgs'][ $strChecksum ]['FirstOccurrence_Date'] = $logArray[SYSLOG_DATE]; - $content["report_consdata"][ $logArray[SYSLOG_HOST] ]['cons_msgs'][ $strChecksum ]['LastOccurrence_Date'] = $logArray[SYSLOG_DATE]; + $content["report_consdata"][ $logArray[SYSLOG_HOST] ]['cons_msgs'][ $strChecksum ]['itemcount'] = 1; + $content["report_consdata"][ $logArray[SYSLOG_HOST] ]['cons_msgs'][ $strChecksum ]['firstoccurrence_date'] = $logArray[SYSLOG_DATE]; + $content["report_consdata"][ $logArray[SYSLOG_HOST] ]['cons_msgs'][ $strChecksum ]['lastoccurrence_date'] = $logArray[SYSLOG_DATE]; } } @@ -384,57 +461,59 @@ class Report_syslogsummary extends Report { // TimeStats $nowtime = microtime_float(); $content["report_rendertime"] .= number_format($nowtime - $gl_starttime, 2, '.', '') . "s "; - - // Start Postprocessing - foreach( $content["report_consdata"] as &$tmpConsolidatedComputer ) - { - // First use callback function to sort array - uasort($tmpConsolidatedComputer['cons_msgs'], "MultiSortArrayByItemCountDesc"); - - // Remove entries according to _maxMsgsPerHost - if ( count($tmpConsolidatedComputer['cons_msgs']) > $this->_maxMsgsPerHost ) - { - $iDropCount = 0; - - do - { - array_pop($tmpConsolidatedComputer['cons_msgs']); - $iDropCount++; - } while ( count($tmpConsolidatedComputer['cons_msgs']) > $this->_maxMsgsPerHost ); - - // Append a dummy entry which shows count of all other events - if ( $iDropCount > 0 ) - { - $lastEntry[SYSLOG_SEVERITY] = SYSLOG_NOTICE; - $lastEntry[SYSLOG_FACILITY] = SYSLOG_LOCAL0; - $lastEntry[SYSLOG_SYSLOGTAG] = $content['LN_GEN_ALL_OTHER_EVENTS']; - $lastEntry[SYSLOG_MESSAGE] = $content['LN_GEN_ALL_OTHER_EVENTS']; - $lastEntry['ItemCount'] = $iDropCount; - $lastEntry['FirstOccurrence_Date'] = "-"; - $lastEntry['LastOccurrence_Date'] = "-"; - - $tmpConsolidatedComputer['cons_msgs'][] = $lastEntry; - } - } - - // TimeStats - $nowtime = microtime_float(); - $content["report_rendertime"] .= number_format($nowtime - $gl_starttime, 2, '.', '') . "s "; - - // PostProcess Events! - foreach( $tmpConsolidatedComputer["cons_msgs"] as &$tmpMyEvent ) - { - $tmpMyEvent['FirstOccurrence_Date_Formatted'] = GetFormatedDate( $tmpMyEvent['FirstOccurrence_Date'] ); - $tmpMyEvent['LastOccurrence_Date_Formatted'] = GetFormatedDate( $tmpMyEvent['LastOccurrence_Date'] ); - $tmpMyEvent['syslogseverity_text'] = $this->GetSeverityDisplayName($tmpMyEvent['syslogseverity']); //$content['filter_severity_list'][ $tmpMyEvent['syslogseverity'] ]["DisplayName"]; - $tmpMyEvent['syslogfacility_text'] = $this->GetFacilityDisplayName($tmpMyEvent['syslogfacility']); //$content['filter_facility_list'][ $tmpMyEvent['syslogfacility'] ]["DisplayName"]; - $tmpMyEvent['syslogseverity_bgcolor'] = $this->GetSeverityBGColor($tmpMyEvent['syslogseverity']); - $tmpMyEvent['syslogfacility_bgcolor'] = $this->GetSeverityBGColor($tmpMyEvent['syslogfacility']); - } - } } else return $ret; +*/ + + // --- Start Postprocessing + foreach( $content["report_consdata"] as &$tmpConsolidatedComputer ) + { + // First use callback function to sort array + uasort($tmpConsolidatedComputer['cons_msgs'], "MultiSortArrayByItemCountDesc"); + + // Remove entries according to _maxMsgsPerHost + if ( count($tmpConsolidatedComputer['cons_msgs']) > $this->_maxMsgsPerHost ) + { + $iDropCount = 0; + + do + { + array_pop($tmpConsolidatedComputer['cons_msgs']); + $iDropCount++; + } while ( count($tmpConsolidatedComputer['cons_msgs']) > $this->_maxMsgsPerHost ); + + // Append a dummy entry which shows count of all other events + if ( $iDropCount > 0 ) + { + $lastEntry[SYSLOG_SEVERITY] = SYSLOG_NOTICE; + $lastEntry[SYSLOG_FACILITY] = SYSLOG_LOCAL0; + $lastEntry[SYSLOG_SYSLOGTAG] = $content['LN_GEN_ALL_OTHER_EVENTS']; + $lastEntry[SYSLOG_MESSAGE] = $content['LN_GEN_ALL_OTHER_EVENTS']; + $lastEntry['itemcount'] = $iDropCount; + $lastEntry['firstoccurrence_date'] = "-"; + $lastEntry['lastoccurrence_date'] = "-"; + + $tmpConsolidatedComputer['cons_msgs'][] = $lastEntry; + } + } + + // TimeStats + $nowtime = microtime_float(); + $content["report_rendertime"] .= number_format($nowtime - $gl_starttime, 2, '.', '') . "s "; + + // PostProcess Events! + foreach( $tmpConsolidatedComputer["cons_msgs"] as &$tmpMyEvent ) + { + $tmpMyEvent['FirstOccurrence_Date_Formatted'] = GetFormatedDate( $tmpMyEvent['firstoccurrence_date'] ); + $tmpMyEvent['LastOccurrence_Date_Formatted'] = GetFormatedDate( $tmpMyEvent['lastoccurrence_date'] ); + $tmpMyEvent['syslogseverity_text'] = $this->GetSeverityDisplayName($tmpMyEvent['syslogseverity']); //$content['filter_severity_list'][ $tmpMyEvent['syslogseverity'] ]["DisplayName"]; + $tmpMyEvent['syslogfacility_text'] = $this->GetFacilityDisplayName($tmpMyEvent['syslogfacility']); //$content['filter_facility_list'][ $tmpMyEvent['syslogfacility'] ]["DisplayName"]; + $tmpMyEvent['syslogseverity_bgcolor'] = $this->GetSeverityBGColor($tmpMyEvent['syslogseverity']); + $tmpMyEvent['syslogfacility_bgcolor'] = $this->GetSeverityBGColor($tmpMyEvent['syslogfacility']); + } + } + // --- } // Work done! diff --git a/src/classes/reports/report.syslog.syslogsummary/report.syslog.syslogsummary.template.html b/src/classes/reports/report.syslog.syslogsummary/report.syslog.syslogsummary.template.html index 766b4e2..5f7d9b6 100644 --- a/src/classes/reports/report.syslog.syslogsummary/report.syslog.syslogsummary.template.html +++ b/src/classes/reports/report.syslog.syslogsummary/report.syslog.syslogsummary.template.html @@ -57,7 +57,7 @@ - +
{ln_report_number}{ln_report_count} {ln_report_firstevent} {ln_report_lastevent} {ln_report_process} {ln_report_severity} {ln_report_eventid}{ln_report_count}
{ZAEHLER}{itemcount}{itemcount} {FirstEvent_Date_Formatted} {LastEvent_Date_Formatted} {sourceproc} {syslogseverity_text} {id}{ItemCount}{ItemCount}
{ln_report_description}
{DisplayName}{ItemCount}{itemcount}
@@ -69,7 +69,7 @@ - {FROMHOST}({ItemCount}), + {FROMHOST}({itemcount}), @@ -92,33 +92,32 @@

{FROMHOST}

- +
+ - + + + + + + - - - - - - - diff --git a/src/classes/reports/report.syslog.syslogsummary/report.syslog.syslogsummary.template.pdf b/src/classes/reports/report.syslog.syslogsummary/report.syslog.syslogsummary.template.pdf index 6daa3c9..ca1cc94 100644 --- a/src/classes/reports/report.syslog.syslogsummary/report.syslog.syslogsummary.template.pdf +++ b/src/classes/reports/report.syslog.syslogsummary/report.syslog.syslogsummary.template.pdf @@ -38,7 +38,7 @@ - +
{ln_report_number}{ln_report_count} {ln_report_firstoccurrence} {ln_report_lastoccurrence} {ln_report_severity} {ln_report_facility} {ln_report_syslogtag} {ln_report_description}{ln_report_count}
{ZAEHLER}{itemcount}{itemcount} {FirstOccurrence_Date_Formatted} {LastOccurrence_Date_Formatted} {syslogseverity_text} {syslogfacility_text} {syslogtag} {msg}{ItemCount}{ItemCount}
{DisplayName}{ItemCount}{itemcount}
@@ -52,7 +52,7 @@ - {FROMHOST}({ItemCount}), + {FROMHOST}({itemcount}), @@ -68,27 +68,27 @@ + - + + + + + + - - - - - -
{ln_report_number}{ln_report_count} {ln_report_firstoccurrence} {ln_report_lastoccurrence} {ln_report_severity} {ln_report_facility} {ln_report_syslogtag}{ln_report_count}
{ZAEHLER}{itemcount}{itemcount} {FirstOccurrence_Date_Formatted} {LastOccurrence_Date_Formatted} {syslogseverity_text} {syslogfacility_text} {syslogtag}{ItemCount}{ItemCount}
{ln_report_description}