|
1 <?php |
|
2 /** |
|
3 * Licensed to the Apache Software Foundation (ASF) under one or more |
|
4 * contributor license agreements. See the NOTICE file distributed with |
|
5 * this work for additional information regarding copyright ownership. |
|
6 * The ASF licenses this file to You under the Apache License, Version 2.0 |
|
7 * (the "License"); you may not use this file except in compliance with |
|
8 * the License. You may obtain a copy of the License at |
|
9 * |
|
10 * http://www.apache.org/licenses/LICENSE-2.0 |
|
11 * |
|
12 * Unless required by applicable law or agreed to in writing, software |
|
13 * distributed under the License is distributed on an "AS IS" BASIS, |
|
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
15 * See the License for the specific language governing permissions and |
|
16 * limitations under the License. |
|
17 * |
|
18 * @package log4php |
|
19 */ |
|
20 |
|
21 /** |
|
22 * The output of the LoggerXmlLayout consists of a series of log4php:event elements. |
|
23 * |
|
24 * Configurable parameters: |
|
25 * - {@link $locationInfo} - If set to true then the file name and line number |
|
26 * of the origin of the log statement will be included in output. |
|
27 * - {@link $log4jNamespace} - If set to true then log4j namespace will be used |
|
28 * instead of log4php namespace. This can be usefull when using log viewers |
|
29 * which can only parse the log4j namespace such as Apache Chainsaw. |
|
30 * |
|
31 * <p>It does not output a complete well-formed XML file. |
|
32 * The output is designed to be included as an external entity in a separate file to form |
|
33 * a correct XML file.</p> |
|
34 * |
|
35 * Example: |
|
36 * |
|
37 * {@example ../../examples/php/layout_xml.php 19}<br> |
|
38 * |
|
39 * {@example ../../examples/resources/layout_xml.properties 18}<br> |
|
40 * |
|
41 * The above would print: |
|
42 * |
|
43 * <pre> |
|
44 * <log4php:eventSet xmlns:log4php="http://logging.apache.org/log4php/" version="0.3" includesLocationInfo="true"> |
|
45 * <log4php:event logger="root" level="INFO" thread="13802" timestamp="1252456226491"> |
|
46 * <log4php:message><![CDATA[Hello World!]]></log4php:message> |
|
47 * <log4php:locationInfo class="main" file="examples/php/layout_xml.php" line="6" method="main" /> |
|
48 * </log4php:event> |
|
49 * </log4php:eventSet> |
|
50 * </pre> |
|
51 * |
|
52 * @version $Revision: 1213283 $ |
|
53 * @package log4php |
|
54 * @subpackage layouts |
|
55 */ |
|
56 class LoggerLayoutXml extends LoggerLayout { |
|
57 const LOG4J_NS_PREFIX = 'log4j'; |
|
58 const LOG4J_NS = 'http://jakarta.apache.org/log4j/'; |
|
59 |
|
60 const LOG4PHP_NS_PREFIX = 'log4php'; |
|
61 const LOG4PHP_NS = 'http://logging.apache.org/log4php/'; |
|
62 |
|
63 const CDATA_START = '<![CDATA['; |
|
64 const CDATA_END = ']]>'; |
|
65 const CDATA_PSEUDO_END = ']]>'; |
|
66 const CDATA_EMBEDDED_END = ']]>]]><![CDATA['; |
|
67 |
|
68 /** |
|
69 * If set to true then the file name and line number of the origin of the |
|
70 * log statement will be output. |
|
71 * @var boolean |
|
72 */ |
|
73 protected $locationInfo = true; |
|
74 |
|
75 /** |
|
76 * If set to true, log4j namespace will be used instead of the log4php |
|
77 * namespace. |
|
78 * @var boolean |
|
79 */ |
|
80 protected $log4jNamespace = false; |
|
81 |
|
82 /** The namespace in use. */ |
|
83 protected $namespace = self::LOG4PHP_NS; |
|
84 |
|
85 /** The namespace prefix in use */ |
|
86 protected $namespacePrefix = self::LOG4PHP_NS_PREFIX; |
|
87 |
|
88 public function activateOptions() { |
|
89 if ($this->getLog4jNamespace()) { |
|
90 $this->namespace = self::LOG4J_NS; |
|
91 $this->namespacePrefix = self::LOG4J_NS_PREFIX; |
|
92 } else { |
|
93 $this->namespace = self::LOG4PHP_NS; |
|
94 $this->namespacePrefix = self::LOG4PHP_NS_PREFIX; |
|
95 } |
|
96 } |
|
97 |
|
98 /** |
|
99 * @return string |
|
100 */ |
|
101 public function getHeader() { |
|
102 return "<{$this->namespacePrefix}:eventSet " . |
|
103 "xmlns:{$this->namespacePrefix}=\"{$this->namespace}\" " . |
|
104 "version=\"0.3\" " . |
|
105 "includesLocationInfo=\"" . ($this->getLocationInfo() ? "true" : "false") . "\"" . |
|
106 ">" . PHP_EOL; |
|
107 } |
|
108 |
|
109 /** |
|
110 * Formats a {@link LoggerLoggingEvent} in conformance with the log4php.dtd. |
|
111 * |
|
112 * @param LoggerLoggingEvent $event |
|
113 * @return string |
|
114 */ |
|
115 public function format(LoggerLoggingEvent $event) { |
|
116 $ns = $this->namespacePrefix; |
|
117 |
|
118 $loggerName = $event->getLoggerName(); |
|
119 $timeStamp = number_format((float)($event->getTimeStamp() * 1000), 0, '', ''); |
|
120 $thread = $event->getThreadName(); |
|
121 $level = $event->getLevel()->toString(); |
|
122 |
|
123 $buf = "<$ns:event logger=\"{$loggerName}\" level=\"{$level}\" thread=\"{$thread}\" timestamp=\"{$timeStamp}\">" . PHP_EOL; |
|
124 $buf .= "<$ns:message>"; |
|
125 $buf .= $this->encodeCDATA($event->getRenderedMessage()); |
|
126 $buf .= "</$ns:message>" . PHP_EOL; |
|
127 |
|
128 $ndc = $event->getNDC(); |
|
129 if (!empty($ndc)) { |
|
130 $buf .= "<$ns:NDC><![CDATA["; |
|
131 $buf .= $this->encodeCDATA($ndc); |
|
132 $buf .= "]]></$ns:NDC>" . PHP_EOL; |
|
133 } |
|
134 |
|
135 $mdcMap = $event->getMDCMap(); |
|
136 if (!empty($mdcMap)) { |
|
137 $buf .= "<$ns:properties>" . PHP_EOL; |
|
138 foreach ($mdcMap as $name => $value) { |
|
139 $buf .= "<$ns:data name=\"$name\" value=\"$value\" />" . PHP_EOL; |
|
140 } |
|
141 $buf .= "</$ns:properties>" . PHP_EOL; |
|
142 } |
|
143 |
|
144 if ($this->getLocationInfo()) { |
|
145 $locationInfo = $event->getLocationInformation(); |
|
146 $buf .= "<$ns:locationInfo " . |
|
147 "class=\"" . $locationInfo->getClassName() . "\" " . |
|
148 "file=\"" . htmlentities($locationInfo->getFileName(), ENT_QUOTES) . "\" " . |
|
149 "line=\"" . $locationInfo->getLineNumber() . "\" " . |
|
150 "method=\"" . $locationInfo->getMethodName() . "\" "; |
|
151 $buf .= "/>" . PHP_EOL; |
|
152 } |
|
153 |
|
154 $buf .= "</$ns:event>" . PHP_EOL; |
|
155 |
|
156 return $buf; |
|
157 } |
|
158 |
|
159 /** |
|
160 * @return string |
|
161 */ |
|
162 public function getFooter() { |
|
163 return "</{$this->namespacePrefix}:eventSet>" . PHP_EOL; |
|
164 } |
|
165 |
|
166 |
|
167 /** |
|
168 * Whether or not file name and line number will be included in the output. |
|
169 * @return boolean |
|
170 */ |
|
171 public function getLocationInfo() { |
|
172 return $this->locationInfo; |
|
173 } |
|
174 |
|
175 /** |
|
176 * The {@link $locationInfo} option takes a boolean value. By default, |
|
177 * it is set to false which means there will be no location |
|
178 * information output by this layout. If the the option is set to |
|
179 * true, then the file name and line number of the statement at the |
|
180 * origin of the log statement will be output. |
|
181 */ |
|
182 public function setLocationInfo($flag) { |
|
183 $this->setBoolean('locationInfo', $flag); |
|
184 } |
|
185 |
|
186 /** |
|
187 * @return boolean |
|
188 */ |
|
189 public function getLog4jNamespace() { |
|
190 return $this->log4jNamespace; |
|
191 } |
|
192 |
|
193 /** |
|
194 * @param boolean |
|
195 */ |
|
196 public function setLog4jNamespace($flag) { |
|
197 $this->setBoolean('log4jNamespace', $flag); |
|
198 } |
|
199 |
|
200 /** |
|
201 * Encases a string in CDATA tags, and escapes any existing CDATA end |
|
202 * tags already present in the string. |
|
203 * @param string $string |
|
204 */ |
|
205 private function encodeCDATA($string) { |
|
206 $string = str_replace(self::CDATA_END, self::CDATA_EMBEDDED_END, $string); |
|
207 return self::CDATA_START . $string . self::CDATA_END; |
|
208 } |
|
209 } |
|
210 |