Issues (1474)

framework/Util/TLogRouter.php (2 issues)

1
<?php
2
3
/**
4
 * TLogRouter, TLogRoute, TFileLogRoute, TEmailLogRoute class file
5
 *
6
 * @author Qiang Xue <[email protected]>
7
 * @link https://github.com/pradosoft/prado
8
 * @license https://github.com/pradosoft/prado/blob/master/LICENSE
9
 */
10
11
namespace Prado\Util;
12
13
use Prado\Exceptions\TConfigurationException;
14
use Prado\Exceptions\TInvalidDataTypeException;
15
use Prado\Prado;
16
use Prado\TApplication;
17
use Prado\TPropertyValue;
18
use Prado\Xml\TXmlDocument;
19
20
/**
21
 * TLogRouter class.
22
 *
23
 * TLogRouter manages routes that record log messages in different media different ways.
24
 * For example, a file log route {@see \Prado\Util\TFileLogRoute} records log messages
25
 * in log files. An email log route {@see \Prado\Util\TEmailLogRoute} sends log messages
26
 * to email addresses.
27
 *
28
 * Log routes may be configured in application or page folder configuration files
29
 * or an external configuration file specified by {@see setConfigFile ConfigFile}.
30
 * The format is as follows,
31
 * ```xml
32
 *   <route class="TFileLogRoute" Categories="Prado\Web\UI" Levels="Warning" />
33
 *   <route class="TEmailLogRoute" Categories="Application" Levels="Fatal" Emails="[email protected]" />
34
 * ```
35
 * You can specify multiple routes with different filtering conditions and different
36
 * targets, even if the routes are of the same type.
37
 *
38
 * @author Qiang Xue <[email protected]>
39
 * @author Carl G. Mathisen <[email protected]>
40
 * @author Brad Anderson <[email protected]>
41
 * @since 3.0
42
 */
