From 38a00af8da69dd5c4c4ea4fcf6a34733f8a4ab8c Mon Sep 17 00:00:00 2001 From: Andre Lorbach Date: Wed, 3 Sep 2008 17:55:00 +0200 Subject: [PATCH] Started implemented jpgraph lib to draw charts and graphs --- src/chartgenerator.php | 223 ++++++++++++++-------------- src/classes/logstream.class.php | 7 + src/classes/logstreamdb.class.php | 12 ++ src/classes/logstreamdisk.class.php | 43 ++++++ src/classes/logstreampdo.class.php | 12 ++ src/include/constants_general.php | 3 + src/lang/en/main.php | 4 + 7 files changed, 192 insertions(+), 112 deletions(-) diff --git a/src/chartgenerator.php b/src/chartgenerator.php index a1dd9b8..dfe8d1a 100644 --- a/src/chartgenerator.php +++ b/src/chartgenerator.php @@ -50,18 +50,39 @@ InitFilterHelpers(); // Helpers for frontend filtering! // --- // --- READ CONTENT Vars +$content['error_occured'] = false; + if ( isset($_GET['type']) ) $content['chart_type'] = intval($_GET['type']); else $content['chart_type'] = CHART_CAKE; if ( isset($_GET['width']) ) +{ $content['chart_width'] = intval($_GET['width']); + + // Limit Chart Size for now + if ( $content['chart_width'] < 100 ) + $content['chart_width'] = 100; + else if ( $content['chart_width'] > 1000 ) + $content['chart_width'] = 1000; +} else $content['chart_width'] = 100; if ( isset($_GET['byfield']) ) - $content['chart_field'] = $_GET['byfield']; +{ + if ( isset($fields[ $_GET['byfield'] ]) ) + { + $content['chart_field'] = $_GET['byfield']; + $content['chart_fieldtype'] = $fields[SYSLOG_UID]['FieldType']; + } + else + { + $content['error_occured'] = true; + $content['error_details'] = $content['LN_GEN_ERROR_INVALIDFIELD']; + } +} else { $content['error_occured'] = true; @@ -74,6 +95,23 @@ $content['TITLE'] = InitPageTitle(); // --- END CREATE TITLE // --- BEGIN Custom Code + +include_once ($gl_root_path . "classes/jpgraph/jpgraph.php"); +include_once ($gl_root_path . "classes/jpgraph/jpgraph_bar.php"); + +// Create Basic Image! +$myGraph = new Graph($content['chart_width'], $content['chart_width'], 'auto'); +$myGraph->SetScale("textlin"); +$myGraph->img->SetMargin(60,30,20,40); +$myGraph->yaxis->SetTitleMargin(45); +$myGraph->yaxis->scale->SetGrace(30); +$myGraph->SetShadow(); + +// Turn the tickmarks +$myGraph->xaxis->SetTickSide(SIDE_DOWN); +$myGraph->yaxis->SetTickSide(SIDE_LEFT); + +// Get data and print on the image! if ( !$content['error_occured'] ) { if ( isset($content['Sources'][$currentSourceID]) ) @@ -87,8 +125,51 @@ if ( !$content['error_occured'] ) $res = $stream->Open( $content['Columns'], true ); if ( $res == SUCCESS ) { + // Obtain data from the logstream! + $chartData = $stream->GetCountSortedByField($content['chart_field'], $content['chart_fieldtype']); + + // If data is valid, we have an array! + if ( is_array($chartData) ) + { + // Sort Array, so the highest count comes first! + array_multisort($chartData, SORT_NUMERIC, SORT_DESC); + + // Create y array! + foreach( $chartData as $myYData) + $YchartData[] = intval($myYData); + + //print_r ($chartData); + //$datay=array(12,26,9,17,31); + + // Create a bar pot + $bplot = new BarPlot($YchartData); +// $bplot->SetFillColor("orange"); + + // Use a shadow on the bar graphs (just use the default settings) + $bplot->SetShadow(); + $bplot->value->SetFormat("%2.0f",70); + $bplot->value->SetFont(FF_ARIAL,FS_NORMAL,9); + $bplot->value->SetColor("blue"); + $bplot->value->Show(); + + $myGraph->Add($bplot); + + $myGraph->title->Set("Chart blabla"); + $myGraph->xaxis->title->Set("X-title"); + $myGraph->yaxis->title->Set("Y-title"); + } + else + { + $content['error_occured'] = true; + $content['error_details'] = GetErrorMessage($chartData); + if ( isset($extraErrorDescription) ) + $content['error_details'] .= "\n\n" . GetAndReplaceLangStr( $content['LN_SOURCES_ERROR_EXTRAMSG'], $extraErrorDescription); + } + + +//$fields[SYSLOG_UID]['FieldID'] } else @@ -97,7 +178,7 @@ if ( !$content['error_occured'] ) $content['error_occured'] = true; $content['error_details'] = GetErrorMessage($res); if ( isset($extraErrorDescription) ) - $content['error_details'] .= "

