diff options
-rw-r--r-- | lib/private/log.php | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/lib/private/log.php b/lib/private/log.php index 021cc1578a7..86e9533647a 100644 --- a/lib/private/log.php +++ b/lib/private/log.php @@ -1,6 +1,8 @@ <?php /** * Copyright (c) 2013 Bart Visscher <bartv@thisnet.nl> + * Copyright (c) 2014 Jordi Boggiano <j.boggiano@seld.be> + * Copyright (c) 2014 Olivier Paroz <owncloud@oparoz.com> * This file is licensed under the Affero General Public License version 3 or * later. * See the COPYING-README file. @@ -147,6 +149,8 @@ class Log implements ILogger { // interpolate $message as defined in PSR-3 $replace = array(); foreach ($context as $key => $val) { + // Allows us to dump arrays, objects and exceptions to the log + $val = $this->normalize($val); $replace['{' . $key . '}'] = $val; } @@ -156,4 +160,78 @@ class Log implements ILogger { $logger = $this->logger; call_user_func(array($logger, 'write'), $app, $message, $level); } + + private function normalize($data) { + if (null === $data || is_scalar($data)) { + return $data; + } + + if (is_array($data) || $data instanceof \Traversable) { + $normalized = array(); + $count = 1; + foreach ($data as $key => $value) { + if ($count++ >= 1000) { + $normalized['...'] = 'Over 1000 items, aborting normalization'; + break; + } + $normalized[$key] = $this->normalize($value); + } + + //return $normalized; + return $this->toJson($normalized, true); + } + + if (is_object($data)) { + if ($data instanceof \Exception) { + return $this->normalizeException($data); + } + + $arrayObject = new \ArrayObject($data); + $serializedObject = $arrayObject->getArrayCopy(); + return sprintf("[object] (%s: %s)", get_class($data), $this->toJson($serializedObject, true)); + } + + if (is_resource($data)) { + return '[resource]'; + } + + return '[unknown(' . gettype($data) . ')]'; + } + + private function normalizeException(\Exception $e) { + $data = array( + 'class' => get_class($e), + 'message' => $e->getMessage(), + 'file' => $e->getFile() . ':' . $e->getLine(), + ); + $trace = $e->getTrace(); + foreach ($trace as $frame) { + if (isset($frame['file'])) { + $data['trace'][] = $frame['file'] . ':' . $frame['line']; + } else { + $data['trace'][] = $this->toJson($frame, true); + } + } + if ($previous = $e->getPrevious()) { + $data['previous'] = $this->normalizeException($previous); + } + + return $this->toJson($data, true); + } + + private function toJson($data, $ignoreErrors = false) { + // suppress json_encode errors since it's twitchy with some inputs + if ($ignoreErrors) { + if (version_compare(PHP_VERSION, '5.4.0', '>=')) { + return @json_encode($data, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE); + } + + return @json_encode($data); + } + if (version_compare(PHP_VERSION, '5.4.0', '>=')) { + return json_encode($data, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE); + } + + return json_encode($data); + } } |