From b30eeb22734fbd8e95524a34c4e2f7181afb0f0f Mon Sep 17 00:00:00 2001
From: mattpiwik <matthieu.aubry@gmail.com>
Date: Fri, 27 Jul 2007 17:40:54 +0000
Subject: [PATCH] wonderful new logging system => yet to be finished

TODO: tell zend that the attributes in Zend_Log have to be PROTECTED

git-svn-id: http://dev.piwik.org/svn/trunk@20 59fd770c-687e-43c8-a1e3-f5a4ff64c105
---
 config/config.ini.php    |  29 +++++++
 index.php                |  33 +++++++
 libs/Zend/Log.php        |   8 +-
 modules/Log.php          | 181 +++++++++++++++++++++++++++++++++++++--
 modules/Log/APICalls.php |   3 +
 modules/Piwik.php        |  13 ++-
 6 files changed, 252 insertions(+), 15 deletions(-)
 create mode 100644 modules/Log/APICalls.php

diff --git a/config/config.ini.php b/config/config.ini.php
index f20888081d..12cb06bb23 100755
--- a/config/config.ini.php
+++ b/config/config.ini.php
@@ -18,6 +18,35 @@ tables_prefix	= piwiktests_
 
 [log]
 
+; query profiling information (SQL, avg execution time, etc.)
+query_profiles[]	= screen
+query_profiles[]	= database
+query_profiles[]	= file
+
+; all call to the API (method name, parameters, execution time, caller IP, etc.)
+api_calls[]			= screen
+api_calls[]			= database
+api_calls[]			= file
+
+; exception raised
+exceptions[]		= screen
+exceptions[]		= database
+exceptions[]		= file
+
+; error intercepted
+errors[]			= screen
+errors[]			= database
+errors[]			= file
+
+; normal messages
+messages[]			= screen
+messages[]			= database
+messages[]			= file
+
+
+[path]
+log				= logs/
+
 
 [smarty]
 template_dir	= core/views/scripts
diff --git a/index.php b/index.php
index d4720fa6ab..20beb8df84 100755
--- a/index.php
+++ b/index.php
@@ -56,6 +56,39 @@ Piwik::createDatabase();
 
 Piwik::createTables();
 
+
+
+
+//$logger = new Piwik_Log_APICalls;
+$logger = new Piwik_Log_Messages;
+
+$configAPI = Zend_Registry::get('config')->log->api_calls;
+
+foreach($configAPI as $recordTo)
+{
+	switch($recordTo)
+	{
+		case 'screen':
+			$logger->addWriteToScreen();
+		break;
+		
+		case 'database':
+			$logger->addWriteToDatabase();
+		break;
+		
+		case 'file':
+			$logger->addWriteToFile();		
+		break;
+		
+		default:
+			throw new Exception("TODO");
+		break;
+	}
+}
+
+Zend_Registry::set('logger', $logger);
+
+
 // Create auth object
 $auth = Zend_Auth::getInstance();
 $authAdapter = new Piwik_Auth();
diff --git a/libs/Zend/Log.php b/libs/Zend/Log.php
index d0430cdc56..6a22c37e4d 100755
--- a/libs/Zend/Log.php
+++ b/libs/Zend/Log.php
@@ -44,22 +44,22 @@ class Zend_Log
      * @var array of priorities where the keys are the
      * priority numbers and the values are the priority names
      */
-    private $_priorities = array();
+    protected $_priorities = array();
 
     /**
      * @var array of Zend_Log_Writer_Abstract
      */
-    private $_writers = array();
+    protected $_writers = array();
 
     /**
      * @var array of Zend_Log_Filter_Interface
      */
-    private $_filters = array();
+    protected $_filters = array();
 
     /**
      * @var array of extra log event
      */