" . GetAndReplaceLangStr( $content['LN_SOURCES_ERROR_EXTRAMSG'], $extraErrorDescription); + $content['error_details'] .= "\n\n" . GetAndReplaceLangStr( $content['LN_SOURCES_ERROR_EXTRAMSG'], $extraErrorDescription); } // Close file! @@ -109,122 +190,40 @@ if ( !$content['error_occured'] ) $content['error_details'] = GetAndReplaceLangStr( $content['LN_GEN_ERROR_SOURCENOTFOUND'], $currentSourceID); } } -// --- -// --- Convert and Output -if ( $content['error_occured'] ) +if ( $content['error_occured'] ) { - // TODO PRINT ERROR ON PICTURE STREAM! + // QUICK AND DIRTY! + $myImage = imagecreatetruecolor( $content['chart_width'], $content['chart_width']); -// InitTemplateParser(); -// $page -> parser($content, "export.html"); -// $page -> output(); -} -else -{ - // Create ChartDiagram! +/* // create basic colours + $red = ImageColorAllocate($myImage, 255, 0, 0); + $green = ImageColorAllocate($myImage, 0, 255, 0); + $gray = ImageColorAllocate($myImage, 128, 128, 128); + $black = ImageColorAllocate($myImage, 0, 0, 0); + $white = ImageColorAllocate($myImage, 255, 255, 255); + + // Fill image with colour, and create a border + imagerectangle( $myImage, 0, 0, $content['chart_width']-1, $content['chart_width']-1, $gray ); + imagefill( $myImage, 1, 1, $white ); +*/ + $text_color = imagecolorallocate($myImage, 255, 0, 0); + imagestring($myImage, 3, 10, 10, $content['LN_GEN_ERRORDETAILS'], $text_color); + imagestring($myImage, 3, 10, 25, $content['error_details'], $text_color); + + header ("Content-type: image/png"); + imagepng($myImage); // Outputs the image to the browser + imagedestroy($myImage); // Clean Image resource exit; - - // Create a CVS File! - $szOutputContent = ""; - $szOutputMimeType = "text/plain"; - $szOutputCharset = ""; - - $szOutputFileName = "ExportMessages"; - $szOutputFileExtension = ".txt"; - if ( $content['exportformat'] == EXPORT_CVS ) - { - // Set MIME TYPE and File Extension - $szOutputMimeType = "text/csv"; - $szOutputFileExtension = ".csv"; - - // Set Column line in cvs file! - foreach($content['Columns'] as $mycolkey) - { - if ( isset($fields[$mycolkey]) ) - { - // Prepend Comma if needed - if (strlen($szOutputContent) > 0) - $szOutputContent .= ","; - - // Append column name - $szOutputContent .= $content[ $fields[$mycolkey]['FieldCaptionID'] ]; - } - } - - // Append line break - $szOutputContent .= "\n"; - - // Append messages into output - foreach ( $content['syslogmessages'] as $myIndex => $mySyslogMessage ) - { - $szLine = ""; - - // --- Process columns - foreach($mySyslogMessage as $myColkey => $mySyslogField) - { - // Prepend Comma if needed - if (strlen($szLine) > 0) - $szLine .= ","; - - // Append field contents - $szLine .= '"' . str_replace('"', '\\"', $mySyslogField['fieldvalue']) . '"'; - } - // --- - - // Append line! - $szOutputContent .= $szLine . "\n"; - } - } - else if ( $content['exportformat'] == EXPORT_XML ) - { - // Set MIME TYPE and File Extension - $szOutputMimeType = "application/xml"; - $szOutputFileExtension = ".xml"; - $szOutputCharset = "charset=UTF-8"; - - // Create XML Header and first node!! - $szOutputContent .= "\xef\xbb\xbf"; - $szOutputContent .= "\n"; - $szOutputContent .= "\n"; - - // Append messages into output - foreach ( $content['syslogmessages'] as $myIndex => $mySyslogMessage ) - { - $szXmlLine = "\t\n"; - - // --- Process columns - foreach($mySyslogMessage as $myColkey => $mySyslogField) - { - -// if ( isset($content[ $fields[$mycolkey]['FieldCaptionID'] ]) ) -// $szNodeTitle = $content[ $fields[$mycolkey]['FieldCaptionID'] ]; -// else - - // Append field content | first run htmlentities,tnen utf8 encoding!! - $szXmlLine .= "\t\t<" . $myColkey . ">" . utf8_encode( htmlentities($mySyslogField['fieldvalue']) ) . "\n"; - } - // --- - - $szXmlLine .= "\t\n"; - - // Append line! - $szOutputContent .= $szXmlLine; - } - - // End first XML Node - $szOutputContent .= ""; - } - - // Set needed Header properties - header('Content-type: ' . $szOutputMimeType . "; " . $szOutputCharset); - header("Content-Length: " . strlen($szOutputContent) ); - header('Content-Disposition: attachment; filename="' . $szOutputFileName . $szOutputFileExtension . '"'); - - // Output Content! - print( $szOutputContent ); } // --- + +// --- Output the image + +// Send back the HTML page which will call this script again to retrieve the image. +$myGraph->StrokeCSIM(); +// --- + ?> \ No newline at end of file diff --git a/src/classes/logstream.class.php b/src/classes/logstream.class.php index a14c5c2..e567081 100644 --- a/src/classes/logstream.class.php +++ b/src/classes/logstream.class.php @@ -195,6 +195,13 @@ abstract class LogStream { */ public abstract function GetCurrentPageNumber(); + /** + * This functions is used by charts/graph generator to obtain data + * + * @return integer Error stat + */ + public abstract function GetCountSortedByField($szFieldId, $nFieldType); + /** * Gets a property and checks if the class is able to sort the records diff --git a/src/classes/logstreamdb.class.php b/src/classes/logstreamdb.class.php index 5d7d857..dac6810 100644 --- a/src/classes/logstreamdb.class.php +++ b/src/classes/logstreamdb.class.php @@ -499,6 +499,18 @@ class LogStreamDB extends LogStream { return false; } + /** + * Implementation of GetCountSortedByField + * + * In the native MYSQL Logstream, the database will do most of the work + * + * @return integer Error stat + */ + public function GetCountSortedByField($szFieldId, $nFieldType) + { + } + + /* * ============= Beginn of private functions ============= */ diff --git a/src/classes/logstreamdisk.class.php b/src/classes/logstreamdisk.class.php index c135df7..e2ba072 100644 --- a/src/classes/logstreamdisk.class.php +++ b/src/classes/logstreamdisk.class.php @@ -573,6 +573,49 @@ class LogStreamDisk extends LogStream { return false; } + /** + * Implementation of GetCountSortedByField + * + * For now, the disk source needs to loop through the whole file + * to consolidate and sort the data + * + * @return integer Error stat + */ + public function GetCountSortedByField($szFieldId, $nFieldType) + { + // We loop through all loglines! this may take a while! + $uID = UID_UNKNOWN; + $ret = $this->ReadNext($uID, $logArray); + if ( $ret == SUCCESS ) + { + do + { + if ( isset($logArray[$szFieldId]) ) + { + if ( isset($aResult[ $logArray[$szFieldId] ]) ) + $aResult[ $logArray[$szFieldId] ]++; + else + $aResult[ $logArray[$szFieldId] ] = 1; + /* + if ( isset($aResult[ $logArray[$szFieldId] ][CHARTDATA_COUNT]) ) + $aResult[ $logArray[$szFieldId] ][CHARTDATA_COUNT]++; + else + { + $aResult[ $logArray[$szFieldId] ][CHARTDATA_NAME] = $logArray[$szFieldId]; + $aResult[ $logArray[$szFieldId] ][CHARTDATA_COUNT] = 1; + } + */ + } + } while ( ($ret = $this->ReadNext($uID, $logArray)) == SUCCESS ); + + // finally return result! + return $aResult; + } + else + return ERROR_NOMORERECORDS; + } + + /** * Set the direction the stream should read data. * diff --git a/src/classes/logstreampdo.class.php b/src/classes/logstreampdo.class.php index 91d6d2d..7a613cb 100644 --- a/src/classes/logstreampdo.class.php +++ b/src/classes/logstreampdo.class.php @@ -509,6 +509,18 @@ class LogStreamPDO extends LogStream { return false; } + /** + * Implementation of GetCountSortedByField + * + * In the PDO DB Logstream, the database will do most of the work + * + * @return integer Error stat + */ + public function GetCountSortedByField($szFieldId, $nFieldType) + { + } + + /* * ============= Beginn of private functions ============= */ diff --git a/src/include/constants_general.php b/src/include/constants_general.php index 3421475..a9ef9e1 100644 --- a/src/include/constants_general.php +++ b/src/include/constants_general.php @@ -78,6 +78,9 @@ define('EXPORT_XML', 'XML'); define('CHART_CAKE', 1); define('CHART_BARS_VERTICAL', 2); define('CHART_BARS_HORIZONTAL', 3); + +define('CHARTDATA_NAME', 'NAME'); +define('CHARTDATA_COUNT', 'COUNT'); // --- // --- diff --git a/src/lang/en/main.php b/src/lang/en/main.php index 888645b..c8b96d0 100644 --- a/src/lang/en/main.php +++ b/src/lang/en/main.php @@ -282,6 +282,10 @@ $content['LN_CONVERT_ERROR_SOURCEIMPORT'] = "Critical Error while importing the // Stats Site $content['LN_STATS_COUNTBYSOURCE'] = "Messagecount by Source"; $content['LN_STATS_GRAPH'] = "Graph"; + $content['LN_GEN_ERROR_INVALIDFIELD'] = "Invalid fieldname"; + $content['LN_GEN_ERROR_MISSINGCHARTFIELD'] = "Missing fieldname"; + + ?> \ No newline at end of file