[TASK] Support logger names with namespaces
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Classes / Log / LogManager.php
1 <?php
2 namespace TYPO3\CMS\Core\Log;
3
4 /***************************************************************
5 * Copyright notice
6 *
7 * (c) 2011-2012 Ingo Renner (ingo@typo3.org)
8 * (c) 2011-2012 Steffen Müller (typo3@t3node.com)
9 * (c) 2011-2012 Steffen Gebert (steffen.gebert@typo3.org))
10 * All rights reserved
11 *
12 * This script is part of the TYPO3 project. The TYPO3 project is
13 * free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 *
18 * The GNU General Public License can be found at
19 * http://www.gnu.org/copyleft/gpl.html.
20 *
21 * This script is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * This copyright notice MUST APPEAR in all copies of the script!
27 ***************************************************************/
28 /**
29 * Global LogManager that keeps track of global logging information.
30 *
31 * Inspired by java.util.logging
32 *
33 * @author Ingo Renner <ingo@typo3.org>
34 * @author Steffen Müller <typo3@t3node.com>
35 * @author Steffen Gebert <steffen.gebert@typo3.org>
36 * @package TYPO3
37 * @subpackage t3lib
38 */
39 class LogManager implements \TYPO3\CMS\Core\SingletonInterface {
40
41 /**
42 * @var string
43 */
44 const CONFIGURATION_TYPE_WRITER = 'writer';
45 /**
46 * @var string
47 */
48 const CONFIGURATION_TYPE_PROCESSOR = 'processor';
49 /**
50 * Loggers to retrieve them for repeated use.
51 *
52 * @var array
53 */
54 protected $loggers = array();
55
56 /**
57 * Default / global / root logger.
58 *
59 * @var \TYPO3\CMS\Core\Log\Logger
60 */
61 protected $rootLogger = NULL;
62
63 /**
64 * Constructor
65 */
66 public function __construct() {
67 $this->rootLogger = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Log\\Logger', '');
68 $this->loggers[''] = $this->rootLogger;
69 }
70
71 /**
72 * For use in unit test context only. Resets the internal logger registry.
73 *
74 * @return void
75 */
76 public function reset() {
77 $this->loggers = array();
78 }
79
80 /**
81 * Gets a logger instance for the given name.
82 *
83 * t3lib_div::makeInstance('\TYPO3\CMS\Core\Log\LogManager')->getLogger('main.sub.subsub');
84 *
85 * $name can also be submitted as a underscore-separated string, which will
86 * be converted to dots. This is useful to call this method with __CLASS__
87 * as parameter.
88 *
89 * @param string $name Logger name, empty to get the global "root" logger.
90 * @return \TYPO3\CMS\Core\Log\Logger Logger with name $name
91 */
92 public function getLogger($name = '') {
93 /** @var $logger \TYPO3\CMS\Core\Log\Logger */
94 $logger = NULL;
95 // Transform namespaces and underscore class names to the dot-name style
96 $separators = array('_', '\\');
97 $name = str_replace($separators, '.', $name);
98 if (isset($this->loggers[$name])) {
99 $logger = $this->loggers[$name];
100 } else {
101 // Lazy instantiation
102 /** @var $logger \TYPO3\CMS\Core\Log\Logger */
103 $logger = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Log\\Logger', $name);
104 $this->loggers[$name] = $logger;
105 $this->setWritersForLogger($logger);
106 $this->setProcessorsForLogger($logger);
107 }
108 return $logger;
109 }
110
111 /**
112 * For use in unit test context only.
113 *
114 * @param string $name
115 * @return void
116 */
117 public function registerLogger($name) {
118 $this->loggers[$name] = NULL;
119 }
120
121 /**
122 * For use in unit test context only.
123 *
124 * @return array
125 */
126 public function getLoggerNames() {
127 return array_keys($this->loggers);
128 }
129
130 /**
131 * Appends the writers to the given logger as configured.
132 *
133 * @param \TYPO3\CMS\Core\Log\Logger $logger Logger to configure
134 * @return void
135 * @throws \RangeException
136 */
137 protected function setWritersForLogger(\TYPO3\CMS\Core\Log\Logger $logger) {
138 $configuration = $this->getConfigurationForLogger(self::CONFIGURATION_TYPE_WRITER, $logger->getName());
139 foreach ($configuration as $severityLevel => $writer) {
140 foreach ($writer as $logWriterClassName => $logWriterOptions) {
141 /** @var $logWriter \TYPO3\CMS\Core\Log\Writer\Writer */
142 $logWriter = NULL;
143 try {
144 $logWriter = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance($logWriterClassName, $logWriterOptions);
145 $logger->addWriter($severityLevel, $logWriter);
146 } catch (\RangeException $e) {
147 $logger->warning('Instantiation of LogWriter "' . $logWriterClassName . '" failed for logger ' . $logger->getName() . ' (' . $e->getMessage() . ')');
148 }
149 }
150 }
151 }
152
153 /**
154 * Appends the processors to the given logger as configured.
155 *
156 * @param \TYPO3\CMS\Core\Log\Logger $logger Logger to configure
157 * @return void
158 * @throws \RangeException
159 */
160 protected function setProcessorsForLogger(\TYPO3\CMS\Core\Log\Logger $logger) {
161 $configuration = $this->getConfigurationForLogger(self::CONFIGURATION_TYPE_PROCESSOR, $logger->getName());
162 foreach ($configuration as $severityLevel => $processor) {
163 foreach ($processor as $logProcessorClassName => $logProcessorOptions) {
164 /** @var $logProcessor \TYPO3\CMS\Core\Log\Processor\Processor */
165 $logProcessor = NULL;
166 try {
167 $logProcessor = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance($logProcessorClassName, $logProcessorOptions);
168 $logger->addProcessor($severityLevel, $logProcessor);
169 } catch (\RangeException $e) {
170 $logger->warning('Instantiation of LogProcessor "' . $logProcessorClassName . '" failed for logger ' . $logger->getName() . ' (' . $e->getMessage() . ')');
171 }
172 }
173 }
174 }
175
176 /**
177 * Returns the configuration from $TYPO3_CONF_VARS['LOG'] as
178 * hierarchical array for different components of the class hierarchy.
179 *
180 * @param string $configurationType Type of config to return (writer, processor)
181 * @param string $loggerName Logger name
182 * @throws \RangeException
183 * @return array
184 */
185 protected function getConfigurationForLogger($configurationType, $loggerName) {
186 // Split up the logger name (dot-separated) into its parts
187 $explodedName = explode('.', $loggerName);
188 // Search in the $TYPO3_CONF_VARS['LOG'] array
189 // for these keys, for example "writerConfiguration"
190 $configurationKey = $configurationType . 'Configuration';
191 $configuration = $GLOBALS['TYPO3_CONF_VARS']['LOG'];
192 $result = !empty($configuration[$configurationKey]) ? $configuration[$configurationKey] : array();
193 // Walk from general to special (t3lib, t3lib.db, t3lib.db.foo)
194 // and search for the most specific configuration
195 foreach ($explodedName as $partOfClassName) {
196 if (!empty($configuration[$partOfClassName][$configurationKey])) {
197 $result = $configuration[$partOfClassName][$configurationKey];
198 }
199 $configuration = $configuration[$partOfClassName];
200 }
201 // Validate the config
202 foreach ($result as $level => $unused) {
203 try {
204 \TYPO3\CMS\Core\Log\LogLevel::validateLevel($level);
205 } catch (\RangeException $e) {
206 throw new \RangeException('The given severity level "' . htmlspecialchars($level) . '" for ' . $configurationKey . ' of logger "' . $loggerName . '" is not valid.', 1326406447);
207 }
208 }
209 return $result;
210 }
211
212 }
213
214
215 ?>