From dd1fbe7b54344683ca9d74366c398d23c5b4608c Mon Sep 17 00:00:00 2001 From: Ryan Rathsam Date: Mon, 8 Feb 2021 16:54:03 -0500 Subject: [PATCH 1/2] Updating the logging code to not throw away all class information We ran into a problem described in this PR: https://github.com/ubccr/xdmod/pull/1490 After some research I found that the root of the problem is this function json_encode'ing `$record` when the contents of `$record` may contain objects that do not support `JsonSerializable` but that do implement `toString()`. After a conversation w/ Joe it's been decided that our Logging API will be to support the logging of arrays w/ objects that implement a `toString()` function. The eagle-eyed may notice that this solution differs from the one I put forth in the above PR. The reason being that the original solution only supported the use case of having an array w/ top level value objects and would not work as expected if a nested array is supplied with an object that implements `toString()`. --- classes/CCR/Logger.php | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/classes/CCR/Logger.php b/classes/CCR/Logger.php index ed519bc392..2a96eac45e 100644 --- a/classes/CCR/Logger.php +++ b/classes/CCR/Logger.php @@ -44,8 +44,28 @@ public function addRecord($level, $message, array $context = array()) protected function extractMessage($record) { if (is_array($record)) { - return json_encode($record); + return json_encode($this->recursivelyStringifyObjects($record)); } return json_encode(array('message' => $record)); } + + /** + * This function recursively iterates over the provided $array keys and values. If a value is an object it replaces + * the object with it's cast string value. + * + * @param array $array The array to be recursively iterated over + * + * @return array returns the provided $array w/ any object values cast to strings. + */ + protected function recursivelyStringifyObjects(&$array) + { + while (list($key, $value) = each($array)) { + if (is_object($value)) { + $array[$key] = (string) $value; + } elseif (is_array($value)) { + $array[$key] = $this->recursivelyStringifyObjects($value); + } + } + return $array; + } } From f30bdc67bfd3ebb078fae11eea47a25fd3d73e1c Mon Sep 17 00:00:00 2001 From: Ryan Rathsam Date: Tue, 9 Feb 2021 15:54:44 -0500 Subject: [PATCH 2/2] Adding Additional Documentation Per @jpwhite4, it's important that we document that our Logger supports logging both strings and arrays, and if an array is provided that contains objects, those objects will be converted to strings via the `__toString` function. --- classes/CCR/Logger.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/classes/CCR/Logger.php b/classes/CCR/Logger.php index 2a96eac45e..0c3994a9a8 100644 --- a/classes/CCR/Logger.php +++ b/classes/CCR/Logger.php @@ -9,6 +9,9 @@ * messages while still utilizing Monolog but this will only be the case for loggers retrieved from CCR\Log::factory|singleton * or if code instantiates this class directly. * + * Note: This logger supports string and array "messages". If an array is provided that contains objects, then this class + * will use the __toString() function to convert the object to a string. + * * @package CCR */ class Logger extends \Monolog\Logger implements LoggerInterface