Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 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
}