PageRenderTime 26ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 1ms

/lib/google/src/Google/Logger/Abstract.php

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