diff options
-rw-r--r-- | appinfo/application.php | 9 | ||||
-rw-r--r-- | middleware/checkmiddleware.php | 5 | ||||
-rw-r--r-- | utility/normalizer.php | 167 | ||||
-rw-r--r-- | utility/smarterlogger.php | 154 |
4 files changed, 203 insertions, 132 deletions
diff --git a/appinfo/application.php b/appinfo/application.php index ec5dc64a..cffc0929 100644 --- a/appinfo/application.php +++ b/appinfo/application.php @@ -28,6 +28,7 @@ use OCA\GalleryPlus\Middleware\SharingCheckMiddleware; use OCA\GalleryPlus\Middleware\TokenCheckMiddleware; use OCA\GalleryPlus\Middleware\SessionMiddleware; use OCA\GalleryPlus\Utility\SmarterLogger; +use OCA\GalleryPlus\Utility\Normalizer; /** @@ -142,10 +143,16 @@ class Application extends App { } ); $container->registerService( + 'Normalizer', function (IAppContainer $c) { + return new Normalizer(); + } + ); + $container->registerService( 'SmarterLogger', function (IAppContainer $c) { return new SmarterLogger( $c->query('AppName'), - $c->query('Logger') + $c->query('Logger'), + $c->query('Normalizer') ); } ); diff --git a/middleware/checkmiddleware.php b/middleware/checkmiddleware.php index 7d2e2b0c..4f4a7de7 100644 --- a/middleware/checkmiddleware.php +++ b/middleware/checkmiddleware.php @@ -84,10 +84,9 @@ abstract class CheckMiddleware extends Middleware { $code = $exception->getCode(); $this->logger->debug( - "[TokenCheckException] {message} ({code})", + "[TokenCheckException] {exception}", array( - 'message' => $message, - 'code' => $code + 'exception' => $exception, ) ); diff --git a/utility/normalizer.php b/utility/normalizer.php new file mode 100644 index 00000000..287345c6 --- /dev/null +++ b/utility/normalizer.php @@ -0,0 +1,167 @@ +<?php +/** + * ownCloud - galleryplus + * + * This file is licensed under the Affero General Public License version 3 or + * later. See the COPYING file. + * + * @author Olivier Paroz <owncloud@interfasys.ch> + * @author Jordi Boggiano <j.boggiano@seld.be> + * + * @copyright Olivier Paroz 2015 + * @copyright Jordi Boggiano 2014-2015 + */ + +namespace OCA\GalleryPlus\Utility; + +/** + * Lets us call the main logger without having to add the context at every + * request + * + * @package OCA\GalleryPlus\Utility + */ +class Normalizer { + + /** + * Converts Objects, Arrays and Exceptions to String + * + * @param $data + * @param int $depth + * + * @return string|array + */ + public function normalize($data, $depth = 0) { + if (null === $data || is_scalar($data)) { + /*// utf8_encode only works for Latin1, we may have ANSI strings + if (is_string($data)) { + $data = mb_convert_encoding($data, "UTF-8"); + }*/ + + return $data; + } + + $traversable = $this->normalizeTraversable($data, $depth); + if ($traversable) { + return $traversable; + } + + $object = $this->normalizeObject($data, $depth); + if ($object) { + return $object; + } + + $resource = $this->normalizeResource($data); + if ($resource) { + return $resource; + } + + return '[unknown(' . gettype($data) . ')]'; + } + + /** + * Converts each element of a traversable variable to String + * + * @param $data + * @param int $depth + * + * @return array|null + */ + private function normalizeTraversable($data, $depth = 0) { + if (is_array($data) || $data instanceof \Traversable) { + $maxArrayRecursion = 20; // + $normalized = array(); + $count = 1; + + foreach ($data as $key => $value) { + if ($count++ >= $maxArrayRecursion) { + $normalized['...'] = + 'Over ' + . $maxArrayRecursion + . ' items, aborting normalization'; + break; + } + $normalized[$key] = $this->normalize($value, $depth); + } + + return $normalized; + } + + return null; + } + + /** + * Converts an Object to String + * + * @param mixed $data + * @param int $depth + * + * @return array|null + */ + private function normalizeObject($data, $depth) { + if (is_object($data)) { + if ($data instanceof \Exception) { + return $this->normalizeException($data); + } + + // We don't need to go too deep in the recursion + $maxObjectRecursion = 2; + $response = $data; + $arrayObject = new \ArrayObject($data); + $serializedObject = $arrayObject->getArrayCopy(); + + if ($depth < $maxObjectRecursion) { + $depth++; + $response = $this->normalize($serializedObject, $depth); + } + + // Don't convert to json here as we would double encode + return array( + sprintf("[object] (%s)", get_class($data)), + $response + ); + } + + return null; + } + + /** + * Converts an Exception to String + * + * @param \Exception $exception + * + * @return string + */ + private function normalizeException(\Exception $exception) { + $data = array( + 'class' => get_class($exception), + 'message' => $exception->getMessage(), + 'code' => $exception->getCode(), + 'file' => $exception->getFile() . ':' . $exception->getLine(), + ); + $trace = $exception->getTraceAsString(); + $data['trace'][] = $trace; + + $previous = $exception->getPrevious(); + if ($previous) { + $data['previous'] = $this->normalizeException($previous); + } + + return $data; + } + + /** + * Converts a resource to a String + * + * @param $data + * + * @return string|null + */ + private function normalizeResource($data) { + if (is_resource($data)) { + return "[resource] " . substr((string)$data, 0, 40); + } + + return null; + } + +}
\ No newline at end of file diff --git a/utility/smarterlogger.php b/utility/smarterlogger.php index 4cc2e11c..4899b18e 100644 --- a/utility/smarterlogger.php +++ b/utility/smarterlogger.php @@ -6,12 +6,8 @@ * later. See the COPYING file. * * @author Olivier Paroz <owncloud@interfasys.ch> - * @author Bart Visscher <bartv@thisnet.nl> - * @author Jordi Boggiano <j.boggiano@seld.be> * * @copyright Olivier Paroz 2015 - * @copyright Bart Visscher 2013-2015 - * @copyright Jordi Boggiano 2014-2015 */ namespace OCA\GalleryPlus\Utility; @@ -22,7 +18,7 @@ use OCP\ILogger; * Lets us call the main logger without having to add the context at every * request * - * @package OCA\GalleryPlus\Middleware + * @package OCA\GalleryPlus\Utility */ class SmarterLogger implements ILogger { @@ -30,19 +26,26 @@ class SmarterLogger implements ILogger { * @type ILogger */ private $logger; + /** + * @type Normalizer + */ + private $normalizer; /*** * Constructor * * @param string $appName * @param ILogger $logger + * @param Normalizer $normalizer */ public function __construct( $appName, - ILogger $logger + ILogger $logger, + Normalizer $normalizer ) { $this->appName = $appName; $this->logger = $logger; + $this->normalizer = $normalizer; } /** @@ -143,7 +146,8 @@ class SmarterLogger implements ILogger { } /** - * Normalises a message and logs it with an arbitrary level. + * Converts the received log message to string before sending it to the + * ownCloud logger * * @param mixed $level * @param string $message @@ -152,140 +156,34 @@ class SmarterLogger implements ILogger { * @return mixed */ public function log($level, $message, array $context = array()) { - // 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; - } - - // interpolate replacement values into the message and return - $message = strtr($message, $replace); - - $this->logger->log( - $level, $message, - array( - 'app' => $this->appName - ) - ); - - } + array_walk($context, [$this, 'contextNormalizer']); - /** - * Converts Objects, Arrays and Exceptions to String - * - * @param $data - * - * @return string - */ - private function normalize($data) { - if (null === $data || is_scalar($data)) { - return $data; + if (!isset($context['app'])) { + $context['app'] = $this->appName; } - if ($this->normalizeTraversable($data)) { - return $this->normalizeTraversable($data); - } - - if ($this->normalizeObject($data)) { - return $this->normalizeObject($data); - } - - if (is_resource($data)) { - return '[resource]'; - } - - return '[unknown(' . gettype($data) . ')]'; + $this->logger->log($level, $message, $context); } /** - * Converts a traversable variable to String + * Normalises the context parameters and JSON encodes and cleans up the + * result * - * @param $data - * - * @return string - */ - private function normalizeTraversable($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); - } - - return null; - } - - /** - * Converts an Object to String + * @todo: could maybe do a better job removing slashes * - * @param $data + * @param array $data * * @return string */ - private function normalizeObject($data) { - 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) + private function contextNormalizer(&$data) { + $data = $this->normalizer->normalize($data); + if (!is_string($data)) { + $data = @json_encode( + $data, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE ); + // Removing null byte and double slashes from object properties + $data = str_replace(['\\u0000', '\\\\'], ["", "\\"], $data); } - - return null; } - /** - * Converts an Exception to String - * - * @param \Exception $exception - * - * @return string - */ - private function normalizeException(\Exception $exception) { - $data = array( - 'class' => get_class($exception), - 'message' => $exception->getMessage(), - 'file' => $exception->getFile() . ':' . $exception->getLine(), - ); - $trace = $exception->getTraceAsString(); - $data['trace'][] = $trace; - - $previous = $exception->getPrevious(); - if ($previous) { - $data['previous'] = $this->normalizeException($previous); - } - - return $this->toJson($data); - } - - /** - * JSON encodes data - * - * @param $data - * - * @return string - */ - private function toJson($data) { - // suppress json_encode errors since it's twitchy with some inputs - return @json_encode( - $data, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE - ); - } }
\ No newline at end of file |