-    private $_extras = array();
+    protected $_extras = array();
 
     /**
      * Class constructor.  Create a new logger
diff --git a/modules/Log.php b/modules/Log.php
index d01174be30..29d05b9582 100755
--- a/modules/Log.php
+++ b/modules/Log.php
@@ -1,26 +1,189 @@
 <?php
 Zend_Loader::loadClass('Zend_Log');
-Zend_Loader::loadClass('Zend_Registry');
+Zend_Loader::loadClass('Zend_Log');
+Zend_Loader::loadClass('Zend_Log_Formatter_Interface');
+Zend_Loader::loadClass('Zend_Log_Writer_Stream');
+Zend_Loader::loadClass('Zend_Log_Writer_Db');
+
 
 class Piwik_Log extends Zend_Log
 {
-	function __construct()
+	private $logToDatabaseTableName = null;
+	private $logToDatabaseColumnMapping = null;
+	private $logToFileFilename = null;
+	private $fileFormatter = null;
+	private $screenFormatter = null;
+	
+	function __construct( 	$logToFileFilename, 
+							$fileFormatter,
+							$screenFormatter,
+							$logToDatabaseTableName, 
+							$logToDatabaseColumnMapping )
 	{
 		parent::__construct();
 		
-		Zend_Loader::loadClass('Zend_Log_Writer_Stream');
-		$writer 	= new Zend_Log_Writer_Stream('php://output');
-		$formatter	= new Zend_Log_Formatter_Simple('%message% <br>' . PHP_EOL);
-		$writer->setFormatter($formatter);
-		$this->addWriter($writer);
-		Zend_Registry::set('logger', $this);
+		$this->logToFileFilename = $logToFileFilename;
+		$this->fileFormatter = $fileFormatter;
+		$this->screenFormatter = $screenFormatter;
+		$this->logToDatabaseTableName = $logToDatabaseTableName;
+		$this->logToDatabaseColumnMapping = $logToDatabaseColumnMapping;
 	}
 	
 	static public function dump($var, $label=null)
 	{
-		Zend_Registry::get('logger')->log(Zend_Debug::dump($var, $label, false), Piwik_Log::DEBUG);
+		Zend_Registry::get('LoggerMessages')->log(Zend_Debug::dump($var, $label, false), Piwik_Log::DEBUG);
+	}
+	
+	function addWriteToFile()
+	{
+		$writerFile = new Zend_Log_Writer_Stream($this->logToFileFilename);
+		$writerFile->setFormatter( $this->fileFormatter );
+		$this->addWriter($writerFile);
+	}
+	
+	function addWriteToDatabase()
+	{
+		$writerDb = new Zend_Log_Writer_Db(
+								Zend_Registry::get('db'), 
+								$this->logToDatabaseTableName, 
+								$this->logToDatabaseColumnMapping);
+		
+		$this->addWriter($writerDb);
+	}
+	
+	function addWriteToScreen()
+	{
+		$writerScreen = new Zend_Log_Writer_Stream('php://output');
+		$writerScreen->setFormatter( $this->screenFormatter );
+		$this->addWriter($writerScreen);
+	}
+	
+    /**
+     * Log an event
+     * Overload Zend_log::log cos its too weak for our requirements
+     */
+    public function log($event)
+    {
+        // sanity checks
+        if (empty($this->_writers)) {
+            throw new Zend_Log_Exception('No writers were added');
+        }
+		if(isset($event['priority']))
+		{
+	        if (! isset($this->_priorities[$event['priority']])) {
+	            throw new Zend_Log_Exception('Bad log priority');
+	        }
+		}
+		$event['timestamp'] = date('c');
+		
+        // pack into event required by filters and writers
+        $event = array_merge( $event, $this->_extras);
+
+        // abort if rejected by the global filters
+        foreach ($this->_filters as $filter) {
+            if (! $filter->accept($event)) {
+                return;
+            }
+        }
+
+        // send to each writer
+        foreach ($this->_writers as $writer) {
+            $writer->write($event);
+        }
+    }
+	
+}
+
+class Piwik_Log_Formatter_FileFormatter implements Zend_Log_Formatter_Interface
+{
+	/**
+     * Formats data into a single line to be written by the writer.
+     *
+     * @param  array    $event    event data
+     * @return string             formatted line to write to the log
+     */
+    public function format($event)
+    {
+    	$str = implode(" ", $event);
+    	return $str;
+    }
+}
+
+class Piwik_Log_Formatter_ScreenFormatter implements Zend_Log_Formatter_Interface
+{
+	/**
+     * Formats data into a single line to be written by the writer.
+     *
+     * @param  array    $event    event data
+     * @return string             formatted line to write to the log
+     */
+    public function format($event)
+    {
+    	$str = '';
+    	foreach($event as $name => $value)
+    	{
+    		$str .= "$name : $value \n<br>";
+    	}
+    	return $str;
+    }
+}
+
+class Piwik_Log_APICalls extends Piwik_Log
+{
+	function __construct()
+	{
+		$logToFileFilename = 'api_call';
+		$logToDatabaseTableName = 'log_api_calls';//TODO generalize
+		$logToDatabaseColumnMapping = null;
+		$screenFormatter = new Piwik_Log_Formatter_ScreenFormatter;
+		$fileFormatter = new Piwik_Log_Formatter_FileFormatter;
+		
+		parent::__construct($logToFileFilename, 
+							$fileFormatter,
+							$screenFormatter,
+							$logToDatabaseTableName, 
+							$logToDatabaseColumnMapping );
+		
+		$this->setEventItem('ip', ip2long( Piwik::getIp() ) );
+	}
+	
+	function log( $methodName, $parameters, $executionTime)
+	{
+		$event = array();
+		$event['methodName'] = $methodName;
+		$event['parameters'] = serialize($parameters);
+		$event['executionTime'] = $executionTime;
+		
+		parent::log($event);
+	}
+}
+
+class Piwik_Log_Messages extends Piwik_Log
+{
+	function __construct()
+	{
+		$logToFileFilename = 'message';
+		$logToDatabaseTableName = 'log_message';//TODO generalize
+		$logToDatabaseColumnMapping = null;
+		$screenFormatter = new Piwik_Log_Formatter_ScreenFormatter;
+		$fileFormatter = new Piwik_Log_Formatter_FileFormatter;
+		
+		parent::__construct($logToFileFilename, 
+							$fileFormatter,
+							$screenFormatter,
+							$logToDatabaseTableName, 
+							$logToDatabaseColumnMapping );
+		
+		$this->setEventItem('ip', ip2long( Piwik::getIp() ) );
 	}
 	
+	public function log( $message )
+	{
+		$event = array();
+		$event['message'] = $message;
+		
+		parent::log($event);
+	}
 }
 
 ?>
