Tag Archive log

ทำ Virtual Host ใน Apache

เพราะว่าต้องแยกส่วนของ frontend และ backend ไว้คนละ server เพื่อความสดวกและปลอดภัย โดยทั้งคู่จะติดต่อกันผ่านทาง api แต่เวลาเขียนมีคอมพิวเตอร์แค่เครื่องเดียว ตามปกติสามารถทำได้โดยแยกงานไว้คนละ folder และเพื่อให้เหมือนของจริงยิ่งขึ้นก็ใข้วิธีทำ Virtual Host แยกออกเป็น 2 เซิร์ฟเวอร์ (ถึงจะแค่เครื่องจำลองก็เถอะ)

ทำได้โดยการเปิดไฟล์ C:\xampp\apache\conf\extra\httpd-vhosts.conf และเพิ่ม


## backend
Listen 81
<VirtualHost *:81>

    CustomLog "D:\xampp\htdocs\cms_backend\logs\apacheAccess.txt" common
    ErrorLog "D:\xampp\htdocs\cms_backend\logs\apacheError.txt"

    php_flag display_errors on
    php_flag log_errors on
    php_value error_log "D:\xampp\htdocs\cms_backend\logs\phpError.txt"
    php_value error_reporting 2147483647

    DocumentRoot "D:\xampp\htdocs\cms_backend\www"

    ServerAdmin [email protected]
    ServerName backend.localhost

</VirtualHost>

## frontend
Listen 82
<VirtualHost *:82>

    CustomLog "D:\xampp\htdocs\cms_frontend\logs\apacheAccess.txt" common
    ErrorLog "D:\xampp\htdocs\cms_frontend\logs\apacheError.txt"

    php_flag display_errors on
    php_flag log_errors on
    php_value error_log "D:\xampp\htdocs\cms_frontend\logs\phpError.txt"
    php_value error_reporting 2147483647

    DocumentRoot "D:\xampp\htdocs\cms_frontend\www"

    ServerAdmin [email protected]
    ServerName frontend.localhost

</VirtualHost>

อธิบาย

Listen
คือหมายเลขพอร์ตที่จะให้รอรับ request อย่าตั้งให้ชนกับตัวอื่น
CustomLog, ErrorLog
คือไฟล์ log ที่แยกออกมาของแต่ละ virtual host โดยสามารถอ่านคู่มือได้จาก Log Files
php_flag, php_value
คือ การปรับแต่ง php เป็นพิเศษสำหรับ server ตัวนี้เท่านั้น
DocumentRoot
คือ folder ที่ไว้เก็บ php ที่เราตั้งใจแยกไว้ เป็น code ชุดเดียวกับที่เราจะเอาขึ้น server จริง
ServerAdmin, ServerName
คือ ข้อมูล server แต่ละตัว

ทดสอบโดย restart apache ใหม่และเปิดเว็บ

Mysql: log query

debug ระบบที่ใช้ mysql แต่หาไม่เจอว่าข้อมูลเปลี่ยนที่จุดไหน เลยต้อง log ทุกๆ sql query ที่ส่งไปให้ mysql server

  1. เปิดไฟล์ config ของ mysql ขึ้นมา โดยแต่ละระบบจะไม่เหมือนกัน
    Ubuntu/Debian
    /etc/mysql/my.cnf
    wamp
    c:\wamp\bin\mysql\mysqlx.y.z\my.ini
    Windows
    c:\ProgramData\MySQL\MySQL Server 5.x
    xampp
    c:\xampp\mysql\bin\my.ini
  2. เพิ่ม
    # log all query
    general_log = on
    general_log_file = C:\xampp\logs_mysql\general_log.txt
    log_output = file
  3. สร้างไฟล์ C:\xampp\logs_mysql\all.txt ขึ้นมา ตัว mysql จะไม่สร้างให้อัตโนมัติถ้าไม่มีไฟล์นี้
  4. restart mysql service ใหม่

ถ้าเปลี่ยน config ให้ log_output = table log จะถูกบันทึกไว้ในตาราง general_log ใน database mysql แทน

