Merge branch 'master' of github.com:gebhardtdasense/system

Conflicts:
	log/log.php
This commit is contained in:
Ulf Gebhardt 2013-12-23 00:38:02 +01:00
commit 628a93f30a
6 changed files with 253 additions and 124 deletions

View File

@ -17,4 +17,5 @@ INSERT INTO system.api ("ID", "group", type, "parentID", "parentValue", name, ve
INSERT INTO system.api ("ID", "group", type, "parentID", "parentValue", name, verify) VALUES (35, 42, 2, 3, 'add', 'id', 'ALL');
INSERT INTO system.api ("ID", "group", type, "parentID", "parentValue", name, verify) VALUES (30, 42, 2, 3, 'edit', 'id', 'ALL');
INSERT INTO system.api ("ID", "group", type, "parentID", "parentValue", name, verify) VALUES (36, 42, 2, 3, 'add', 'category', 'INT');
INSERT INTO system.api ("ID", "group", type, "parentID", "parentValue", name, verify) VALUES (40, 42, 3, 3, 'filter', 'filter', 'STRING');
INSERT INTO system.api ("ID", "group", type, "parentID", "parentValue", name, verify) VALUES (302, 42, 4, -1, NULL, '_lang', 'LANG');

View File

@ -18,13 +18,10 @@ class log {
die("You registered an invalid Errorhandler!");}
self::$handlers[] = $handler;
set_error_handler('\SYSTEM\LOG\log::__error_handler');
set_exception_handler('\SYSTEM\LOG\log::__exception_handler');
register_shutdown_function( '\SYSTEM\LOG\log::__shutdown_handler' );
ini_set('error_prepend_string', '<phpfatalerror>');
ini_set('error_append_string', '</phpfatalerror>');
ob_start('\SYSTEM\LOG\log::__fatal_error_handler');
set_error_handler ('\SYSTEM\LOG\log::__error_handler');
set_exception_handler ('\SYSTEM\LOG\log::__exception_handler');
register_shutdown_function ( '\SYSTEM\LOG\log::__shutdown_handler' );
ob_start ('\SYSTEM\LOG\log::__fatal_error_handler');
}
private static function call_handlers(\Exception $E, $thrown = true){
@ -47,15 +44,12 @@ class log {
return self::call_handlers(new \SYSTEM\LOG\ShutdownException($error["message"], 1, $error["type"],$error["file"],$error["line"]) ,$thrown);}
}
public static function __fatal_error_handler($bufferContent, $thrown = true){
$errors = array();
if ( preg_match('|<phpfatalerror>.*</phpfatalerror>|s', $bufferContent, $errors) ){
$error = strip_tags($errors[0]);
$error = substr($error,1,strlen($error)-2);
$file = substr($error,strpos($error,' in ')+5,strpos($error,' on ')-5-strpos($error,' in '));
$line = intval(substr($error,strpos($error,' line ')+6));
$error = substr($error,0,strpos($error,' in '));
return \SYSTEM\LOG\JsonResult::error(new \SYSTEM\LOG\ShutdownException($error,1,1,$file,$line));}
public static function __fatal_error_handler($bufferContent, $thrown = true){
if( ($error = error_get_last()) !== NULL && !$error['type'] === E_DEPRECATED){ //seams like we cannot call anything but core stuff
$result = array('querytime' => 0, 'status' => false, 'result' => $error);
header('Access-Control-Allow-Origin: *');//allow cross domain calls
header('content-type: application/json');
return json_encode($result);}
return $bufferContent;
}
}

View File