diff --git a/modules/Log/APICalls.php b/modules/Log/APICalls.php
new file mode 100644
index 0000000000..62a2de0c86
--- /dev/null
+++ b/modules/Log/APICalls.php
@@ -0,0 +1,3 @@
+<?php
+
+?>
diff --git a/modules/Piwik.php b/modules/Piwik.php
index ea2dd42677..80c5a2fc3b 100755
--- a/modules/Piwik.php
+++ b/modules/Piwik.php
@@ -6,7 +6,7 @@ class Piwik
 	
 	static public function log($message, $priority = Zend_Log::NOTICE)
 	{
-		Zend_Registry::get('logger')->log($message . PHP_EOL, $priority);
+		Zend_Registry::get('logger')->log($message . PHP_EOL);
 	}
 	
 	static public function getTablesCreateSql()
@@ -52,10 +52,18 @@ class Piwik
 			);
 		return $tables;
 	}
+	
+	static public function getIp()
+	{
+		//TODO test and move from piwik
+		return '127.0.0.1';
+	}
+	
 	static public function getCurrentUserLogin()
 	{
 		return Zend_Registry::get('access')->getIdentity();
 	}
+	
 	// Accessible either to the user itself
 	static public function checkUserIsSuperUserOrTheUser( $theUser )
 	{
@@ -156,7 +164,8 @@ class Piwik
 
 	static public function createLogObject()
 	{
-		$log = new Piwik_Log;
+		//TODO
+		//$log = new Piwik_Log;
 	}
 	static public function createConfigObject()
 	{
-- 
GitLab