ควรเปิดใช้เมื่อจำเป็นเท่านั้น ไม่ควรเปิดทิ้งไว้เพราะจะทำให้ mysql ทำงานช้าลง

อ่านเพิ่มเติม

Javascript Debugging

Code สั้นๆ ไว้แสดง message เวลา javascript มี error หรือจะดัดแปลงให้ส่ง error กลับไปที่ server ผ่าน ajax ก็ได้ครับ

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>javascript onerror</title>
</head>

<body>
<script>
window.onerror = function (msg, url, line) {
	str = "Message :tt"+msg+"nUrl :ttt"+url+"nLine number :t"+line;
	alert(str);
}

/* ตัวอย่างไปเรียก function ที่ไม่มีจริง */
noBody();
</script>
</body>
</html>

เรื่องที่เกี่ยวข้อง

เก็บ CodeIgniter log ด้วย hook

วิธีที่จะพัฒนาและดูแลเว็บคือทำระบบ log ที่จะบันทึกข้อมูลการใช้งาน ซึ่งจะบันทึกสิ่งที่เกิดขึ้นไว้สำหรับเข้ามาดูเหตุการณ์ที่เกิดขึ้นย้อนหลังได้ มีประโยชน์ในการดูแลระบบโดยเฉพาะตัวที่เป็น API ให้ระบบอื่นๆเรียกใช้ สำหรับ ci เราสามารถเขียนได้โดยการใช้ hook

ระบบ Hook (ตะขอ) คือ เป็นตะขอที่เกี่ยวกับเหตุการณ์ซักอย่างแล้วจึงทำงาน เหมือนกับ tricker ในดาต้าเบส หรือจะ อธิบายการทำงานง่ายๆ ก็เหมือน คุณไปที่ร้านอาหารคิดไม่ออกว่าจะทานอะไร ใช้วิธีรอให้เพื่อนสั่งแล้วบอกว่า หมีทู่ (me too.) นั้นละครับ

  1. ก่อนอื่น ไปเปิดการใช้งาน hook ก่อน เปิดไฟล์ /application /config/config.php แก้ $config[‘enable_hooks’] = FALSE; เป็น TRUE;
  2. เปิดไฟล์ /application /config/ hooks.php เพิ่มบรรทัด
    $hook['post_system'][] = array(
            'class' => '',
            'function' => 'log_Profiling',
            'filename' => 'log_Profiling.php',
            'filepath' => 'hooks'
    );
    
  3. จากนั้นไปสร้างไฟล์ log_Profiling.php ใน /application/hooks เนื้อหาตามนี้ครับ
    <?php
    function log_Profiling(){
    global $CI ,$application_folder;
    	$output = '<html><body>';
    	$output .= '<fieldset id="ci_profiler_benchmarks" style="border:1px solid #c00000;padding:6px 10px 10px 10px;margin:20px 0 20px 0;background-color:#eee">
    <legend style="color:#c00000;">OUTPUT</legend>'.$CI->output->get_output().'</fieldset>';
    	if( ! isset($_POST['profiler'])){
    		$CI->load->library('profiler');
    		if ( ! empty($CI->_profiler_sections)){
    			$CI->profiler->set_sections($this->_profiler_sections);
    		}
    		$output .= $CI->profiler->run();
    	}
    	$output .= '</body></html>';
    	$fp = fopen($application_folder.'/logs/Profiling/'.date('Y-m-d-H-i-s-U').'_'.$CI->router->fetch_class().'_'.$CI->router->fetch_method().'.html' ,'w');
    	flock($fp ,LOCK_EX);
    	fwrite($fp ,$output);
    	flock($fp ,LOCK_UN);
    	fclose($fp);
    }
    
  4. สร้างโฟลเดอร์ application/logs/Profiling/

แก้ระบบ error ของ CodeIgniter สำหรับ API

