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 * Serialize events and send them to a network socket. 23 * 24 * This appender can be configured by changing the following attributes: 25 * 26 * - locationInfo - Sets the location info for the xml layout (true or false) 27 * - log4jNamespace - Sets the namespace for log4j (true or false) 28 * - port - Sets the port of the socket. 29 * - remoteHost - Sets the remote host 30 * - timeout - Sets the timeout in ms 31 * - useXml - true, if xml should be transmitted. 32 * false, if a serialized php object should be transmitted 33 * 34 * Parameters are {@link $remoteHost}, {@link $port}, {@link $timeout}, 35 * {@link $locationInfo}, {@link $useXml} and {@link $log4jNamespace}. 36 * 37 * An example: 38 * 39 * {@example ../../examples/php/appender_socket.php 19} 40 * 41 * {@example ../../examples/resources/appender_socket.properties 18} 42 * 43 * @version $Revision: 883108 $ 44 * @package log4php 45 * @subpackage appenders 46 */ 47class LoggerAppenderSocket extends LoggerAppender { 48 49 /** 50 * @var mixed socket connection resource 51 * @access private 52 */ 53 private $sp = false; 54 55 /** 56 * Target host. On how to define remote hostaname see 57 * {@link PHP_MANUAL#fsockopen} 58 * @var string 59 */ 60 private $remoteHost = ''; 61 62 /** 63 * @var integer the network port. 64 */ 65 private $port = 4446; 66 67 /** 68 * @var boolean get event's location info. 69 */ 70 private $locationInfo = false; 71 72 /** 73 * @var integer connection timeout 74 */ 75 private $timeout = 30; 76 77 /** 78 * @var boolean output events via {@link LoggerXmlLayout} 79 */ 80 private $useXml = false; 81 82 /** 83 * @var boolean forward this option to {@link LoggerXmlLayout}. 84 * Ignored if {@link $useXml} is <i>false</i>. 85 */ 86 private $log4jNamespace = false; 87 88 /** 89 * @var LoggerXmlLayout 90 * @access private 91 */ 92 private $xmlLayout = null; 93 94 /** @var indiciates if this appender should run in dry mode */ 95 private $dry = false; 96 97 public function __destruct() { 98 $this->close(); 99 } 100 101 /** 102 * Create a socket connection using defined parameters 103 */ 104 public function activateOptions() { 105 if(!$this->dry) { 106 $this->sp = @fsockopen($this->getRemoteHost(), $this->getPort(), $errno, $errstr, $this->getTimeout()); 107 if ($this->sp === false) { 108 throw new LoggerException("Could not open socket to ".$this->getRemoteHost().":".$this->getPort().": $errstr ($errno)"); 109 } 110 } 111 if($this->getUseXml()) { 112 $this->xmlLayout = LoggerReflectionUtils::createObject('LoggerLayoutXml'); 113 if($this->xmlLayout === null) { 114 $this->setUseXml(false); 115 } else { 116 $this->xmlLayout->setLocationInfo($this->getLocationInfo()); 117 $this->xmlLayout->setLog4jNamespace($this->getLog4jNamespace()); 118 $this->xmlLayout->activateOptions(); 119 } 120 } 121 $this->closed = false; 122 } 123 124 public function close() { 125 if($this->closed != true) { 126 if(!$this->dry and $this->sp !== false) { 127 fclose($this->sp); 128 } 129 $this->closed = true; 130 } 131 } 132 133 public function setDry($dry) { 134 $this->dry = $dry; 135 } 136 137 /** 138 * @return string 139 */ 140 public function getHostname() { 141 return $this->getRemoteHost(); 142 } 143 144 /** 145 * @return boolean 146 */ 147 public function getLocationInfo() { 148 return $this->locationInfo; 149 } 150 151 /** 152 * @return boolean 153 */ 154 public function getLog4jNamespace() { 155 return $this->log4jNamespace; 156 } 157 158 /** 159 * @return integer 160 */ 161 public function getPort() { 162 return $this->port; 163 } 164 165 public function getRemoteHost() { 166 return $this->remoteHost; 167 } 168 169 /** 170 * @return integer 171 */ 172 public function getTimeout() { 173 return $this->timeout; 174 } 175 176 /** 177 * @var boolean 178 */ 179 public function getUseXml() { 180 return $this->useXml; 181 } 182 183 public function reset() { 184 $this->close(); 185 parent::reset(); 186 } 187 188 /** 189 * @param mixed 190 */ 191 public function setLocationInfo($flag) { 192 $this->locationInfo = LoggerOptionConverter::toBoolean($flag, $this->getLocationInfo()); 193 } 194 195 /** 196 * @param mixed 197 */ 198 public function setLog4jNamespace($flag) { 199 $this->log4jNamespace = LoggerOptionConverter::toBoolean($flag, $this->getLog4jNamespace()); 200 } 201 202 /** 203 * @param integer 204 */ 205 public function setPort($port) { 206 $port = LoggerOptionConverter::toInt($port, 0); 207 if($port > 0 and $port < 65535) { 208 $this->port = $port; 209 } 210 } 211 212 /** 213 * @param string 214 */ 215 public function setRemoteHost($hostname) { 216 $this->remoteHost = $hostname; 217 } 218 219 /** 220 * @param integer 221 */ 222 public function setTimeout($timeout) { 223 $this->timeout = LoggerOptionConverter::toInt($timeout, $this->getTimeout()); 224 } 225 226 /** 227 * @param mixed 228 */ 229 public function setUseXml($flag) { 230 $this->useXml = LoggerOptionConverter::toBoolean($flag, $this->getUseXml()); 231 } 232 233 public function append(LoggerLoggingEvent $event) { 234 if($this->sp || $this->dry) { 235 if($this->getLocationInfo()) { 236 $event->getLocationInformation(); 237 } 238 239 if(!$this->getUseXml()) { 240 $sEvent = serialize($event); 241 if(!$this->dry) { 242 fwrite($this->sp, $sEvent, strlen($sEvent)); 243 } else { 244 echo "DRY MODE OF SOCKET APPENDER: ".$sEvent; 245 } 246 } else { 247 if(!$this->dry) { 248 fwrite($this->sp, $this->xmlLayout->format($event)); 249 } else { 250 echo "DRY MODE OF SOCKET APPENDER: ".$this->xmlLayout->format($event); 251 } 252 } 253 254 // not sure about it... 255 if(!$this->dry) { 256 fflush($this->sp); 257 } 258 } 259 } 260} 261