16 require_once SQ_INCLUDE_PATH.
'/asset.inc';
33 protected $log_level_map;
35 protected $min_tail_lines = 10;
46 $this->_ser_attrs = TRUE;
47 parent::__construct($assetid);
65 require_once SQ_CORE_PACKAGE_PATH.
'/system/system_asset_fns.inc';
66 if (!system_asset_fns_create_pre_check($this)) {
70 $GLOBALS[
'SQ_SYSTEM']->changeDatabaseConnection(
'db2');
71 $GLOBALS[
'SQ_SYSTEM']->doTransaction(
'BEGIN');
73 if ($linkid = parent::create($link)) {
74 if (!system_asset_fns_create_cleanup($this)) {
80 $GLOBALS[
'SQ_SYSTEM']->doTransaction(
'COMMIT');
82 $GLOBALS[
'SQ_SYSTEM']->doTransaction(
'ROLLBACK');
85 $GLOBALS[
'SQ_SYSTEM']->restoreDatabaseConnection();
101 SQ_LINK_TYPE_1 => Array(),
102 SQ_LINK_TYPE_2 => Array(),
103 SQ_LINK_TYPE_3 => Array(),
104 SQ_LINK_NOTICE => Array(),
134 return $GLOBALS[
'SQ_SYSTEM']->am->getTypeInfo($this->
type(),
'name');
166 $files = glob(SQ_LOG_PATH.
'/*.log');
167 $logs = $this->
attr(
'logs');
169 foreach ($files as $file) {
171 if (!empty($logname)) {
172 if (!isset($logs[$logname])) {
195 preg_match(
'/^'.preg_quote(SQ_LOG_PATH.
'/',
'/').
'(\S*).log$/', $file, $matches);
196 if (isset($matches[1]) && !empty($matches[1])) {
216 if (isset($logs[$logname]) && !empty($logs[$logname])) {
217 return $logs[$logname];
238 public function &
getLogLine($logname, $rotation_index=NULL, $offset=0)
240 $rotation_suffix = (!is_null($rotation_index) && is_numeric($rotation_index)) ?
'.'.$rotation_index :
'';
242 $read_data = $this->
_readLineFromFile(SQ_LOG_PATH.
'/'.$logname.SQ_CONF_LOG_EXTENSION.$rotation_suffix, $offset);
244 if (!empty($read_data)) {
245 $read_data[
'line'] = $this->
_decodeLine(array_get_index($read_data,
'line', FALSE));
265 $rotation_suffix = (!is_null($rotation_index) && is_numeric($rotation_index)) ?
'.'.$rotation_index :
'';
266 return $this->
_getFileSize(SQ_LOG_PATH.
'/'.$logname.SQ_CONF_LOG_EXTENSION.$rotation_suffix);
282 include_once
'log_iterator.inc';
284 $iterator =
new Log_Iterator($logname, $rotation_index);
301 $rotation = array_get_index($log,
'rotation', Array());
303 $log[
'rotation'][
'interval'] = array_get_index($rotation,
'interval', 86400);
304 $log[
'rotation'][
'min_index'] = array_get_index($rotation,
'min_index', 1);
305 $log[
'rotation'][
'max_index'] = array_get_index($rotation,
'max_index', 10);
306 $log[
'rotation'][
'last_timestamp'] = array_get_index($rotation,
'last_timestamp', 0);
335 if (empty($line))
return FALSE;
341 preg_match(
'/\[([^[\]]*)\]\[([^[\]]*):([^[\]]*)\]\[(\d+):([^[\]]*)\]\[(.)\] (.*)/', $line, $matches);
343 if (empty($matches))
return FALSE;
347 $user = str_replace(
'[',
'[', $user);
348 $user = str_replace(
']',
']', $user);
349 $user = str_replace(
':',
':', $user);
350 $user = str_replace(
' ',
"\n", $user);
351 $data = str_replace(
' ',
"\r", $user);
354 $data = str_replace(
' ',
"\n", $data);
355 $data = str_replace(
' ',
"\r", $data);
357 $decoded_line = Array(
358 'userid' => $matches[2],
360 'date' => strtotime($matches[1]),
361 'level' => (
int) $matches[4],
366 if ($matches[6] ==
'S') {
367 $decoded_line[
'data'] = unserialize($decoded_line[
'data']);
370 return $decoded_line;
394 if (empty($file))
return FALSE;
396 $file_contents = Array();
398 if (file_exists($file) && $handle = fopen($file,
'r')) {
399 if (fseek($handle, $offset) >= 0 && !feof($handle)) {
400 $line = fgets($handle);
402 $offset = ftell($handle);
404 'line' => trim($line),
412 trigger_localised_error(
'CORE0018', E_USER_ERROR, $file);
431 if (empty($file))
return FALSE;
434 if (file_exists($file)) {
435 $filesize = sprintf(
'%u', filesize($file));
457 $rotated_logs = Array();
458 $rotate_hr = $this->
attr(
'log_rotate_time');
459 $rotate_hr_fwd = ($rotate_hr > 22) ?
'0' : ($rotate_hr + 1);
460 $time_to_rotate = mktime($rotate_hr,
'0',
'0');
461 $time_to_rotate_fwd = mktime($rotate_hr_fwd,
'0',
'0');
464 if (time() >= $time_to_rotate && time() <= $time_to_rotate_fwd) {
465 foreach ($logs as $logname => $log_data) {
470 if ($time_to_rotate - $log_data[
'rotation'][
'last_timestamp'] >= ($log_data[
'rotation'][
'interval']-360)) {
471 if ($this->
rotateLog($logname, $log_data)) {
472 $logs[$logname] = $log_data;
473 $rotated_logs[] = $logname;
481 $GLOBALS[
'SQ_SYSTEM']->setRunLevel(SQ_RUN_LEVEL_FORCED);
486 $GLOBALS[
'SQ_SYSTEM']->restoreRunLevel();
488 return $rotated_logs;
504 $rotation = array_get_index($log_data,
'rotation', Array());
505 $interval = array_get_index($rotation,
'interval');
506 $min_index = array_get_index($rotation,
'min_index');
507 $max_index = array_get_index($rotation,
'max_index');
508 $last_timestamp = array_get_index($rotation,
'last_timestamp');
511 if (empty($rotation) || empty($interval) || !is_numeric($min_index) || empty($max_index) || $min_index > $max_index) {
523 $existing_logs = glob(SQ_LOG_PATH .
'/' . $logname . SQ_CONF_LOG_EXTENSION .
'*');
529 $log_id = $max_index;
530 while ($log_id > 0) {
531 $full_log_path = SQ_LOG_PATH .
'/' . $logname . SQ_CONF_LOG_EXTENSION;
537 if ($log_id == $max_index) {
538 if (in_array($full_log_path .
'.' . $max_index, $existing_logs)) {
539 $log_deleted = @unlink($full_log_path .
'.' . $max_index);
549 if (in_array($full_log_path .
'.' . $log_id, $existing_logs)) {
550 $status = $this->
_rotateLogFiles($full_log_path, $log_id, ($log_id+1));
562 $status = $this->
_rotateLogFiles(SQ_LOG_PATH.
'/'.$logname.SQ_CONF_LOG_EXTENSION,
'',
'1');
565 $rotate_hr = $this->
attr(
'log_rotate_time');
566 $time_to_rotate = mktime($rotate_hr,
'0',
'0');
567 $log_data[
'rotation'][
'interval'] = $interval;
568 $log_data[
'rotation'][
'min_index'] = $min_index;
569 $log_data[
'rotation'][
'max_index'] = $max_index;
570 $log_data[
'rotation'][
'last_timestamp'] = $time_to_rotate;
595 require_once SQ_FUDGE_PATH.
'/general/file_system.inc';
596 if (file_exists($file)) {
597 $orig_filename = $file;
598 if (!empty($current_rotation)) {
599 $orig_filename .=
'.' . $current_rotation;
602 if (copy_file($orig_filename, $file.
'.'.$new_rotation)) {
603 return truncate_file($orig_filename);
642 $direct = array_get_index($_REQUEST, $prefix.
'_direct_connection', FALSE);
650 parent::paintBackend($o);
666 require_once SQ_FUDGE_PATH.
'/general/file_system.inc';
670 $action = array_get_index($_REQUEST, $prefix.
'_action');
671 $value = array_get_index($_REQUEST, $prefix.
'_value');
672 $logname = array_get_index($_REQUEST, $prefix.
'_log');
673 $offset = array_get_index($_REQUEST, $prefix.
'_offset');
674 $numlines= array_get_index($_REQUEST, $prefix.
'_num_lines');
678 if (empty($action)) {
679 echo translate(
'no_action_supplied');
682 }
else if ($action ==
'monitor' && !empty($logname)) {
683 $num_lines = empty($value) ? (int)$numlines : (
int)$value;
684 $filename = SQ_LOG_PATH.
'/'.$logname.SQ_CONF_LOG_EXTENSION;
686 if (!is_readable($filename)) {
687 echo translate(
'file_not_readable');
691 if (empty($offset)) {
692 $lines = get_last_lines_from_file($filename, $num_lines);
693 $new_offset = filesize($filename);
695 $handle = fopen($filename,
'r');
697 echo translate(
'cannot_open_file');
701 $error_status = fseek($handle, $offset);
704 $lines = get_last_lines_from_file($filename, $num_lines);
705 $new_offset = filesize($filename);
707 while (!feof($handle)) {
708 $lines[] = rtrim(fgets($handle));
711 $new_offset = ftell($handle);
713 if (count($lines) < $num_lines) {
715 $lines = get_last_lines_from_file($filename, $num_lines);
716 $new_offset = filesize($filename);
721 $date_string = date(
'G:i:s - d M');
723 <table class="sq-backend-table">
725 <th style="width: 150px">'.translate(
'metadata').
'</th>
726 <th>'.translate(
'message').
'</th>
730 $content .= translate(
'empty');
732 foreach ($lines as $line) {
733 if (empty($line))
continue;
735 if ($d_line !== FALSE) {
736 $message = $d_line[
'data'];
737 if (is_array($message)) {
738 $message =
'<pre>'.print_r($message, TRUE).
'</pre>';
740 $message = htmlspecialchars($message);
741 $message = nl2br($message);
742 $error_type_name = get_error_name($d_line[
'level']);
743 $error_type_colour = get_error_colour($d_line[
'level']);
744 $log_date = date(
'G:i:s - d M',$d_line[
'date']);
748 <td style="background-color: '.$error_type_colour.
'; color: white">
750 '.translate(
'user').
': <strong>'.$d_line[
'user'].
'</strong> ('.$d_line[
'userid'].
')<br />
751 '.translate(
'level').
': <strong>'.$error_type_name.
'</strong><br />
753 <td><span style="font-family: \'Courier New\', Courier, monospace;">'.$message.
'</span></td>
756 $line = htmlspecialchars($line);
757 $line = nl2br($line);
760 <td style="color: red; background-color: #eef; text-align: right;">
761 <strong>'.translate(
'raw_entry').
':</strong>
763 <td><span style="font-family: \'Courier New\', Courier, monospace;">'.$line.
'<span></td>
770 $content .=
'</table>';
773 trigger_localised_error(
'CORE0125', E_USER_WARNING);
780 <title><?php echo translate(
'log_monitor'); ?></title>
781 <link rel=
"stylesheet" type=
"text/css" href=
"<?php echo sq_web_path('lib');?>/web/css/edit.css" />
782 <script
type=
"text/javascript">
790 function getEltPosition(elt)
794 while (elt != null) {
795 posX += elt.offsetLeft;
796 posY += elt.offsetTop;
797 elt = elt.offsetParent;
799 return {x:posX,y:posY};
808 function scrolToBottom()
810 elt = document.getElementById(
"sq-log-end");
811 coords = getEltPosition(elt);
813 window.scrollTo(0,coords.y);
820 <body onload=
"scrolToBottom(); parent.setLastRefreshInfo('<?php echo $date_string; ?>','<?php echo count($lines); ?>','<?php echo $new_offset; ?>')">
821 <?php echo $content; ?>
822 <a name=
"bottom" id=
"sq-log-end" />