43
class TLogRouter extends \Prado\TModule
44
{
45
	/**
46
	 * @var array list of routes available
47
	 */
48
	private $_routes = [];
49
	/**
50
	 * @var string external configuration file
51
	 */
52
	private $_configFile;
53
54
	/**
55
	 * Initializes this module.
56
	 * This method is required by the IModule interface.
57
	 * @param mixed $config configuration for this module, can be null
58
	 * @throws TConfigurationException if {@see getConfigFile ConfigFile} is invalid.
59
	 */
60
	public function init($config)
61
	{
62
		if ($this->_configFile !== null) {
63
			if (is_file($this->_configFile)) {
64
				if ($this->getApplication()->getConfigurationType() == TApplication::CONFIG_TYPE_PHP) {
65
					$phpConfig = include $this->_configFile;
66
					$this->loadConfig($phpConfig);
67
				} else {
68
					$dom = new TXmlDocument();
69
					$dom->loadFromFile($this->_configFile);
70
					$this->loadConfig($dom);
71
				}
72
			} else {
73
				throw new TConfigurationException('logrouter_configfile_invalid', $this->_configFile);
74
			}
75
		}
76
		$this->loadConfig($config);
77
		Prado::getLogger()->attachEventHandler('onFlushLogs', [$this, 'collectLogs']);
78
		parent::init($config);
79
	}
80
81
	/**
82
	 * Loads configuration from an XML element or PHP array
83
	 * @param mixed $config configuration node
84
	 * @throws TConfigurationException if log route class or type is not specified
85
	 */
86
	private function loadConfig($config)
87
	{
88
		if (is_array($config)) {
89
			if (isset($config['routes']) && is_array($config['routes'])) {
90
				foreach ($config['routes'] as $route) {
91
					$properties = $route['properties'] ?? [];
92
					if (!isset($route['class'])) {
93
						throw new TConfigurationException('logrouter_routeclass_required');
94
					}
95
					$route = Prado::createComponent($route['class']);
96
					if (!($route instanceof TLogRoute)) {
97
						throw new TConfigurationException('logrouter_routetype_invalid');
98
					}
99
					foreach ($properties as $name => $value) {
100
						$route->setSubproperty($name, $value);
101
					}
102
					$this->addRoute($route, $route);
103
				}
104
			}
105
		} else {
106
			foreach ($config->getElementsByTagName('route') as $routeConfig) {
107
				$properties = $routeConfig->getAttributes();
108
				if (($class = $properties->remove('class')) === null) {
109
					throw new TConfigurationException('logrouter_routeclass_required');
110
				}
111
				$route = Prado::createComponent($class);
112
				if (!($route instanceof TLogRoute)) {
113
					throw new TConfigurationException('logrouter_routetype_invalid');
114
				}
115
				foreach ($properties as $name => $value) {
116
					$route->setSubproperty($name, $value);
117
				}
118
				$this->addRoute($route, $routeConfig);
119
			}
120
		}
121
	}
122
123
	/**
124
	 * Adds a TLogRoute instance to the log router.
125
	 * @param TLogRoute $route the route being added.
126
	 * @param mixed $config the configuration for the route.
127
	 * @throws TInvalidDataTypeException if the route object is invalid
128
	 */
129
	public function addRoute($route, $config = null)
130
	{
131
		if (!($route instanceof TLogRoute)) {
0 ignored issues
show
$route is always a sub-type of Prado\Util\TLogRoute.
Loading history...
132
			throw new TInvalidDataTypeException('logrouter_routetype_invalid');
133
		}
134
		$this->_routes[] = $route;
135
		$route->init($config);
136
	}
137
138
	/**
139
	 * Gets the number of log routes.
140
	 * @return int The number of routes.
141
	 * @since 4.3.0
142
	 */
143
	public function getRoutesCount(): int
144
	{
145
		return count($this->_routes);
146
	}
147
148
	/**
149
	 * Gets the log routes.
150
	 * @return TLogRoute[] The routes for the Router
151
	 * @since 4.3.0
152
	 */
153
	public function getRoutes(): array
154
	{
155
		return $this->_routes;
156
	}
157
158
	/**
159
	 * Removes a TLogRoute instance to the log router.
160
	 * @param mixed $route the Route or Route Key to remove
161
	 * @return ?TLogRoute The routes for the Router
162
	 * @since 4.3.0
163
	 */
164
	public function removeRoute($route): ?TLogRoute
165
	{
166
		if (!is_array($route) && !is_object($route) && isset($this->_routes[$route])) {
167
			$removed = $this->_routes[$route];
168
			unset($this->_routes[$route]);
169
			$this->_routes = array_values($this->_routes);
170
			return $removed;
171
		}
172
		if (($key = array_search($route, $this->_routes, true)) !== false) {
173
			$removed = $this->_routes[$key];
174
			unset($this->_routes[$key]);
175
			$this->_routes = array_values($this->_routes);
176
			return $removed;
177
		}
178
		return null;
179
	}
180
181
	/**
182
	 * @return string external configuration file. Defaults to null.
183
	 */
184
	public function getConfigFile()
185
	{
186
		return $this->_configFile;
187
	}
188
189
	/**
190
	 * @param string $value external configuration file in namespace format. The file
191
	 * must be suffixed with '.xml'.
192
	 * @throws TConfigurationException if the file is invalid.
193
	 */
194
	public function setConfigFile($value)
195
	{
196
		if (($this->_configFile = Prado::getPathOfNamespace($value, $this->getApplication()->getConfigurationFileExt())) === null) {
197
			throw new TConfigurationException('logrouter_configfile_invalid', $value);
198
		}
199
	}
200
201
	/**
202
	 * Collects log messages from a logger.
203
	 * This method is an event handler to application's EndRequest event.
204
	 * @param TLogger $logger
205
	 * @param bool $final
206
	 */
207
	public function collectLogs($logger, bool $final)
208
	{
209
		if (!($logger instanceof TLogger)) {
0 ignored issues
show
$logger is always a sub-type of Prado\Util\TLogger.
Loading history...
210
			$logger = Prado::getLogger();
211
		}
212
		foreach ($this->_routes as $route) {
213
			if ($route->getEnabled()) {
214
				$route->collectLogs($logger, $final);
215
			}
216
		}
217
	}
218
219
	/**
220
	 * This is a passthrough to the Application TLogger.
221
	 * @return int The number of logs before triggering {@see self::onFlushLogs()}, default 1000.
222
	 * @since 4.3.0
223
	 */
224
	public function getFlushCount(): int
225
	{
226
		return Prado::getLogger()->getFlushCount();
227
	}
228
229
	/**
230
	 * This is a passthrough to the Application TLogger.
231
	 * @param int|string $value the number of logs before triggering {@see self::onFlushLogs()}
232
	 * @return static $this
233
	 * @since 4.3.0
234
	 */
235
	public function setFlushCount($value): static
236
	{
237
		Prado::getLogger()->setFlushCount(TPropertyValue::ensureInteger($value));
238
239
		return $this;
240
	}
241
242
	/**
243
	 * This is a passthrough to the Application TLogger.
244
	 * @return int How much debug trace stack information to include. Default 0.
245
	 * @since 4.3.0
246
	 */
247
	public function getTraceLevel(): int
248
	{
249
		return Prado::getLogger()->getTraceLevel();
250
	}
251
252
	/**
253
	 * This is a passthrough to the Application TLogger.
254
	 * @param null|int|string $value How much debug trace stack information to include.
255
	 * @return static $this
256
	 * @since 4.3.0
257
	 */
258
	public function setTraceLevel($value): static
259
	{
260
		Prado::getLogger()->setTraceLevel(TPropertyValue::ensureInteger($value));
261
262
		return $this;
263
	}
264
}
265