@ -1,42 +1,149 @@
function init__SYSTEM_SAI_saimod_sys_log() {
$('#truncate_table').click(function(){
$.ajax({
type :'GET',
url : './?action=developer&sai_mod=.SYSTEM.SAI.saimod_sys_log&truncate=sys_log',
success : function(data) {
if(data == 1){
$('#info_box').html("deleting data...");
$('#truncate_modal').modal('hide');
$('#content-wrapper').load(SAI_ENDPOINT+'sai_mod=.SYSTEM.SAI.saimod_sys_log');
}else{
$('#info_box').html("You do not have the permission to truncate table!");
}
}
$.ajax({ type :'GET',
url : SAI_ENDPOINT+'sai_mod=.SYSTEM.SAI.saimod_sys_log&action=truncate',
success : function(data) {
if(data == 1){
$('#info_box').html("deleting data...");
$('#truncate_modal').modal('hide');
$('#content-wrapper').load(SAI_ENDPOINT+'sai_mod=.SYSTEM.SAI.saimod_sys_log');
}else{
$('#info_box').html("You do not have the permission to truncate table!");
}
}
});
});
$('#refresh_error_table').live("click", (function(){
$('img#loader').show();
$('#content-wrapper').load(SAI_ENDPOINT+'sai_mod=.SYSTEM.SAI.saimod_sys_log');
setTimeout("$('img#loader').hide()", 1300);
}));
$('#refresh_error_table').live("click", (function(){
do_filter("");}));
$("#filter-error button").live("click", (function(){
$(this).parents().children().removeClass('active');
$("#filter-error button").live("click", (function(){
$('#filter-error button').each(function(){
$(this).removeClass('active');});
$(this).addClass('active');
$('#table-wrapper').load(SAI_ENDPOINT+'sai_mod=.SYSTEM.SAI.saimod_sys_log&filter_error='+$(this).attr('id'));
do_filter($(this).attr('filter'));}));
$('#show_visualtization').live("click", (function(){
drawVisualization();
}));
};
do_filter("");
};
function drawVisualization() {
$('img#loader').show();
$.getJSON(SAI_ENDPOINT+'sai_mod=.SYSTEM.SAI.saimod_sys_log&action=visualization',function(json){
if(json.status != true){
$('img#loader').hide();
$('#visualization').hide();
return;
}
json = json.result;
var data1 = new google.visualization.DataTable();
data1.addColumn('date', 'day');
data1.addColumn('number', 'count');
//data.addColumn('string', 'from to');
data1.addColumn('number', 'file_unique');
data1.addColumn('number', 'ip_unique');
data1.addColumn('number', 'text_unique');
data1.addColumn('number', 'class_unique');
var data2 = new google.visualization.DataTable();
data2.addColumn('date', 'day');
data2.addColumn('number', 'count');
data2.addColumn('number', 'querytime avg');
data2.addColumn('number', 'querytime max');
data2.addColumn('number', 'querytime min');
var data3 = new google.visualization.DataTable();
data3.addColumn('date', 'day');
data3.addColumn('number', 'count');
data3.addColumn('number', 'class_info');
data3.addColumn('number', 'class_deprecated');
data3.addColumn('number', 'class_warning');
data3.addColumn('number', 'class_error');
data3.addColumn('number', 'class_apperror');
var data4 = new google.visualization.DataTable();
data4.addColumn('date', 'day');
data4.addColumn('number', 'count');
data4.addColumn('number', 'class_system_log_info');
data4.addColumn('number', 'class_system_log_deprecated');
data4.addColumn('number', 'class_system_log_warning');
data4.addColumn('number', 'class_system_log_error');
data4.addColumn('number', 'class_system_log_errorexception');
data4.addColumn('number', 'class_system_log_shutdownexception');
var data5 = new google.visualization.DataTable();
data5.addColumn('date', 'day');
data5.addColumn('number', 'count');
data5.addColumn('number', 'class_exception');
data5.addColumn('number', 'class_runtimeexception');
data5.addColumn('number', 'class_errorexception');
data5.addColumn('number', 'class_other');
$.each(json, function(key, value){
data1.addRow([ new Date(value.day),
parseInt(value.count),
parseInt(value.file_unique),
parseInt(value.ip_unique),
parseInt(value.text_unique),
parseInt(value.class_unique)]);
data2.addRow([ new Date(value.day),
parseInt(value.count),
parseFloat(value.querytime_avg),
parseFloat(value.querytime_max),
parseFloat(value.querytime_min)]);
data3.addRow([ new Date(value.day),
parseInt(value.count),
parseInt(value.class_info)+0.5,
parseInt(value.class_deprecated)+0.5,
parseInt(value.class_warning)+0.5,
parseInt(value.class_error)+0.5,
parseInt(value.class_apperror)+0.5]);
data4.addRow([ new Date(value.day),
parseInt(value.count),
parseInt(value.class_system_log_info)+0.5,
parseInt(value.class_system_log_deprecated)+0.5,
parseInt(value.class_system_log_warning)+0.5,
parseInt(value.class_system_log_error)+0.5,
parseInt(value.class_system_log_errorexception)+0.5,
parseInt(value.class_system_log_shutdownexception)+0.5,
]);
data5.addRow([ new Date(value.day),
parseInt(value.count),
parseInt(value.class_exception)+0.5,
parseInt(value.class_runtimeexception)+0.5,
parseInt(value.class_errorexception)+0.5,
parseInt(value.count)+0.5 - parseInt(value.class_info) - parseInt(value.class_deprecated) - parseInt(value.class_warning) - parseInt(value.class_error) - parseInt(value.class_apperror) - parseInt(value.class_system_log_info) - parseInt(value.class_system_log_deprecated) - parseInt(value.class_system_log_warning) - parseInt(value.class_system_log_error) - parseInt(value.class_system_log_errorexception) - parseInt(value.class_system_log_shutdownexception) - parseInt(value.class_exception) - parseInt(value.class_runtimeexception) - parseInt(value.class_errorexception)]);
});
// Create and draw the visualization.
var options = {title: 'Exception Occurrence', aggregationTarget: 'category', selectionMode: 'multiple', /*focusTarget: 'category',*/ chartArea:{left:100,top:40}, vAxis:{logScale: true}, interpolateNulls: false, width: "1400", height: "500"};
new google.visualization.LineChart(document.getElementById('visualization1')).draw(data1, options);
var options = {title: 'Exception Querytime', /*focusTarget: 'category',*/ chartArea:{left:100,top:40}, vAxis:{logScale: true}, interpolateNulls: false, width: "1400", height: "500"};
new google.visualization.LineChart(document.getElementById('visualization2')).draw(data2, options);
var options = {title: 'Exception Classes - basic', /*focusTarget: 'category',*/ chartArea:{left:100,top:40}, vAxis:{logScale: true}, interpolateNulls: false, width: "1400", height: "500"};
new google.visualization.LineChart(document.getElementById('visualization3')).draw(data3, options);
var options = {title: 'Exception Classes - system', /*focusTarget: 'category',*/ chartArea:{left:100,top:40}, vAxis:{logScale: true}, interpolateNulls: false, width: "1400", height: "500"};
new google.visualization.LineChart(document.getElementById('visualization4')).draw(data4, options);
var options = {title: 'Exception Classes - other', /*focusTarget: 'category',*/ chartArea:{left:100,top:40}, vAxis:{logScale: true}, interpolateNulls: false, width: "1400", height: "500"};
new google.visualization.LineChart(document.getElementById('visualization5')).draw(data5, options);
$('img#loader').hide();
$('#table-wrapper').hide();
$('#visualization').show();
});
}
function do_filter(filter){
$('img#loader').show();
$('#visualization').hide();
$(this).parents().children().removeClass('active');
$(this).addClass('active');
$('#table-wrapper').load(SAI_ENDPOINT+'sai_mod=.SYSTEM.SAI.saimod_sys_log&action=filter&filter='+filter,function(){$('#table-wrapper').show(); $('img#loader').hide();});
}

View File

@ -5,30 +5,64 @@ namespace SYSTEM\SAI;
class saimod_sys_log extends \SYSTEM\SAI\SaiModule {
private static function truncate_syslog(){
public static function sai_mod__SYSTEM_SAI_saimod_sys_log_action_truncate(){
if(\SYSTEM\SECURITY\Security::check(\SYSTEM\SECURITY\RIGHTS::SYS_SAI)){
$con = new \SYSTEM\DB\Connection(\SYSTEM\system::getSystemDBInfo());
$res = $con->query('TRUNCATE system.sys_log;');
return true;
}else{
return false;
}
}
return false;
}
public static function sai_mod__SYSTEM_SAI_saimod_sys_log_action_visualization(){
$con = new \SYSTEM\DB\Connection(\SYSTEM\system::getSystemDBInfo());
$res = $con->query('SELECT time::date as day,
min(time) as time_min, max(time) as time_max,
count(*) as count,
avg(querytime) as querytime_avg,
max(querytime) as querytime_max,
min(querytime) as querytime_min,
count(distinct file) as file_unique,
count(distinct ip) as ip_unique,
count(distinct message) as text_unique,
count(distinct class) as class_unique,
sum(case when class = \'INFO\' then 1 else 0 end) class_INFO,
sum(case when class = \'DEPRECATED\' then 1 else 0 end) class_DEPRECATED,
sum(case when class = \'WARNING\' then 1 else 0 end) class_WARNING,
sum(case when class = \'ERROR\' then 1 else 0 end) class_ERROR,
sum(case when class = \'AppError\' then 1 else 0 end) class_AppError,
sum(case when class = \'SYSTEM\LOG\INFO\' then 1 else 0 end) class_SYSTEM_LOG_INFO,
sum(case when class = \'SYSTEM\LOG\DEPRECATED\' then 1 else 0 end) class_SYSTEM_LOG_DEPRECATED,
sum(case when class = \'SYSTEM\LOG\WARNING\' then 1 else 0 end) class_SYSTEM_LOG_WARNING,
sum(case when class = \'SYSTEM\LOG\ERROR\' then 1 else 0 end) class_SYSTEM_LOG_ERROR,
sum(case when class = \'SYSTEM\LOG\ErrorException\' then 1 else 0 end) class_SYSTEM_LOG_ErrorException,
sum(case when class = \'SYSTEM\LOG\ShutdownException\' then 1 else 0 end) class_SYSTEM_LOG_ShutdownException,
sum(case when class = \'Exception\' then 1 else 0 end) class_Exception,
sum(case when class = \'RuntimeException\' then 1 else 0 end) class_RuntimeException,
sum(case when class = \'ErrorException\' then 1 else 0 end) class_ErrorException
from system.sys_log
group by day
order by day desc
limit 365;');
$result = array();
while($row = $res->next()){
$result[] = $row;}
return \SYSTEM\LOG\JsonResult::toString($result);
}
private static function build_table($filter){
public static function sai_mod__SYSTEM_SAI_saimod_sys_log_action_filter($filter = ""){
$con = new \SYSTEM\DB\Connection(\SYSTEM\system::getSystemDBInfo());
$res = null;
if($filter !== NULL && $filter !== 'all'){
if($filter !== ""){
if(\SYSTEM\system::isSystemDbInfoPG()){
$res = $con->prepare( 'selectSysLogFilter',
'SELECT * FROM system.sys_log WHERE class ILIKE $1 ORDER BY time DESC LIMIT 100;',
array('%'.$filter.'%'));
array($filter));
} else {
$res = $con->prepare( 'selectSysLogFilter',
'SELECT * FROM system_log WHERE class LIKE ? ORDER BY time DESC LIMIT 100;',
array('%'.$filter.'%'));
array($filter));
}
} else {
if(\SYSTEM\system::isSystemDbInfoPG()){
@ -40,98 +74,58 @@ class saimod_sys_log extends \SYSTEM\SAI\SaiModule {
$now = microtime(true);
$result = '<div id="table-wrapper"><table class="table table-hover table-condensed">'.
$result = '<table class="table table-hover table-condensed">'.
'<tr>'.'<th>'.'time ago'.'</th>'.'<th>'.'time'.'</th>'.'<th>'.'class'.'</th>'.'<th>'.'message'.'</th>'.'<th>'.'code'.'</th>'.'<th>'.'file'.'</th>'.'<th>'.'line'.'</th>'.'<th>'.'ip'.'</th>'.'<th>'.'querytime'.'</tr>';
while($r = $res->next()){
//TODO make time conversion on database
if(\SYSTEM\system::isSystemDbInfoPG()){
$result .= '<tr class="'.self::tablerow_class($r['class']).'">'.'<td>'.self::time_elapsed_string(strtotime($r['time'])).'</td>'.'<td>'.$r['time'].'</td>'.'<td>'.$r['class'].'</td>'.'<td>'.$r['message'].'</td>'.'<td>'.$r['code'].'</td>'.'<td style="word-break: break-all;">'.$r['file'].'</td>'.'<td>'.$r['line'].'</td>'.'<td>'.$r['ip'].'</td>'.'<td>'.$r['querytime'].'</td>'.'</tr>';
$result .= '<tr class="'.self::tablerow_class($r['class']).'">'.'<td>'.self::time_elapsed_string(strtotime($r['time'])).'</td>'.'<td>'.$r['time'].'</td>'.'<td>'.$r['class'].'</td>'.'<td style="word-break: break-all">'.substr($r['message'],0,255).'</td>'.'<td>'.$r['code'].'</td>'.'<td style="word-break: break-all">'.$r['file'].'</td>'.'<td>'.$r['line'].'</td>'.'<td>'.$r['ip'].'</td>'.'<td>'.$r['querytime'].'</td>'.'</tr>';
} else {
$result .= '<tr class="'.self::tablerow_class($r['class']).'">'.'<td>'.self::time_elapsed_string($r['time']).'</td>'.'<td>'.$r['time'].'</td>'.'<td>'.$r['class'].'</td>'.'<td>'.$r['message'].'</td>'.'<td>'.$r['code'].'</td>'.'<td style="word-break: break-all;">'.$r['file'].'</td>'.'<td>'.$r['line'].'</td>'.'<td>'.$r['ip'].'</td>'.'<td>'.$r['querytime'].'</td>'.'</tr>';
$result .= '<tr class="'.self::tablerow_class($r['class']).'">'.'<td>'.self::time_elapsed_string($r['time']).'</td>'.'<td>'.$r['time'].'</td>'.'<td>'.$r['class'].'</td>'.'<td style="word-break: break-all;">'.substr($r['message'],0,255).'</td>'.'<td>'.$r['code'].'</td>'.'<td>'.$r['file'].'</td>'.'<td>'.$r['line'].'</td>'.'<td>'.$r['ip'].'</td>'.'<td>'.$r['querytime'].'</td>'.'</tr>';
}
}
$result .= '</table></div>';
$result .= '</table>';
return $result;
}
private static function time_elapsed_string($ptime)
{
private static function time_elapsed_string($ptime){
$etime = time() - $ptime;
if ($etime < 1)
{
return '0 seconds';
}
if ($etime < 1){
return '0 seconds';}
$a = array( 12 * 30 * 24 * 60 * 60 => 'year',
30 * 24 * 60 * 60 => 'month',
24 * 60 * 60 => 'day',
60 * 60 => 'hour',
60 => 'minute',
1 => 'second'
);
1 => 'second');
foreach ($a as $secs => $str)
{
foreach ($a as $secs => $str){
$d = $etime / $secs;
if ($d >= 1)
{
if ($d >= 1){
$r = round($d);
return $r . ' ' . $str . ($r > 1 ? 's' : '') . ' ago';
}
return $r . ' ' . $str . ($r > 1 ? 's' : '') . ' ago';}
}
}
public static function sai_mod__SYSTEM_SAI_saimod_sys_log(){
private static function generate_error_filters(){
$con = new \SYSTEM\DB\Connection(\SYSTEM\system::getSystemDBInfo());
$res = $con->query("SELECT class FROM system.sys_log GROUP BY class ORDER BY class;");
if( isset($_GET['truncate'])){
return self::truncate_syslog();
}
if( isset($_GET['filter_error'])){
return self::build_table($_GET['filter_error']);
}else{
$filter = NULL;
}
$result = '<div id="truncate_modal" class="modal hide fade">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h3>Truncate table system.sys_log</h3>
</div>
<div class="modal-body">
<p>This action will delete all error messages from database. <br />
Are you sure?</p>
<span id="info_box" />
</div>
<div class="modal-footer">
<a href="#" class="btn" data-dismiss="modal">Cancel</a>
<a href="#" class="btn btn-danger" id="truncate_table">Yes, delete all!</a>
</div>
</div>
<button id="refresh_error_table" class="btn" style="height: 32px; font-size: 13px;">Refresh</button>
<img id="loader" src="dasense/page/default_developer/img/ajax-loader.gif" style="margin-left: 10px; display: none;"/>
<div id="filter-error" class="btn-group" style="left: 60px;">
<button class="btn active" href="#" id="all">All</button>
<button class="btn" href="#" id="error">Error</button>
<button class="btn" href="#" id="warning">Warning</button>
<button class="btn" href="#" id="info">Info</button>
<button class="btn" href="#" id="deprecated">Deprecated</button>
<button class="btn" href="#" id="exception">Exception</button>
<button class="btn" href="#" id="apperror">AppError</button>
</diV>
<button data-toggle="modal" href="#truncate_modal" class="btn" style="height: 32px; font-size: 13px; float: right;">Truncate Table</button>
<br /><br />';
$result .= self::build_table($filter);
$result = "";
$i = 1;
while($row = $res->next()){
$result .= '<button class="btn" href="#" filter="'.$row['class'].'">'.$row['class'].'</button>'.(($i++ % 6 == 0) ? '</br>' : '');}
return $result;
}
public static function sai_mod__SYSTEM_SAI_saimod_sys_log(){
$vars = array();
$vars['error_filter'] = self::generate_error_filters();
return \SYSTEM\PAGE\replace::replaceFile(\SYSTEM\SERVERPATH(new \SYSTEM\PSAI(),'modules/saimod_sys_log/saimod_sys_log.tpl'), $vars);
}
private static function tablerow_class($class){

View File

@ -0,0 +1,34 @@
<div id="truncate_modal" class="modal hide fade">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h3>Truncate table system.sys_log</h3>
</div>
<div class="modal-body">
<p>This action will delete all error messages from database. <br /> Are you sure?</p>
<span id="info_box" />
</div>
<div class="modal-footer">
<a href="#" class="btn" data-dismiss="modal">Cancel</a>
<a href="#" class="btn btn-danger" id="truncate_table">Yes, delete all!</a>
</div>
</div>
<button id="refresh_error_table" class="btn" style="height: 32px; font-size: 13px; float: left">Refresh</button>
<img id="loader" src="dasense/page/default_developer/img/ajax-loader.gif" style="margin-left: 10px; display: none; float: left"/>
<div id="filter-error" class="btn-group" style="left: 60px; float: left;">
<button class="btn active" href="#" filter="">All</button>
${error_filter}
<br/><br/>
</div>
<button data-toggle="modal" href="#truncate_modal" class="btn" style="height: 32px; font-size: 13px; float: right;">Truncate Table</button>
<button id="show_visualtization" class="btn" style="height: 32px; font-size: 13px; float: right;">Show Stats</button>
<br/><br/>
<div id="table-wrapper"></div>
<br/><br/>
<div id="visualization" style="width: 100%; height: 100%; display: none;">
<div id="visualization1"></div>
<div id="visualization2"></div>
<div id="visualization3"></div>
<div id="visualization4"></div>
<div id="visualization5"></div>
</div>

View File

@ -12,9 +12,8 @@ class HEADER {
public static function JSON(){
self::checkHeader();
header('Access-Control-Allow-Origin: *');//allow cross domain calls
header('content-type: application/json');
//header('Access-Control-Allow-Methods", "POST, GET, OPTIONS');
//header('Access-Control-Allow-Headers *');
}
public static function PNG(){
self::checkHeader();