summaryrefslogtreecommitdiff
path: root/framework/Util/TDbLogRoute.php
blob: 9c2c6e31c039c39cbf38e0596e1c210831d6079c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
<?php
/**
 * TLogRouter, TLogRoute, TFileLogRoute, TEmailLogRoute class file
 *
 * @author Qiang Xue <qiang.xue@gmail.com>
 * @link http://www.pradosoft.com/
 * @copyright Copyright &copy; 2005-2014 PradoSoft
 * @license http://www.pradosoft.com/license/
 * @package System.Util
 */

/**
 * TDbLogRoute class
 *
 * TDbLogRoute stores log messages in a database table.
 * To specify the database table, set {@link setConnectionID ConnectionID} to be
 * the ID of a {@link TDataSourceConfig} module and {@link setLogTableName LogTableName}.
 * If they are not setting, an SQLite3 database named 'sqlite3.log' will be created and used
 * under the runtime directory.
 *
 * By default, the database table name is 'pradolog'. It has the following structure:
 * <code>
 *	CREATE TABLE pradolog
 *  (
 *		log_id INTEGER NOT NULL PRIMARY KEY,
 *		level INTEGER,
 *		category VARCHAR(128),
 *		logtime VARCHAR(20),
 *		message VARCHAR(255)
 *   );
 * </code>
 *
 * @author Qiang Xue <qiang.xue@gmail.com>
 * @package System.Util
 * @since 3.1.2
 */
class TDbLogRoute extends TLogRoute
{
	/**
	 * @var string the ID of TDataSourceConfig module
	 */
	private $_connID='';
	/**
	 * @var TDbConnection the DB connection instance
	 */
	private $_db;
	/**
	 * @var string name of the DB log table
	 */
	private $_logTable='pradolog';
	/**
	 * @var boolean whether the log DB table should be created automatically
	 */
	private $_autoCreate=true;

	/**
	 * Destructor.
	 * Disconnect the db connection.
	 */
	public function __destruct()
	{
		if($this->_db!==null)
			$this->_db->setActive(false);
	}

	/**
	 * Initializes this module.
	 * This method is required by the IModule interface.
	 * It initializes the database for logging purpose.
	 * @param TXmlElement configuration for this module, can be null
	 * @throws TConfigurationException if the DB table does not exist.
	 */
	public function init($config)
	{
		$db=$this->getDbConnection();
		$db->setActive(true);

		$sql='SELECT * FROM '.$this->_logTable.' WHERE 0=1';
		try
		{
			$db->createCommand($sql)->query()->close();
		}
		catch(Exception $e)
		{
			// DB table not exists
			if($this->_autoCreate)
				$this->createDbTable();
			else
				throw new TConfigurationException('db_logtable_inexistent',$this->_logTable);
		}

		parent::init($config);
	}

	/**
	 * Stores log messages into database.
	 * @param array list of log messages
	 */
	protected function processLogs($logs)
	{
		$sql='INSERT INTO '.$this->_logTable.'(level, category, logtime, message) VALUES (:level, :category, :logtime, :message)';
		$command=$this->getDbConnection()->createCommand($sql);
		foreach($logs as $log)
		{
			$command->bindValue(':message',$log[0]);
			$command->bindValue(':level',$log[1]);
			$command->bindValue(':category',$log[2]);
			$command->bindValue(':logtime',$log[3]);
			$command->execute();
		}
	}

	/**
	 * Creates the DB table for storing log messages.
	 * @todo create sequence for PostgreSQL
	 */
	protected function createDbTable()
	{
		$db = $this->getDbConnection();
		$driver=$db->getDriverName();
		$autoidAttributes = '';
		if($driver==='mysql')
			$autoidAttributes = 'AUTO_INCREMENT';

		$sql='CREATE TABLE '.$this->_logTable.' (
			log_id INTEGER NOT NULL PRIMARY KEY ' . $autoidAttributes . ',
			level INTEGER,
			category VARCHAR(128),
			logtime VARCHAR(20),
			message VARCHAR(255))';
		$db->createCommand($sql)->execute();
	}

	/**
	 * Creates the DB connection.
	 * @param string the module ID for TDataSourceConfig
	 * @return TDbConnection the created DB connection
	 * @throws TConfigurationException if module ID is invalid or empty
	 */
	protected function createDbConnection()
	{
		if($this->_connID!=='')
		{
			$config=$this->getApplication()->getModule($this->_connID);
			if($config instanceof TDataSourceConfig)
				return $config->getDbConnection();
			else
				throw new TConfigurationException('dblogroute_connectionid_invalid',$this->_connID);
		}
		else
		{
			$db=new TDbConnection;
			// default to SQLite3 database
			$dbFile=$this->getApplication()->getRuntimePath().'/sqlite3.log';
			$db->setConnectionString('sqlite:'.$dbFile);
			return $db;
		}
	}

	/**
	 * @return TDbConnection the DB connection instance
	 */
	public function getDbConnection()
	{
		if($this->_db===null)
			$this->_db=$this->createDbConnection();
		return $this->_db;
	}

	/**
	 * @return string the ID of a {@link TDataSourceConfig} module. Defaults to empty string, meaning not set.
	 */
	public function getConnectionID()
	{
		return $this->_connID;
	}

	/**
	 * Sets the ID of a TDataSourceConfig module.
	 * The datasource module will be used to establish the DB connection for this log route.
	 * @param string ID of the {@link TDataSourceConfig} module
	 */
	public function setConnectionID($value)
	{
		$this->_connID=$value;
	}

	/**
	 * @return string the name of the DB table to store log content. Defaults to 'pradolog'.
	 * @see setAutoCreateLogTable
	 */
	public function getLogTableName()
	{
		return $this->_logTable;
	}

	/**
	 * Sets the name of the DB table to store log content.
	 * Note, if {@link setAutoCreateLogTable AutoCreateLogTable} is false
	 * and you want to create the DB table manually by yourself,
	 * you need to make sure the DB table is of the following structure:
	 * (key CHAR(128) PRIMARY KEY, value BLOB, expire INT)
	 * @param string the name of the DB table to store log content
	 * @see setAutoCreateLogTable
	 */
	public function setLogTableName($value)
	{
		$this->_logTable=$value;
	}

	/**
	 * @return boolean whether the log DB table should be automatically created if not exists. Defaults to true.
	 * @see setAutoCreateLogTable
	 */
	public function getAutoCreateLogTable()
	{
		return $this->_autoCreate;
	}

	/**
	 * @param boolean whether the log DB table should be automatically created if not exists.
	 * @see setLogTableName
	 */
	public function setAutoCreateLogTable($value)
	{
		$this->_autoCreate=TPropertyValue::ensureBoolean($value);
	}

}