1 <?php 2 /* 3 * Copyright 2014 Google Inc. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 if (!class_exists('Google_Client')) { 19 require_once dirname(__FILE__) . '/../autoload.php'; 20 } 21 22 /** 23 * Abstract logging class based on the PSR-3 standard. 24 * 25 * NOTE: We don't implement `Psr\Log\LoggerInterface` because we need to 26 * maintain PHP 5.2 support. 27 * 28 * @see https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md 29 */ 30 abstract class Google_Logger_Abstract 31 { 32 /** 33 * Default log format 34 */ 35 const DEFAULT_LOG_FORMAT = "[%datetime%] %level%: %message% %context%\n"; 36 /** 37 * Default date format 38 * 39 * Example: 16/Nov/2014:03:26:16 -0500 40 */ 41 const DEFAULT_DATE_FORMAT = 'd/M/Y:H:i:s O'; 42 43 /** 44 * System is unusable 45 */ 46 const EMERGENCY = 'emergency'; 47 /** 48 * Action must be taken immediately 49 * 50 * Example: Entire website down, database unavailable, etc. This should 51 * trigger the SMS alerts and wake you up. 52 */ 53 const ALERT = 'alert'; 54 /** 55 * Critical conditions 56 * 57 * Example: Application component unavailable, unexpected exception. 58 */ 59 const CRITICAL = 'critical'; 60 /** 61 * Runtime errors that do not require immediate action but should typically 62 * be logged and monitored. 63 */ 64 const ERROR = 'error'; 65 /** 66 * Exceptional occurrences that are not errors. 67 * 68 * Example: Use of deprecated APIs, poor use of an API, undesirable things 69 * that are not necessarily wrong. 70 */ 71 const WARNING = 'warning'; 72 /** 73 * Normal but significant events. 74 */ 75 const NOTICE = 'notice'; 76 /** 77 * Interesting events. 78 * 79 * Example: User logs in, SQL logs. 80 */ 81 const INFO = 'info'; 82 /** 83 * Detailed debug information. 84 */ 85 const DEBUG = 'debug'; 86 87 /** 88 * @var array $levels Logging levels 89 */ 90 protected static $levels = array( 91 self::EMERGENCY => 600, 92 self::ALERT => 550, 93 self::CRITICAL => 500, 94 self::ERROR => 400, 95 self::WARNING => 300, 96 self::NOTICE => 250, 97 self::INFO => 200, 98 self::DEBUG => 100, 99 ); 100 101 /** 102 * @var integer $level The minimum logging level 103 */ 104 protected $level = self::DEBUG; 105 106 /** 107 * @var string $logFormat The current log format 108 */ 109 protected $logFormat = self::DEFAULT_LOG_FORMAT; 110 /** 111 * @var string $dateFormat The current date format 112 */ 113 protected $dateFormat = self::DEFAULT_DATE_FORMAT; 114 115 /** 116 * @var boolean $allowNewLines If newlines are allowed 117 */ 118 protected $allowNewLines = false; 119 120 /** 121 * @param Google_Client $client The current Google client 122 */ 123 public function __construct(Google_Client $client) 124 { 125 $this->setLevel( 126 $client->getClassConfig('Google_Logger_Abstract', 'level') 127 ); 128 129 $format = $client->getClassConfig('Google_Logger_Abstract', 'log_format'); 130 $this->logFormat = $format ? $format : self::DEFAULT_LOG_FORMAT; 131 132 $format = $client->getClassConfig('Google_Logger_Abstract', 'date_format'); 133 $this->dateFormat = $format ? $format : self::DEFAULT_DATE_FORMAT; 134 135 $this->allowNewLines = (bool) $client->getClassConfig( 136 'Google_Logger_Abstract', 137 'allow_newlines' 138 ); 139 } 140 141 /** 142 * Sets the minimum logging level that this logger handles. 143 * 144 * @param integer $level 145 */ 146 public function setLevel($level) 147 { 148 $this->level = $this->normalizeLevel($level); 149 } 150 151 /** 152 * Checks if the logger should handle messages at the provided level. 153 * 154 * @param integer $level 155 * @return boolean 156 */ 157 public function shouldHandle($level) 158 { 159 return $this->normalizeLevel($level) >= $this->level; 160 } 161 162 /** 163 * System is unusable. 164 * 165 * @param string $message The log message 166 * @param array $context The log context 167 */ 168 public function emergency($message, array $context = array()) 169 { 170 $this->log(self::EMERGENCY, $message, $context); 171 } 172 173 /** 174 * Action must be taken immediately. 175 * 176 * Example: Entire website down, database unavailable, etc. This should 177 * trigger the SMS alerts and wake you up. 178 * 179 * @param string $message The log message 180 * @param array $context The log context 181 */ 182 public function alert($message, array $context = array()) 183 { 184 $this->log(self::ALERT, $message, $context); 185 } 186 187 /** 188 * Critical conditions. 189 * 190 * Example: Application component unavailable, unexpected exception. 191 * 192 * @param string $message The log message 193 * @param array $context The log context 194 */ 195 public function critical($message, array $context = array()) 196 { 197 $this->log(self::CRITICAL, $message, $context); 198 } 199 200 /** 201 * Runtime errors that do not require immediate action but should typically 202 * be logged and monitored. 203 * 204 * @param string $message The log message 205 * @param array $context The log context 206 */ 207 public function error($message, array $context = array()) 208 { 209 $this->log(self::ERROR, $message, $context); 210 } 211 212 /** 213 * Exceptional occurrences that are not errors. 214 * 215 * Example: Use of deprecated APIs, poor use of an API, undesirable things 216 * that are not necessarily wrong. 217 * 218 * @param string $message The log message 219 * @param array $context The log context 220 */ 221 public function warning($message, array $context = array()) 222 { 223 $this->log(self::WARNING, $message, $context); 224 } 225 226 /** 227 * Normal but significant events. 228 * 229 * @param string $message The log message 230 * @param array $context The log context 231 */ 232 public function notice($message, array $context = array()) 233 { 234 $this->log(self::NOTICE, $message, $context); 235 } 236 237 /** 238 * Interesting events. 239 * 240 * Example: User logs in, SQL logs. 241 * 242 * @param string $message The log message 243 * @param array $context The log context 244 */ 245 public function info($message, array $context = array()) 246 { 247 $this->log(self::INFO, $message, $context); 248 } 249 250 /** 251 * Detailed debug information. 252 * 253 * @param string $message The log message 254 * @param array $context The log context 255 */ 256 public function debug($message, array $context = array()) 257 { 258 $this->log(self::DEBUG, $message, $context); 259 } 260 261 /** 262 * Logs with an arbitrary level. 263 * 264 * @param mixed $level The log level 265 * @param string $message The log message 266 * @param array $context The log context 267 */ 268 public function log($level, $message, array $context = array()) 269 { 270 if (!$this->shouldHandle($level)) { 271 return false; 272 } 273 274 $levelName = is_int($level) ? array_search($level, self::$levels) : $level; 275 $message = $this->interpolate( 276 array( 277 'message' => $message, 278 'context' => $context, 279 'level' => strtoupper($levelName), 280 'datetime' => new DateTime(), 281 ) 282 ); 283 284 $this->write($message); 285 } 286 287 /** 288 * Interpolates log variables into the defined log format. 289 * 290 * @param array $variables The log variables. 291 * @return string 292 */ 293 protected function interpolate(array $variables = array()) 294 { 295 $template = $this->logFormat; 296 297 if (!$variables['context']) { 298 $template = str_replace('%context%', '', $template); 299 unset($variables['context']); 300 } else { 301 $this->reverseJsonInContext($variables['context']); 302 } 303 304 foreach ($variables as $key => $value) { 305 if (strpos($template, '%'. $key .'%') !== false) { 306 $template = str_replace( 307 '%' . $key . '%', 308 $this->export($value), 309 $template 310 ); 311 } 312 } 313 314 return $template; 315 } 316 317 /** 318 * Reverses JSON encoded PHP arrays and objects so that they log better. 319 * 320 * @param array $context The log context 321 */ 322 protected function reverseJsonInContext(array &$context) 323 { 324 if (!$context) { 325 return; 326 } 327 328 foreach ($context as $key => $val) { 329 if (!$val || !is_string($val) || !($val[0] == '{' || $val[0] == '[')) { 330 continue; 331 } 332 333 $json = @json_decode($val); 334 if (is_object($json) || is_array($json)) { 335 $context[$key] = $json; 336 } 337 } 338 } 339 340 /** 341 * Exports a PHP value for logging to a string. 342 * 343 * @param mixed $value The value to 344 */ 345 protected function export($value) 346 { 347 if (is_string($value)) { 348 if ($this->allowNewLines) { 349 return $value; 350 } 351 352 return preg_replace('/[\r\n]+/', ' ', $value); 353 } 354 355 if (is_resource($value)) { 356 return sprintf( 357 'resource(%d) of type (%s)', 358 $value, 359 get_resource_type($value) 360 ); 361 } 362 363 if ($value instanceof DateTime) { 364 return $value->format($this->dateFormat); 365 } 366 367 if (version_compare(PHP_VERSION, '5.4.0', '>=')) { 368 $options = JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE; 369 370 if ($this->allowNewLines) { 371 $options |= JSON_PRETTY_PRINT; 372 } 373 374 return @json_encode($value, $options); 375 } 376 377 return str_replace('\\/', '/', @json_encode($value)); 378 } 379 380 /** 381 * Converts a given log level to the integer form. 382 * 383 * @param mixed $level The logging level 384 * @return integer $level The normalized level 385 * @throws Google_Logger_Exception If $level is invalid 386 */ 387 protected function normalizeLevel($level) 388 { 389 if (is_int($level) && array_search($level, self::$levels) !== false) { 390 return $level; 391 } 392 393 if (is_string($level) && isset(self::$levels[$level])) { 394 return self::$levels[$level]; 395 } 396 397 throw new Google_Logger_Exception( 398 sprintf("Unknown LogLevel: '%s'", $level) 399 ); 400 } 401 402 /** 403 * Writes a message to the current log implementation. 404 * 405 * @param string $message The message 406 */ 407 abstract protected function write($message); 408 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body