เดิมการแสดง error จะแสดงออกมาเป็น html แต่เมื่อเรานำ CI มาใช้เป็นระบบ API ถ้าแสดงแบบเดิมจะเกิดปัญหา app บน iphone / ipad ล่ม เพราะว่าข้อมูลที่ส่งออกไป กับที่ ios ทั้งหลายคาดว่าจะได้รับไม่ตรงกัน แก้ไม่ยากครับ แค่แทนที่ไฟล์ใน application/errors จาก code ด้านล่าง

error_404.php

<?php
global $application_folder;

// Get an article from the database, show a 404 page if the requested article was not found.

	$article = get_content($this->uri->uri_string());

	if(empty($article)){
		show_404($this->uri->uri_string());
	}

$datas['status'] = -1;
$datas['type'] = '404';
$datas['messageHeading'] = '404';
$datas['message'] = 'file not found';

$logs = "nnn".date('Y-m-d H:i:s');
$logs = $logs."ntURLt".$_SERVER['SERVER_ADDR'].$_SERVER['REQUEST_URI'];
$logs = $logs."ntPOSTt".print_r($_POST ,true);
$logs = $logs."ntRETURNt".print_r($datas ,true);
$fp = fopen($application_folder.'/logs/error'.date('Y-m-d').'.txt' ,'a+');
flock($fp ,LOCK_EX);
fwrite($fp ,$logs);
flock($fp ,LOCK_UN);
fclose($fp);
exit(json_encode($datas));

error_db.php

<?php
global $application_folder;
$datas['status'] = -1;
$datas['code'] = 1;
$datas['type'] = 'database';
$datas['messageHeading'] = $heading;
$datas['message'] = 'database error';
$datas['message'] = $message;

$logs = "nnn".date('Y-m-d H:i:s');
$logs = $logs."ntURLt".$_SERVER['SERVER_ADDR'].$_SERVER['REQUEST_URI'];
$logs = $logs."ntPOSTt".print_r($_POST ,true);
$logs = $logs."ntRETURNt".print_r($datas ,true);
$fp = fopen($application_folder.'/logs/error'.date('Y-m-d').'.txt' ,'a+');
flock($fp ,LOCK_EX);
fwrite($fp ,$logs);
flock($fp ,LOCK_UN);
fclose($fp);
exit(json_encode($datas));

error_general.php

<?php
global $application_folder;
$datas['status'] = -1;
$datas['type'] = 'general';
$datas['messageHeading'] = $heading;
$datas['message'] = $message;

$logs = "nnn".date('Y-m-d H:i:s');
$logs = $logs."ntURLt".$_SERVER['SERVER_ADDR'].$_SERVER['REQUEST_URI'];
$logs = $logs."ntPOSTt".print_r($_POST ,true);
$logs = $logs."ntRETURNt".print_r($datas ,true);
$fp = fopen($application_folder.'/logs/error'.date('Y-m-d').'.txt' ,'a+');
flock($fp ,LOCK_EX);
fwrite($fp ,$logs);
flock($fp ,LOCK_UN);
fclose($fp);
exit(json_encode($datas));

error_php.php

<?php
global $application_folder;
$datas['status'] = -1;
$datas['type'] = 'php';
$datas['messageHeading'] = 'A PHP Error was encountered';
$datas['message'] = $message;
$datas['severity'] = $severity;
$datas['filepath'] = $filepath;
$datas['line'] = $line;

$logs = "nnn".date('Y-m-d H:i:s');
$logs = $logs."ntURLt".$_SERVER['SERVER_ADDR'].$_SERVER['REQUEST_URI'];
$logs = $logs."ntPOSTt".print_r($_POST ,true);
$logs = $logs."ntRETURNt".print_r($datas ,true);
$fp = fopen($application_folder.'/logs/error'.date('Y-m-d').'.txt' ,'a+');
flock($fp ,LOCK_EX);
fwrite($fp ,$logs);
flock($fp ,LOCK_UN);
fclose($fp);
exit(json_encode($datas));

เท่านี้ error ทั้งหลายจะแปลงกายไปเป็น แบบ json และบันทึกลงไฟล์ใน application/logs เป็นรายวัน